log_plugin.go 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package logger
  2. import (
  3. "encoding/json"
  4. stringUtils "eta/eta_mini_ht_api/common/utils/string"
  5. "fmt"
  6. "github.com/beego/beego/v2/core/logs"
  7. "log"
  8. "os"
  9. "path"
  10. "sync"
  11. )
  12. const (
  13. DefalutLogFilePath = "./etalogs"
  14. LogChannelLen = 10000
  15. )
  16. var (
  17. loggerHandler *CustomLogger
  18. logMutex = &sync.Mutex{}
  19. )
  20. type logger struct {
  21. *logs.BeeLogger
  22. filter string
  23. }
  24. type CustomLogger struct {
  25. logs []*logger
  26. }
  27. // Logger interface
  28. type Logger interface {
  29. Info(msg string, v ...interface{})
  30. Warn(msg string, v ...interface{})
  31. Error(msg string, v ...interface{})
  32. }
  33. func Info(msg string, v ...interface{}) {
  34. logMutex.Lock()
  35. defer logMutex.Unlock()
  36. loggerHandler.Info(msg, v...)
  37. }
  38. func Error(msg string, v ...interface{}) {
  39. logMutex.Lock()
  40. defer logMutex.Unlock()
  41. loggerHandler.Error(msg, v...)
  42. }
  43. func Warn(msg string, v ...interface{}) {
  44. logMutex.Lock()
  45. defer logMutex.Unlock()
  46. loggerHandler.Warn(msg, v...)
  47. }
  48. func Debug(msg string, v ...interface{}) {
  49. loggerHandler.Debug(msg, v...)
  50. }
  51. func (c *CustomLogger) Debug(msg string, v ...interface{}) {
  52. for _, appender := range c.logs {
  53. if appender.GetLevel() >= logs.LevelInfo {
  54. appender.Debug(msg, v...)
  55. }
  56. }
  57. }
  58. func (c *CustomLogger) Info(msg string, v ...interface{}) {
  59. for _, appender := range c.logs {
  60. if appender.GetLevel() >= logs.LevelInfo {
  61. appender.Info(msg, v...)
  62. }
  63. }
  64. }
  65. func (c *CustomLogger) Error(msg string, v ...interface{}) {
  66. for _, logger := range c.logs {
  67. if logger.GetLevel() >= logs.LevelError {
  68. logger.Error(msg, v...)
  69. }
  70. }
  71. }
  72. func (c *CustomLogger) Warn(msg string, v ...interface{}) {
  73. for _, logger := range c.logs {
  74. if logger.GetLevel() >= logs.LevelWarning {
  75. logger.Warn(msg, v...)
  76. }
  77. }
  78. }
  79. func init() {
  80. var logCfg logConfig
  81. configFile, err := os.ReadFile("conf/log/log_config.json")
  82. if err != nil {
  83. log.Fatalf("Failed to read log config: %v", err)
  84. }
  85. err = json.Unmarshal(configFile, &logCfg)
  86. if err != nil {
  87. log.Fatalf("Failed to parse log config: %v", err)
  88. }
  89. initLogger(logCfg)
  90. }
  91. var levelTrans = map[string]int{
  92. "emergency": logs.LevelEmergency,
  93. "alert": logs.LevelAlert,
  94. "critical": logs.LevelCritical,
  95. "error": logs.LevelError,
  96. "warn": logs.LevelWarning,
  97. "notice": logs.LevelNotice,
  98. "info": logs.LevelInformational,
  99. "debug": logs.LevelDebug,
  100. }
  101. var terminalType = map[string]string{
  102. "console": logs.AdapterConsole,
  103. "file": logs.AdapterFile,
  104. }
  105. func GetInstance() Logger {
  106. return loggerHandler
  107. }
  108. func initLogger(logCfg logConfig) {
  109. if loggerHandler == nil {
  110. loggerHandler = new(CustomLogger)
  111. }
  112. if stringUtils.IsEmptyOrNil(logCfg.FilePath) {
  113. logCfg.FilePath = DefalutLogFilePath
  114. }
  115. for _, appender := range logCfg.Appenders {
  116. terminalType, ok := terminalType[appender.Type]
  117. if !ok {
  118. fmt.Println("初始化日志执行器失败:{%s},终端类型不支持{type:%s}", appender.FileName, appender.Type)
  119. continue
  120. }
  121. var beeLogger *logs.BeeLogger
  122. if terminalType == logs.AdapterConsole {
  123. beeLogger = logs.NewLogger(LogChannelLen)
  124. err := beeLogger.SetLogger(logs.AdapterConsole)
  125. if err != nil {
  126. fmt.Println("创建日志执行器失败:{%s} %v", appender.FileName, err)
  127. continue
  128. }
  129. } else {
  130. logFile := appender.FileName
  131. os.MkdirAll(logCfg.FilePath, os.ModePerm)
  132. // 打开文件
  133. appender.FileName = path.Join(logCfg.FilePath, logFile)
  134. logProps, err := convertAppenderToLog(&appender)
  135. if err != nil {
  136. fmt.Println("初始化日志执行器失败:{%s} %v", appender.FileName, err)
  137. continue
  138. }
  139. b, _ := json.Marshal(logProps)
  140. beeLogger = logs.NewLogger(LogChannelLen)
  141. err = beeLogger.SetLogger(logs.AdapterFile, string(b))
  142. if err != nil {
  143. fmt.Println("设置日志执行器失败:{%s} %v", appender.FileName, err)
  144. continue
  145. }
  146. beeLogger.EnableFuncCallDepth(true)
  147. }
  148. loggerHandler.logs = append(loggerHandler.logs, &logger{BeeLogger: beeLogger,
  149. filter: appender.Filter})
  150. }
  151. }
  152. // ConvertAppenderToLog 将 appender 结构体转换为 log 结构体
  153. func convertAppenderToLog(a *appender) (*logProps, error) {
  154. lvl, ok := levelTrans[a.Level]
  155. if !ok {
  156. return nil, fmt.Errorf("unknown log level: %s", a.Level)
  157. }
  158. return &logProps{
  159. Prefix: a.Prefix,
  160. FileName: a.FileName,
  161. MaxLines: a.MaxLines,
  162. MaxSize: a.MaxSize,
  163. Daily: a.Daily,
  164. MaxDays: a.MaxDays,
  165. Rotate: a.Rotate,
  166. Level: lvl,
  167. Color: a.Color,
  168. }, nil
  169. }
  170. // logConfig 日志配置
  171. type logConfig struct {
  172. FilePath string `json:"filepath" description:"日志路径"`
  173. Appenders []appender `json:"appenders" description:"日志记录"`
  174. }
  175. // appender beeLogger JSON配置
  176. type appender struct {
  177. Filter string `json:"filter"`
  178. Prefix string `json:"perfix" description:"日志前缀"`
  179. Type string `json:"type" description:"终端类型"`
  180. FileName string `json:"filename" description:"保存的文件名"`
  181. MaxLines int `json:"maxlines" description:"每个文件保存的最大行数,默认值 1000000"`
  182. MaxSize int `json:"maxsize" description:"每个文件保存的最大尺寸,默认值是 1 << 28, //256 MB"`
  183. Daily bool `json:"daily" description:"是否按照每天 logrotate,默认是 true"`
  184. MaxDays int `json:"maxdays" description:"文件最多保存多少天,默认保存 7 天"`
  185. Rotate bool `json:"rotate" description:"是否开启 logrotate,默认是 true"`
  186. Level string `json:"level" description:"日志保存的时候的级别,默认是 Trace 级别"`
  187. Color bool `json:"color" description:"日志是否输出颜色"`
  188. }
  189. // logProps beeLogger 配置
  190. type logProps struct {
  191. Prefix string `json:"perfix" description:"日志前缀"`
  192. FileName string `json:"filename" description:"保存的文件名"`
  193. MaxLines int `json:"maxlines" description:"每个文件保存的最大行数,默认值 1000000"`
  194. MaxSize int `json:"maxsize" description:"每个文件保存的最大尺寸,默认值是 1 << 28, //256 MB"`
  195. Daily bool `json:"daily" description:"是否按照每天 logrotate,默认是 true"`
  196. MaxDays int `json:"maxdays" description:"文件最多保存多少天,默认保存 7 天"`
  197. Rotate bool `json:"rotate" description:"是否开启 logrotate,默认是 true"`
  198. Level int `json:"level" description:"日志保存的时候的级别,默认是 Trace 级别"`
  199. Color bool `json:"color" description:"日志是否输出颜色"`
  200. }