log.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package boots
  2. import (
  3. "fmt"
  4. "go-nc/configs/global"
  5. "go-nc/internal/utils"
  6. "os"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "go.uber.org/zap"
  11. "go.uber.org/zap/zapcore"
  12. "gopkg.in/natefinch/lumberjack.v2"
  13. )
  14. var (
  15. level zapcore.Level // zap 日志等级
  16. options []zap.Option // zap 配置项
  17. )
  18. func InitLog() *zap.Logger {
  19. // 创建根目录
  20. createRootDir()
  21. // 设置日志等级
  22. setLogLevel()
  23. if global.App.Config.Log.ShowLine {
  24. options = append(options, zap.AddCaller())
  25. }
  26. // 初始化 zap
  27. return zap.New(getZapCore(), options...)
  28. }
  29. func createRootDir() {
  30. if ok, _ := utils.PathExists(global.App.Config.Log.RootDir); !ok {
  31. _ = os.Mkdir(global.App.Config.Log.RootDir, os.ModePerm)
  32. }
  33. }
  34. func setLogLevel() {
  35. switch global.App.Config.Log.Level {
  36. case "debug":
  37. level = zap.DebugLevel
  38. options = append(options, zap.AddStacktrace(level))
  39. case "info":
  40. level = zap.InfoLevel
  41. case "warn":
  42. level = zap.WarnLevel
  43. case "error":
  44. level = zap.ErrorLevel
  45. options = append(options, zap.AddStacktrace(level))
  46. case "dpanic":
  47. level = zap.DPanicLevel
  48. case "panic":
  49. level = zap.PanicLevel
  50. case "fatal":
  51. level = zap.FatalLevel
  52. default:
  53. level = zap.InfoLevel
  54. }
  55. }
  56. // 扩展 Zap
  57. func getZapCore() zapcore.Core {
  58. var encoder zapcore.Encoder
  59. // 调整编码器默认配置
  60. encoderConfig := zap.NewProductionEncoderConfig()
  61. encoderConfig.EncodeTime = func(time time.Time, encoder zapcore.PrimitiveArrayEncoder) {
  62. encoder.AppendString("\x1b[34m" + time.Format("["+"2006-01-02 15:04:05.000"+"]") + "\x1b[0m")
  63. }
  64. encoderConfig.EncodeLevel = func(l zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) {
  65. // encoder.AppendString("\x1b[34m" + global.App.Config.App.Env + "." + l.String() + "\x1b[0m")
  66. encoder.AppendString("\x1b[34m ." + l.String() + "\x1b[0m")
  67. }
  68. encoderConfig.EncodeCaller = func(caller zapcore.EntryCaller, encoder zapcore.PrimitiveArrayEncoder) {
  69. // 通过判断空来防止调用时的空指针异常
  70. if caller.Defined {
  71. parts := strings.Split(caller.TrimmedPath(), "/")
  72. file := parts[len(parts)-1]
  73. encoder.AppendString("\x1b[32m" + file + ":" + strconv.Itoa(caller.Line) + "\x1b[0m")
  74. }
  75. }
  76. // 设置编码器
  77. if global.App.Config.Log.Format == "json" {
  78. encoder = zapcore.NewJSONEncoder(encoderConfig)
  79. } else {
  80. encoder = zapcore.NewConsoleEncoder(encoderConfig)
  81. }
  82. return zapcore.NewCore(encoder, getLogWriter(), level)
  83. }
  84. // 使用 lumberjack 作为日志写入器
  85. func getLogWriter() zapcore.WriteSyncer {
  86. file := &lumberjack.Logger{
  87. Filename: global.App.Config.Log.RootDir + "/" + global.App.Config.Log.Filename,
  88. MaxSize: global.App.Config.Log.MaxSize,
  89. MaxBackups: global.App.Config.Log.MaxBackups,
  90. MaxAge: global.App.Config.Log.MaxAge,
  91. Compress: global.App.Config.Log.Compress,
  92. }
  93. consoleWriter := zapcore.Lock(os.Stdout) // 使用控制台输出
  94. // 只输入到日志文件 zapcore.AddSync(file) 为日志文件
  95. // return zapcore.AddSync(file)
  96. // 同时输出到控制台和日志文件
  97. return zapcore.NewMultiWriteSyncer(zapcore.AddSync(file), consoleWriter)
  98. }
  99. // 初始化日志
  100. func InitLogger() *zap.Logger {
  101. // 配置 zap 日志
  102. encoderConfig := zapcore.EncoderConfig{
  103. MessageKey: "message",
  104. LevelKey: "level",
  105. TimeKey: "time",
  106. CallerKey: "caller",
  107. EncodeCaller: zapcore.ShortCallerEncoder,
  108. EncodeTime: customTimeEncoder,
  109. EncodeDuration: zapcore.SecondsDurationEncoder,
  110. EncodeLevel: zapcore.CapitalColorLevelEncoder,
  111. }
  112. config := zap.Config{
  113. Encoding: "console",
  114. Level: zap.NewAtomicLevelAt(zap.DebugLevel),
  115. OutputPaths: getOutputPaths(), // 将日志输出到 stdout 和 sql.log 文件
  116. ErrorOutputPaths: []string{"stderr"},
  117. EncoderConfig: encoderConfig,
  118. }
  119. logger, err := config.Build()
  120. if err != nil {
  121. fmt.Println("日志初始化失败:", err)
  122. return nil
  123. }
  124. defer func() {
  125. _ = logger.Sync()
  126. }()
  127. return logger
  128. }
  129. // customTimeEncoder 自定义时间编码器
  130. func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  131. enc.AppendString(fmt.Sprintf("\x1b[34m[%s]\x1b[0m", t.Format("2006-01-02 15:04:05.000")))
  132. }
  133. // getOutputPaths 获取日志输出路径
  134. func getOutputPaths() []string {
  135. if global.App.Config.Database.Mysql.EnableFileLogWriter {
  136. return []string{"stdout", global.App.Config.Database.Mysql.LogFilename}
  137. }
  138. return []string{"stdout"}
  139. }