package logger import ( "fmt" "os" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) func getLogLevel(level string) *zapcore.Level { // 设置日志级别 logLevel := zap.InfoLevel switch level { case "debug": logLevel = zap.DebugLevel case "info": logLevel = zap.InfoLevel case "warn": logLevel = zap.WarnLevel case "error": logLevel = zap.ErrorLevel } return &logLevel } func NewLogger(level, path string) *zap.Logger { // 1. 始终保留控制台输出 consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()) consoleWriter := zapcore.Lock(os.Stderr) // 加锁保证线程安全 cores := []zapcore.Core{ zapcore.NewCore(consoleEncoder, consoleWriter, getLogLevel(level)), } // 2. 条件性添加文件输出 if path != "" { fileWriter := zapcore.AddSync(&lumberjack.Logger{ Filename: path, MaxSize: 10, MaxBackups: 5, MaxAge: 30, Compress: false, }) fileEncoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()) cores = append(cores, zapcore.NewCore(fileEncoder, fileWriter, getLogLevel(level))) } // 3. 创建带恢复机制的Logger return zap.New( zapcore.NewTee(cores...), zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel), zap.WrapCore(func(core zapcore.Core) zapcore.Core { return &safeCore{Core: core} // 包装核心添加recover }), ) } // 安全核心包装器 type safeCore struct { zapcore.Core } func (c *safeCore) Write(ent zapcore.Entry, fields []zapcore.Field) error { defer func() { if r := recover(); r != nil { fmt.Fprintf(os.Stderr, "Recovered from logger panic: %v\n", r) } }() return c.Core.Write(ent, fields) }