log_buf.go 5.5 KB

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