log_buf.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // package log_buf -- потокобезопасный буфер лога.
  2. package log_buf
  3. import (
  4. "fmt"
  5. "log"
  6. "sync"
  7. "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers"
  8. mKs "gitp78su.ipnodns.ru/svi/kern/v4/lev0/kspec"
  9. "gitp78su.ipnodns.ru/svi/kern/v4/lev1/log_msg"
  10. )
  11. var (
  12. hassert = helpers.Hassert
  13. )
  14. // LogBufParam -- параметры логирующего буфера
  15. type LogBufParam struct {
  16. Prefix_ string // Префикс для сообщений
  17. IsTerm_ mKs.ISafeBool // Признак вывода в терминал
  18. }
  19. // SelfCheck -- проверяет корректность параметров.
  20. func (sf *LogBufParam) SelfCheck() {
  21. hassert(sf.IsTerm_ != nil, "LogBufParam.SelfCheck(): IsTerm_==nil")
  22. }
  23. // LogBuf -- потокобезопасный буфер лога.
  24. type LogBuf struct {
  25. sync.RWMutex
  26. *LogBufParam
  27. lst []mKs.ILogMsg
  28. lstErr []mKs.ILogMsg
  29. }
  30. // NewLogBuf -- возвращает новый потокобезопасный буфер лога.
  31. func NewLogBuf(param *LogBufParam) mKs.ILogBuf {
  32. hassert(param != nil, "NewLogBuf(): param=nil")
  33. param.SelfCheck()
  34. sf := &LogBuf{
  35. LogBufParam: param,
  36. lst: []mKs.ILogMsg{},
  37. lstErr: []mKs.ILogMsg{},
  38. }
  39. sf.Prefix_ += "."
  40. return sf
  41. }
  42. // IsTerm -- возвращает признак логирования.
  43. func (sf *LogBuf) IsTerm() mKs.ISafeBool {
  44. return sf.IsTerm_
  45. }
  46. // GetErr -- возвращает сообщение ошибки по номеру.
  47. func (sf *LogBuf) GetErr(num int) mKs.ILogMsg {
  48. sf.RLock()
  49. defer sf.RUnlock()
  50. if len(sf.lstErr) == 0 {
  51. return log_msg.NewLogMsg(log_msg.DEBUG, sf.Prefix_+"not error msg")
  52. }
  53. if num >= len(sf.lstErr) {
  54. return sf.lstErr[len(sf.lstErr)-1]
  55. }
  56. if num <= 0 {
  57. return sf.lstErr[0]
  58. }
  59. return sf.lstErr[num]
  60. }
  61. // Get -- возвращает сообщение по номеру.
  62. func (sf *LogBuf) Get(num int) mKs.ILogMsg {
  63. sf.RLock()
  64. defer sf.RUnlock()
  65. if len(sf.lst) == 0 {
  66. return log_msg.NewLogMsg(log_msg.DEBUG, sf.Prefix_+"*no msg*")
  67. }
  68. if num >= len(sf.lst) {
  69. return log_msg.NewLogMsg(log_msg.DEBUG, sf.Prefix_+"*no msg*")
  70. }
  71. if num <= 0 {
  72. return log_msg.NewLogMsg(log_msg.DEBUG, sf.Prefix_+"*no msg*")
  73. }
  74. return sf.lst[num]
  75. }
  76. type tMsg struct {
  77. text string
  78. args []any
  79. }
  80. // Debug -- сообщение отладки.
  81. func (sf *LogBuf) Debug(fMsg string, args ...any) {
  82. sf.Lock()
  83. defer sf.Unlock()
  84. msg := tMsg{
  85. text: fMsg,
  86. args: args,
  87. }
  88. strMsg := fmt.Sprintf(msg.text, msg.args...)
  89. _msg := log_msg.NewLogMsg(log_msg.DEBUG, sf.Prefix_+strMsg)
  90. sf.lst = append(sf.lst, _msg)
  91. sf.checkLen()
  92. sf.printTerm(_msg)
  93. }
  94. // Info -- информационные сообщения.
  95. func (sf *LogBuf) Info(fMsg string, args ...any) {
  96. sf.Lock()
  97. defer sf.Unlock()
  98. msg := tMsg{
  99. text: fMsg,
  100. args: args,
  101. }
  102. strMsg := fmt.Sprintf(msg.text, msg.args...)
  103. _msg := log_msg.NewLogMsg(log_msg.INFO, sf.Prefix_+strMsg)
  104. sf.lst = append(sf.lst, _msg)
  105. sf.checkLen()
  106. sf.printTerm(_msg)
  107. }
  108. // Warn -- предупреждающие сообщения.
  109. func (sf *LogBuf) Warn(fMsg string, args ...any) {
  110. sf.Lock()
  111. defer sf.Unlock()
  112. msg := tMsg{
  113. text: fMsg,
  114. args: args,
  115. }
  116. strMsg := fmt.Sprintf(msg.text, msg.args...)
  117. _msg := log_msg.NewLogMsg(log_msg.WARN, sf.Prefix_+strMsg)
  118. sf.lst = append(sf.lst, _msg)
  119. sf.checkLen()
  120. sf.printTerm(_msg)
  121. }
  122. // Err -- сообщения об ошибках.
  123. func (sf *LogBuf) Err(fMsg string, args ...any) {
  124. sf.Lock()
  125. defer sf.Unlock()
  126. msg := tMsg{
  127. text: fMsg,
  128. args: args,
  129. }
  130. strMsg := fmt.Sprintf(msg.text, msg.args...)
  131. _msg := log_msg.NewLogMsg(log_msg.ERROR, sf.Prefix_+strMsg)
  132. sf.lst = append(sf.lst, _msg)
  133. sf.lstErr = append(sf.lstErr, _msg)
  134. sf.checkLen()
  135. sf.checkLenErr()
  136. sf.printTerm(_msg)
  137. }
  138. // Size -- возвращает размер буфера.
  139. func (sf *LogBuf) Size() int {
  140. sf.RLock()
  141. defer sf.RUnlock()
  142. return len(sf.lst)
  143. }
  144. // Проверяет длину общую лога.
  145. func (sf *LogBuf) checkLen() {
  146. for len(sf.lst) > 100 {
  147. sf.lst = sf.lst[1:]
  148. }
  149. }
  150. // Проверяет длину лога ошибок.
  151. func (sf *LogBuf) checkLenErr() {
  152. for len(sf.lstErr) > 100 {
  153. sf.lstErr = sf.lstErr[1:]
  154. }
  155. }
  156. // Печатает сообщение в терминал, если разрешено.
  157. func (sf *LogBuf) printTerm(msg mKs.ILogMsg) {
  158. if !sf.IsTerm_.Get() {
  159. return
  160. }
  161. level := msg.Level()
  162. if helpers.IsStageProd {
  163. switch level.Get() {
  164. case "ERRO", "WARN":
  165. log.Printf("%v %v\n", level, msg.String())
  166. default:
  167. return
  168. }
  169. }
  170. log.Printf("%v\n", msg.String())
  171. }