log.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package log
  2. import (
  3. "context"
  4. "github.com/gin-gonic/gin"
  5. "github.com/spf13/viper"
  6. "go.uber.org/zap"
  7. "go.uber.org/zap/zapcore"
  8. "gopkg.in/natefinch/lumberjack.v2"
  9. "os"
  10. "time"
  11. )
  12. const ctxLoggerKey = "zapLogger"
  13. type Logger struct {
  14. *zap.Logger
  15. }
  16. func NewLog(conf *viper.Viper) *Logger {
  17. // log address "out.log" User-defined
  18. lp := conf.GetString("log.log_file_name")
  19. lv := conf.GetString("log.log_level")
  20. var level zapcore.Level
  21. //debug<info<warn<error<fatal<panic
  22. switch lv {
  23. case "debug":
  24. level = zap.DebugLevel
  25. case "info":
  26. level = zap.InfoLevel
  27. case "warn":
  28. level = zap.WarnLevel
  29. case "error":
  30. level = zap.ErrorLevel
  31. default:
  32. level = zap.InfoLevel
  33. }
  34. hook := lumberjack.Logger{
  35. Filename: lp, // Log file path
  36. MaxSize: conf.GetInt("log.max_size"), // Maximum size unit for each log file: M
  37. MaxBackups: conf.GetInt("log.max_backups"), // The maximum number of backups that can be saved for log files
  38. MaxAge: conf.GetInt("log.max_age"), // Maximum number of days the file can be saved
  39. Compress: conf.GetBool("log.compress"), // Compression or not
  40. }
  41. var encoder zapcore.Encoder
  42. if conf.GetString("log.encoding") == "console" {
  43. encoder = zapcore.NewConsoleEncoder(zapcore.EncoderConfig{
  44. TimeKey: "ts",
  45. LevelKey: "level",
  46. NameKey: "Logger",
  47. CallerKey: "caller",
  48. MessageKey: "msg",
  49. StacktraceKey: "stacktrace",
  50. LineEnding: zapcore.DefaultLineEnding,
  51. EncodeLevel: zapcore.LowercaseColorLevelEncoder,
  52. EncodeTime: timeEncoder,
  53. EncodeDuration: zapcore.SecondsDurationEncoder,
  54. EncodeCaller: zapcore.FullCallerEncoder,
  55. })
  56. } else {
  57. encoder = zapcore.NewJSONEncoder(zapcore.EncoderConfig{
  58. TimeKey: "ts",
  59. LevelKey: "level",
  60. NameKey: "logger",
  61. CallerKey: "caller",
  62. FunctionKey: zapcore.OmitKey,
  63. MessageKey: "msg",
  64. StacktraceKey: "stacktrace",
  65. LineEnding: zapcore.DefaultLineEnding,
  66. EncodeLevel: zapcore.LowercaseLevelEncoder,
  67. EncodeTime: zapcore.EpochTimeEncoder,
  68. EncodeDuration: zapcore.SecondsDurationEncoder,
  69. EncodeCaller: zapcore.ShortCallerEncoder,
  70. })
  71. }
  72. core := zapcore.NewCore(
  73. encoder,
  74. zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // Print to console and file
  75. level,
  76. )
  77. if conf.GetString("env") != "prod" {
  78. return &Logger{zap.New(core, zap.Development(), zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
  79. }
  80. return &Logger{zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel))}
  81. }
  82. func timeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
  83. //enc.AppendString(t.Format("2006-01-02 15:04:05"))
  84. enc.AppendString(t.Format("2006-01-02 15:04:05.000000000"))
  85. }
  86. // WithValue Adds a field to the specified context
  87. func (l *Logger) WithValue(ctx context.Context, fields ...zapcore.Field) context.Context {
  88. if c, ok := ctx.(*gin.Context); ok {
  89. ctx = c.Request.Context()
  90. c.Request = c.Request.WithContext(context.WithValue(ctx, ctxLoggerKey, l.WithContext(ctx).With(fields...)))
  91. return c
  92. }
  93. return context.WithValue(ctx, ctxLoggerKey, l.WithContext(ctx).With(fields...))
  94. }
  95. // WithContext Returns a zap instance from the specified context
  96. func (l *Logger) WithContext(ctx context.Context) *Logger {
  97. if c, ok := ctx.(*gin.Context); ok {
  98. ctx = c.Request.Context()
  99. }
  100. zl := ctx.Value(ctxLoggerKey)
  101. ctxLogger, ok := zl.(*zap.Logger)
  102. if ok {
  103. return &Logger{ctxLogger}
  104. }
  105. return l
  106. }