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