log.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package logs
  2. import (
  3. "fmt"
  4. "github.com/coroot/coroot-node-agent/utils/enums"
  5. "github.com/natefinch/lumberjack"
  6. "github.com/sirupsen/logrus"
  7. "log"
  8. "os"
  9. "path"
  10. "path/filepath"
  11. "strings"
  12. "time"
  13. )
  14. const (
  15. defaultTimestamp = "2006-01-02 15:04:05.999"
  16. defaultLogDelimeter = "|"
  17. defaultLogLevel = logrus.ErrorLevel
  18. defaultLogFileSize = 50
  19. // 日志保存天数
  20. defaultMaxAge = 3
  21. // 每天最多保存的日志数量
  22. defaultMaxBackups = 3
  23. )
  24. type LogConfig struct {
  25. Path string
  26. AppInfo string
  27. MaxSize int // 日志文件最大尺寸,单位MB
  28. MaxBackups int // 最多保留的旧日志文件数
  29. MaxAge int // 日志文件保留的最长时间,单位天
  30. // 控制台输出
  31. Console bool
  32. }
  33. // 定义Hook结构体
  34. type FileHook struct {
  35. level logrus.Level
  36. formatter logrus.Formatter
  37. logger *log.Logger
  38. }
  39. func InitLog(level string, config LogConfig) error {
  40. FormatterInit()
  41. if config.Console {
  42. logrus.SetOutput(os.Stdout)
  43. } else {
  44. logrus.SetOutput(&NoOut{})
  45. }
  46. //兜底容错
  47. if level == "" {
  48. level = enums.DefaultLogLevel
  49. }
  50. logrusLevel, err := logrus.ParseLevel(level)
  51. if err == nil {
  52. logrus.SetLevel(logrusLevel)
  53. } else {
  54. logrus.SetLevel(defaultLogLevel)
  55. logrus.WithError(err).Error("log level parse error, use default log level error")
  56. }
  57. logrus.SetFormatter(NewFormatter())
  58. logrus.SetReportCaller(true)
  59. if config.Path == "" {
  60. config.Path = log_config.Path
  61. }
  62. if config.Path == "" {
  63. return fmt.Errorf("config.Path is nil")
  64. }
  65. log_config = config
  66. RegisterLogHook(config)
  67. return nil
  68. }
  69. // 实现Hook接口
  70. func (hook *FileHook) Levels() []logrus.Level {
  71. return logrus.AllLevels[:hook.level+1]
  72. }
  73. func (hook *FileHook) Fire(entry *logrus.Entry) error {
  74. // 将日志消息格式化为字符串
  75. bytes, err := hook.formatter.Format(entry)
  76. hook.logger.Print(string(bytes))
  77. if err != nil {
  78. return fmt.Errorf("failed to format log entry: %v", err)
  79. }
  80. if err != nil {
  81. return fmt.Errorf("failed to write log entry: %v", err)
  82. }
  83. return nil
  84. }
  85. type NoOut struct {
  86. }
  87. func (no *NoOut) Write(p []byte) (n int, err error) {
  88. return 0, nil
  89. }
  90. func RegisterLogHook(logConf LogConfig) {
  91. hooks := make(logrus.LevelHooks)
  92. logrus.StandardLogger().ReplaceHooks(hooks)
  93. // 日志文件最大尺寸,不超过100MB
  94. if logConf.MaxSize > defaultLogFileSize || logConf.MaxSize < 1 {
  95. logConf.MaxSize = defaultLogFileSize
  96. }
  97. // 最多保留的旧日志文件数
  98. if logConf.MaxBackups > defaultMaxBackups || logConf.MaxBackups == 0 {
  99. logConf.MaxBackups = defaultMaxBackups
  100. }
  101. // 日志文件保留的最长时间,单位天
  102. if logConf.MaxAge > defaultMaxAge || logConf.MaxAge == 0 {
  103. logConf.MaxAge = defaultMaxAge
  104. }
  105. for _, val := range logrus.AllLevels {
  106. if val <= logrus.GetLevel() {
  107. fileName := filepath.Join(logConf.Path, logConf.AppInfo+"."+val.String()+".log")
  108. archive := &lumberjack.Logger{
  109. Filename: fileName,
  110. MaxSize: logConf.MaxSize, // 日志文件最大尺寸,单位MB
  111. MaxBackups: logConf.MaxBackups, // 最多保留的旧日志文件数
  112. MaxAge: logConf.MaxAge, // 日志文件保留的最长时间,单位天
  113. LocalTime: true, // 使用本地时间
  114. Compress: true,
  115. }
  116. sysLogger := &log.Logger{}
  117. sysLogger.SetOutput(archive)
  118. hooker := &FileHook{
  119. level: val,
  120. formatter: NewFormatter(),
  121. logger: sysLogger,
  122. }
  123. hooks.Add(hooker)
  124. }
  125. }
  126. }
  127. func FormatterInit() {
  128. logrus.SetFormatter(NewFormatter())
  129. logrus.SetReportCaller(true)
  130. }
  131. func NewFormatter() *MyFormatter {
  132. return &MyFormatter{
  133. Pid: os.Getpid(),
  134. TimestampFormat: defaultTimestamp,
  135. }
  136. }
  137. // Custom log format definition
  138. type MyFormatter struct {
  139. Pid int
  140. TimestampFormat string
  141. }
  142. func (s *MyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
  143. //var callerFun string
  144. var fileInfo string
  145. var entryDataInfo string
  146. for key, val := range entry.Data {
  147. entryDataInfo += fmt.Sprintf(" %s=\"%v\"", key, val)
  148. }
  149. if entry.HasCaller() {
  150. //callerFun = entry.Caller.Function
  151. fileInfo = fmt.Sprintf("%s:%d", path.Base(entry.Caller.File), entry.Caller.Line)
  152. }
  153. timestamp := time.Now().Local().Format(s.TimestampFormat)
  154. msg := fmt.Sprintf("%s|%s|%d|%s] %s%s\n",
  155. timestamp, strings.ToUpper(entry.Level.String()), s.Pid, fileInfo, entry.Message, entryDataInfo)
  156. return []byte(msg), nil
  157. }
  158. var log_config LogConfig
  159. func GetLogConf() LogConfig {
  160. return log_config
  161. }