log_buf.go 4.6 KB

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