package config import ( "fmt" "os" "sync" "time" fiberZap "github.com/gofiber/contrib/v3/zap" "github.com/gofiber/fiber/v3/log" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) var ( mu sync.Mutex currentDay = make(map[string]string) currentSync = make(map[string]zapcore.WriteSyncer) ) func initLogger() { dynamicLevel := zap.NewAtomicLevel() dynamicLevel.SetLevel(LogLevel()) logger := fiberZap.NewLogger(fiberZap.LoggerConfig{ ExtraKeys: []string{"request_id"}, ZapOptions: []zap.Option{ zap.AddCaller(), // 打开 caller zap.AddCallerSkip(2), // 跳过一层 Fiber 调用 }, CoreConfigs: []fiberZap.CoreConfig{ { Encoder: zapcore.NewConsoleEncoder(consoleEncoderConfig()), WriteSyncer: zapcore.AddSync(os.Stdout), LevelEncoder: dynamicLevel, }, { Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/debug", conf.Log.Dir)), LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev == zap.DebugLevel }), }, { Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/info", conf.Log.Dir)), LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev == zap.InfoLevel }), }, { Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/warn", conf.Log.Dir)), LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev == zap.WarnLevel }), }, { Encoder: zapcore.NewJSONEncoder(humanEncoderConfig()), WriteSyncer: getWriteSyncer(fmt.Sprintf("%s/error", conf.Log.Dir)), LevelEncoder: zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev >= zap.ErrorLevel }), }, }, }) log.SetLogger(logger) // 退出时同步日志 defer func() { _ = logger.Sync() }() } func getWriteSyncer(basePath string) zapcore.WriteSyncer { mu.Lock() defer mu.Unlock() today := time.Now().Format("2006-01-02") if day, ok := currentDay[basePath]; !ok || day != today { currentDay[basePath] = today file := fmt.Sprintf("%s/%s.log", basePath, today) currentSync[basePath] = zapcore.AddSync(&lumberjack.Logger{ Filename: file, MaxSize: conf.Log.MaxSize, MaxBackups: conf.Log.MaxBackups, MaxAge: conf.Log.MaxAge, Compress: conf.Log.Compress, LocalTime: true, }) } return currentSync[basePath] } func LogLevel() zapcore.Level { level := conf.Log.Level switch level { case "trace": return zapcore.DebugLevel case "debug": return zapcore.DebugLevel case "info": return zapcore.InfoLevel case "warn": return zapcore.WarnLevel case "error": return zapcore.ErrorLevel case "dpanic": return zapcore.DPanicLevel case "panic": return zapcore.PanicLevel case "fatal": return zapcore.FatalLevel default: return zapcore.InfoLevel } } func consoleEncoderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ MessageKey: "msg", LevelKey: "level", TimeKey: "ts", EncodeTime: customTimeEncoder, EncodeLevel: zapcore.CapitalColorLevelEncoder, EncodeCaller: zapcore.ShortCallerEncoder, } } func humanEncoderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ MessageKey: "message", LevelKey: "level", NameKey: "mame", TimeKey: "ts", CallerKey: "caller", FunctionKey: "func", StacktraceKey: "stacktrace", LineEnding: "\n", EncodeTime: customTimeEncoder, EncodeLevel: zapcore.LowercaseLevelEncoder, EncodeDuration: zapcore.SecondsDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, } } func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString(t.Format("2006-01-02 15:04:05.000")) }