package logger import ( "log" "os" "time" "github.com/spf13/viper" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) var shanghaiLoc *time.Location func init() { var err error shanghaiLoc, err = time.LoadLocation("Asia/Shanghai") if err != nil { // 尝试备选时区名称 shanghaiLoc, err = time.LoadLocation("PRC") if err != nil { // 若仍失败,手动设置东八区偏移 shanghaiLoc = time.FixedZone("CST", 8*3600) log.Printf("警告:加载时区失败,使用手动东八区偏移: %v", err) } } } // Init 初始化日志(依赖配置文件已加载) func Init() { // 日志级别转换 level := zap.InfoLevel switch viper.GetString("logger.level") { case "debug": level = zap.DebugLevel case "warn": level = zap.WarnLevel case "error": level = zap.ErrorLevel } // 日志轮转配置(lumberjack) hook := lumberjack.Logger{ Filename: viper.GetString("logger.path") + "logs/app.log", // 日志文件路径 MaxSize: viper.GetInt("logger.max_size"), // 单个文件最大大小(MB) MaxBackups: viper.GetInt("logger.max_backup"), // 最大备份数 MaxAge: viper.GetInt("logger.max_age"), // 最大保留天数 Compress: true, // 是否压缩 } // 编码器配置 encoderConfig := zapcore.EncoderConfig{ TimeKey: "time", LevelKey: "level", NameKey: "logger", CallerKey: "caller", MessageKey: "msg", StacktraceKey: "stacktrace", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.CapitalLevelEncoder, // 日志级别大写(DEBUG/INFO) EncodeTime: customTimeEncoder, // 自定义时间格式 EncodeDuration: zapcore.SecondsDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, // 精简调用者路径 } // 输出配置(控制台+文件) core := zapcore.NewTee( zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), zapcore.AddSync(os.Stdout), level), zapcore.NewCore(zapcore.NewJSONEncoder(encoderConfig), zapcore.AddSync(&hook), level), ) // 创建logger实例(开启调用者信息和堆栈跟踪) logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zap.ErrorLevel)) zap.ReplaceGlobals(logger) zap.L().Info("✅ 日志初始化成功", zap.String("level", level.String())) } // customTimeEncoder 自定义时间格式(强制东八区,若加载失败则使用UTC) func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) { // 使用提前初始化好的时区,避免每次调用都加载 beijingTime := t.In(shanghaiLoc) // 格式化输出 enc.AppendString(beijingTime.Format("2006-01-02 15:04:05.000")) }