package logger import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" "os" "sync" ) // Logger 封装后的日志器 type Logger struct { *zap.SugaredLogger opts *Options zap *zap.Logger once sync.Once } var ( globalLogger *Logger globalMutex sync.Mutex ) // NewLogger 创建新的日志器 func NewLogger(opts *Options) *Logger { if opts == nil { opts = DefaultOptions() } // 创建 encoder 配置 encoderConfig := zapcore.EncoderConfig{ TimeKey: "time", LevelKey: "level", NameKey: "logger", CallerKey: "caller", MessageKey: "msg", StacktraceKey: "stacktrace", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.CapitalLevelEncoder, EncodeTime: zapcore.ISO8601TimeEncoder, EncodeDuration: zapcore.SecondsDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, } // 设置 encoder var encoder zapcore.Encoder if opts.Format == "json" { encoder = zapcore.NewJSONEncoder(encoderConfig) } else { encoder = zapcore.NewConsoleEncoder(encoderConfig) } // 设置日志级别 level := parseLogLevel(opts.Level) // 创建 core core := zapcore.NewCore( encoder, getWriteSyncer(opts), level, ) // 创建 zap logger zapLogger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) if opts.Caller { zapLogger = zapLogger.WithOptions(zap.AddCaller()) } logger := &Logger{ SugaredLogger: zapLogger.Sugar(), zap: zapLogger, opts: opts, } return logger } // parseLogLevel 解析日志级别 func parseLogLevel(level LogLevel) zapcore.Level { switch level { case DebugLevel: return zapcore.DebugLevel case InfoLevel: return zapcore.InfoLevel case WarnLevel: return zapcore.WarnLevel case ErrorLevel: return zapcore.ErrorLevel default: return zapcore.InfoLevel } } // getWriteSyncer 获取日志输出 func getWriteSyncer(opts *Options) zapcore.WriteSyncer { if opts.OutputPath == "" { return zapcore.AddSync(os.Stdout) } // 使用 lumberjack 实现日志轮转 lumberJackLogger := &lumberjack.Logger{ Filename: opts.OutputPath, MaxSize: opts.MaxSize, MaxBackups: opts.MaxBackups, MaxAge: opts.MaxAge, Compress: opts.Compress, LocalTime: true, } return zapcore.AddSync(lumberJackLogger) } // InitGlobalLogger 初始化全局日志器 func InitGlobalLogger(opts *Options) { globalMutex.Lock() defer globalMutex.Unlock() globalLogger = NewLogger(opts) } // GetGlobalLogger 获取全局日志器 func GetGlobalLogger() *Logger { if globalLogger == nil { globalMutex.Lock() defer globalMutex.Unlock() if globalLogger == nil { globalLogger = NewLogger(DefaultOptions()) } } return globalLogger } // Sync 刷新日志缓冲区 func (l *Logger) Sync() error { return l.zap.Sync() } // WithFields 添加结构化字段 func (l *Logger) WithFields(fields map[string]interface{}) *Logger { zapFields := make([]zap.Field, 0, len(fields)) for k, v := range fields { zapFields = append(zapFields, zap.Any(k, v)) } newZapLogger := l.zap.With(zapFields...) return &Logger{ SugaredLogger: newZapLogger.Sugar(), zap: newZapLogger, opts: l.opts, } } // WithField 添加单个字段 func (l *Logger) WithField(key string, value interface{}) *Logger { return l.WithFields(map[string]interface{}{key: value}) } // 快捷方法 - 使用全局日志器 func Debug(args ...interface{}) { GetGlobalLogger().Debug(args...) } func Debugf(template string, args ...interface{}) { GetGlobalLogger().Debugf(template, args...) } func Info(args ...interface{}) { GetGlobalLogger().Info(args...) } func Infof(template string, args ...interface{}) { GetGlobalLogger().Infof(template, args...) } func Warn(args ...interface{}) { GetGlobalLogger().Warn(args...) } func Warnf(template string, args ...interface{}) { GetGlobalLogger().Warnf(template, args...) } func Error(args ...interface{}) { GetGlobalLogger().Error(args...) } func Errorf(template string, args ...interface{}) { GetGlobalLogger().Errorf(template, args...) } func Fatal(args ...interface{}) { GetGlobalLogger().Fatal(args...) } func Fatalf(template string, args ...interface{}) { GetGlobalLogger().Fatalf(template, args...) } func Panic(args ...interface{}) { GetGlobalLogger().Panic(args...) } func Panicf(template string, args ...interface{}) { GetGlobalLogger().Panicf(template, args...) } // SyncGlobal 刷新全局日志器缓冲区 func SyncGlobal() error { if globalLogger != nil { return globalLogger.Sync() } return nil }