log.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. package log
  2. import (
  3. "fmt"
  4. "github.com/gin-gon
  5. "github.com/gin-gonic/gin"
  6. "github.com/spf13/viper"
  7. "go.uber.org/zap"
  8. "fmt"
  9. "gopkg.in/natefinch/lumberjack.v2"
  10. "os"
  11. "path/filepath"
  12. "time"
  13. )
  14. const LOGGER_KEY = "zapLogger"
  15. type Logger struct {
  16. *zap.Logger
  17. }
  18. func NewLog(conf *viper.Viper) *Logger {
  19. return initZap(conf)
  20. }
  21. func initZap(conf *viper.Viper) *Logger {
  22. // 日志地址 "out.log" 自定义
  23. lp := conf.GetString("log.log_file_name")
  24. // 日志级别 DEBUG,ERROR, INFO
  25. lv := conf.GetString("log.log_level")
  26. var level zapcore.Level
  27. //debug<info<warn<error<fatal<panic
  28. switch lv {
  29. case "debug":
  30. level = zap.DebugLevel
  31. case "info":
  32. level = zap.InfoLevel
  33. case "warn":
  34. level = zap.WarnLevel
  35. case "error":
  36. level = zap.ErrorLevel
  37. default:
  38. level = zap.InfoLevel
  39. }
  40. // 在设置lumberjack.Logger之前,先获取日志文件的目录,并使用os.MkdirAll来创建它
  41. // 这样可以确保日志目录存在,避免因目录不存在而导致日志写入失败的问题
  42. logDir := filepath.Dir(lp)
  43. if err := os.MkdirAll(logDir, os.ModePerm); err != nil {
  44. panic(fmt.Sprintf("create log dir '%s' err: %s", logDir, err))
  45. }
  46. hook := lumberjack.Logger{
  47. Filename: lp, // 日志文件路径
  48. MaxSize: conf.GetInt("log.max_size"), // 每个日志文件保存的最大尺寸 单位:M
  49. MaxBackups: conf.GetInt("log.max_backups"), // 日志文件最多保存多少个备份
  50. MaxAge: conf.GetInt("log.max_age"), // 文件最多保存多少天
  51. Compress: conf.GetBool("log.compress"), // 是否压缩
  52. }
  53. var encoder zapcore.Encoder
  54. if conf.GetString("log.encoding") == "console" {
  55. encoder = zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
  56. TimeKey: "ts",
  57. LevelKey: "level",
  58. NameKey: "Logger",
  59. CallerKey: "caller",
  60. MessageKey: "msg",
  61. StacktraceKey: "stacktrace",
  62. LineEnding: zapcore.DefaultLineEnding,
  63. EncodeLevel: zapcore.LowercaseColorLevelEncoder,
  64. EncodeTime: timeEncoder,
  65. EncodeDuration: zapcore.SecondsDurationEncoder,
  66. EncodeCaller: zapcore.FullCallerEncoder,
  67. })
  68. } else {
  69. encoder = zapcore.NewJSONEncoder(zapcore.EncoderConfig{
  70. TimeKey: "ts",
  71. LevelKey: "level",
  72. NameKey: "logger",
  73. CallerKey: "caller",
  74. FunctionKey: zapcore.OmitKey,
  75. MessageKey: "msg",
  76. StacktraceKey: "stacktrace",
  77. LineEnding: zapcore.DefaultLineEnding,
  78. EncodeLevel: zapcore.LowercaseLevelEncoder,
  79. EncodeTime: zapcore.EpochTimeEncoder,
  80. EncodeDuration: zapcore.SecondsDurationEncoder,
  81. EncodeCaller: zapcore.ShortCallerEncoder,
  82. })
  83. }
  84. core := zapcore.NewCore(
  85. encoder, // 编码器配置
  86. zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
  87. level, // 日志级别
  88. )
  89. if conf.GetString("env") != "prod" {
  90. return &Logger{zap.New(core, zap.Development(), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
  91. }
  92. return &Logger{zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
  93. }
  94. // 自定义时间编码器
  95. func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  96. //enc.AppendString(t.Format("2006-01-02 15:04:05"))
  97. enc.AppendString(t.Format("2006-01-02 15:04:05.000000000"))
  98. }
  99. // NewContext 给指定的context添加字段
  100. func (l *Logger) NewContext(ctx *gin.Context, fields ...zapcore.Field) {
  101. ctx.Set(LOGGER_KEY, l.WithContext(ctx).With(fields...))
  102. }
  103. // WithContext 从指定的context返回一个zap实例
  104. func (l *Logger) WithContext(ctx *gin.Context) *Logger {
  105. if ctx == nil {
  106. return l
  107. }
  108. zl, _ := ctx.Get(LOGGER_KEY)
  109. ctxLogger, ok := zl.(*zap.Logger)
  110. if ok {
  111. return &Logger{ctxLogger}
  112. }
  113. return l
  114. }