logger.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package core
  2. import (
  3. "fmt"
  4. rotateLogs "github.com/lestrrat-go/file-rotatelogs"
  5. "go.uber.org/zap"
  6. "go.uber.org/zap/zapcore"
  7. config2 "go_server/base/config"
  8. "io"
  9. "os"
  10. "strings"
  11. "time"
  12. )
  13. const (
  14. DefaultLog string = "app"
  15. )
  16. var (
  17. loggerMap = make(map[string]*zap.Logger)
  18. Log *zap.SugaredLogger
  19. )
  20. func init() {
  21. tags := []string{DefaultLog}
  22. for _, lg := range tags {
  23. loggerMap[lg] = newLogger(lg)
  24. }
  25. Log = loggerMap[DefaultLog].Sugar()
  26. }
  27. func conf() *config2.Zap {
  28. if loggerConfig == nil {
  29. loggerInit()
  30. }
  31. return loggerConfig
  32. }
  33. var loggerConfig *config2.Zap
  34. func loggerInit() {
  35. defaultConf := &config2.Zap{
  36. TagName: "app",
  37. Level: "debug",
  38. Prefix: "AMS_",
  39. Format: "_json",
  40. Director: "logs",
  41. EncodeLevel: "LowercaseLevelEncoder",
  42. StacktraceKey: "error",
  43. MaxAge: 3,
  44. RotationSize: 100,
  45. RotationCount: 3,
  46. ShowLine: true,
  47. LogInConsole: true,
  48. LogOutputFile: true,
  49. }
  50. zapConf := config2.EnvConf().Zap
  51. if zapConf == nil {
  52. loggerConfig = defaultConf
  53. } else {
  54. loggerConfig = zapConf
  55. }
  56. }
  57. type logConfTags struct {
  58. Tag string `json:"tag" yaml:"tag"`
  59. FileName string `json:"filename" yaml:"filename"`
  60. ErrFileName string `json:"errFileName" yaml:"errFileName"`
  61. }
  62. func getWriter(filename string) io.Writer {
  63. // 生成 rotate_logs 的Logger 实际生成的文件名 demo.log.YY mm dd HH
  64. hook, err := rotateLogs.New(
  65. strings.Replace(filename, ".log", "", -1)+".%Y%m%d%H.log",
  66. rotateLogs.WithLinkName(filename),
  67. // 根据文件大小切割日志
  68. rotateLogs.WithRotationSize(1024*1024*conf().LogSignSize()), // 每个日志文件大小设置:100M
  69. rotateLogs.WithRotationTime(time.Minute*1), // 日志轮询周期 默认1分钟:60秒
  70. rotateLogs.WithRotationCount(conf().LogSaveCount()), // 日志保留份数
  71. // 根据时间分割日志
  72. // rotateLogs.WithMaxAge(time.Hour*24*2), // 保存2天日志
  73. )
  74. if err != nil {
  75. panic(err)
  76. }
  77. return hook
  78. }
  79. // 设置日志格式 非json可进行堆栈跟踪
  80. func getEncoder() zapcore.Encoder {
  81. if conf().Format == "json" || conf().Format == "" {
  82. return zapcore.NewJSONEncoder(getEncoderConfig())
  83. }
  84. return zapcore.NewConsoleEncoder(getEncoderConfig())
  85. }
  86. func getEncoderConfig() zapcore.EncoderConfig {
  87. return zapcore.EncoderConfig{
  88. MessageKey: "message",
  89. LevelKey: "level",
  90. EncodeLevel: conf().ZapEncodeLevel(),
  91. TimeKey: "time",
  92. NameKey: "logger",
  93. CallerKey: "caller",
  94. StacktraceKey: conf().StacktraceKey, // "error"
  95. LineEnding: zapcore.DefaultLineEnding,
  96. EncodeTime: customTimeEncoder,
  97. EncodeDuration: zapcore.SecondsDurationEncoder,
  98. EncodeCaller: zapcore.ShortCallerEncoder,
  99. }
  100. }
  101. func customTimeEncoder(t time.Time, encoder zapcore.PrimitiveArrayEncoder) {
  102. encoder.AppendString(t.Format("2006/01/02-15:04:05.000"))
  103. }
  104. func NewLogger(tag string, args ...interface{}) *zap.Logger {
  105. if loggerMap[tag] != nil {
  106. return loggerMap[tag]
  107. }
  108. return newLogger(tag, args...)
  109. }
  110. func newLogger(tag string, args ...interface{}) *zap.Logger {
  111. savePath := fmt.Sprintf("./%s/", conf().Director)
  112. if len(args) > 0 {
  113. savePath = fmt.Sprintf("./%s/", args[0])
  114. }
  115. tagConf := logConfTags{Tag: tag, FileName: fmt.Sprintf("%s.log", tag),
  116. ErrFileName: fmt.Sprintf("%s_err.log", tag)}
  117. encoder := getEncoder()
  118. infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
  119. return lvl >= conf().TransportLevel()
  120. })
  121. errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
  122. return lvl >= zapcore.ErrorLevel
  123. })
  124. // 获取 info、error日志文件的io.Writer 抽象 getWriter() 在下方实现
  125. infoWriter := getWriter(savePath + tagConf.FileName)
  126. errorWriter := getWriter(savePath + tagConf.ErrFileName)
  127. cores := make([]zapcore.Core, 0)
  128. if conf().LogOutputFile {
  129. cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel))
  130. cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(errorWriter), errorLevel))
  131. }
  132. if conf().LogInConsole {
  133. cores = append(cores, zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), infoLevel))
  134. }
  135. // 最后创建具体的Logger
  136. core := zapcore.NewTee(cores...)
  137. // 开启开发模式,堆栈跟踪
  138. //caller := zap.AddCaller()
  139. // config.DisableCaller = true // 禁用调用者信息(代码行)
  140. development := zap.Development()
  141. filed := zap.Fields(zap.String("Tag", string(tagConf.Tag)))
  142. stackTrace := zap.AddStacktrace(zap.ErrorLevel) // 当错误等级error时 触发堆栈跟踪
  143. log := zap.New(core, stackTrace, development, filed) // caller,
  144. if conf().ShowLine {
  145. log = log.WithOptions(zap.AddCaller())
  146. }
  147. loggerMap[tagConf.Tag] = log
  148. return loggerMap[tagConf.Tag]
  149. }