package logger import ( "context" "path/filepath" "time" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) // LevelLogger 级别分文件日志器 - 基于 Zap 官方推荐 type LevelLogger struct { logger *zap.Logger levelLoggers map[zapcore.Level]*zap.Logger config LevelLoggerConfig } // LevelLoggerConfig 级别分文件日志器配置 type LevelLoggerConfig struct { BaseConfig Config EnableLevelSeparation bool LevelConfigs map[zapcore.Level]LevelFileConfig } // LevelFileConfig 单个级别文件配置 type LevelFileConfig struct { MaxSize int `mapstructure:"max_size"` MaxBackups int `mapstructure:"max_backups"` MaxAge int `mapstructure:"max_age"` Compress bool `mapstructure:"compress"` } // NewLevelLogger 创建级别分文件日志器 func NewLevelLogger(config LevelLoggerConfig) (Logger, error) { // 根据环境创建基础日志器 var baseLogger *zap.Logger var err error if config.BaseConfig.Development { baseLogger, err = zap.NewDevelopment( zap.AddCaller(), zap.AddCallerSkip(1), zap.AddStacktrace(zapcore.ErrorLevel), ) } else { baseLogger, err = zap.NewProduction( zap.AddCaller(), zap.AddCallerSkip(1), zap.AddStacktrace(zapcore.ErrorLevel), ) } if err != nil { return nil, err } // 创建级别分文件的日志器 levelLogger := &LevelLogger{ logger: baseLogger, levelLoggers: make(map[zapcore.Level]*zap.Logger), config: config, } // 为每个级别创建专门的日志器 if config.EnableLevelSeparation { levelLogger.createLevelLoggers() } return levelLogger, nil } // createLevelLoggers 创建各级别的日志器 func (l *LevelLogger) createLevelLoggers() { levels := []zapcore.Level{ zapcore.DebugLevel, zapcore.InfoLevel, zapcore.WarnLevel, zapcore.ErrorLevel, zapcore.FatalLevel, zapcore.PanicLevel, } for _, level := range levels { // 获取该级别的配置 levelConfig, exists := l.config.LevelConfigs[level] if !exists { // 如果没有配置,使用默认配置 levelConfig = LevelFileConfig{ MaxSize: 100, MaxBackups: 5, MaxAge: 30, Compress: true, } } // 创建该级别的文件输出 writeSyncer := l.createLevelWriteSyncer(level, levelConfig) // 创建编码器 encoder := getEncoder(l.config.BaseConfig.Format, l.config.BaseConfig) // 创建 Core core := zapcore.NewCore(encoder, writeSyncer, level) // 创建该级别的日志器 levelLogger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1), zap.AddStacktrace(zapcore.ErrorLevel), ) l.levelLoggers[level] = levelLogger } } // createLevelWriteSyncer 创建级别特定的文件输出同步器 func (l *LevelLogger) createLevelWriteSyncer(level zapcore.Level, config LevelFileConfig) zapcore.WriteSyncer { // 构建文件路径 var logFilePath string if l.config.BaseConfig.UseDaily { // 按日期分包:logs/2024-01-01/debug.log date := time.Now().Format("2006-01-02") levelName := level.String() logFilePath = filepath.Join(l.config.BaseConfig.LogDir, date, levelName+".log") } else { // 传统方式:logs/debug.log levelName := level.String() logFilePath = filepath.Join(l.config.BaseConfig.LogDir, levelName+".log") } // 创建 lumberjack 日志轮转器 rotator := &lumberjack.Logger{ Filename: logFilePath, MaxSize: config.MaxSize, MaxBackups: config.MaxBackups, MaxAge: config.MaxAge, Compress: config.Compress, } return zapcore.AddSync(rotator) } // GetLevelLogger 获取指定级别的日志器 func (l *LevelLogger) GetLevelLogger(level zapcore.Level) *zap.Logger { if logger, exists := l.levelLoggers[level]; exists { return logger } return l.logger } // 实现 Logger 接口 func (l *LevelLogger) Debug(msg string, fields ...zapcore.Field) { if logger := l.GetLevelLogger(zapcore.DebugLevel); logger != nil { logger.Debug(msg, fields...) } } func (l *LevelLogger) Info(msg string, fields ...zapcore.Field) { if logger := l.GetLevelLogger(zapcore.InfoLevel); logger != nil { logger.Info(msg, fields...) } } func (l *LevelLogger) Warn(msg string, fields ...zapcore.Field) { if logger := l.GetLevelLogger(zapcore.WarnLevel); logger != nil { logger.Warn(msg, fields...) } } func (l *LevelLogger) Error(msg string, fields ...zapcore.Field) { if logger := l.GetLevelLogger(zapcore.ErrorLevel); logger != nil { logger.Error(msg, fields...) } } func (l *LevelLogger) Fatal(msg string, fields ...zapcore.Field) { if logger := l.GetLevelLogger(zapcore.FatalLevel); logger != nil { logger.Fatal(msg, fields...) } } func (l *LevelLogger) Panic(msg string, fields ...zapcore.Field) { if logger := l.GetLevelLogger(zapcore.PanicLevel); logger != nil { logger.Panic(msg, fields...) } } func (l *LevelLogger) With(fields ...zapcore.Field) Logger { // 为所有级别添加字段 for level, logger := range l.levelLoggers { l.levelLoggers[level] = logger.With(fields...) } return l } func (l *LevelLogger) WithContext(ctx context.Context) Logger { // 从上下文提取字段 fields := extractFieldsFromContext(ctx) return l.With(fields...) } func (l *LevelLogger) Named(name string) Logger { // 为所有级别添加名称 for level, logger := range l.levelLoggers { l.levelLoggers[level] = logger.Named(name) } return l } func (l *LevelLogger) Sync() error { // 同步所有级别的日志器 for _, logger := range l.levelLoggers { if err := logger.Sync(); err != nil { return err } } return l.logger.Sync() } func (l *LevelLogger) Core() zapcore.Core { return l.logger.Core() } func (l *LevelLogger) GetZapLogger() *zap.Logger { return l.logger }