log_buf.go 5.6 KB

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