package logx import ( "context" "fmt" "sync" "gitea.micah.wiki/pandora/starter/app/config" "gitea.micah.wiki/pandora/starter/pkg/env" "gitea.micah.wiki/pandora/starter/pkg/requestid" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) var ( logger *zap.Logger once sync.Once ) func Init() { _ = _getLogger() } func _getLogger() *zap.Logger { if logger == nil { once.Do(func() { logFile := config.GetConfig().LogFile 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, // 自定义控制台输出的字段顺序(仅对ConsoleEncoder生效) ConsoleSeparator: " ", // 字段之间的分隔符 } var writer zapcore.WriteSyncer var encoder zapcore.Encoder writer = zapcore.AddSync(&lumberjack.Logger{ Filename: logFile, MaxSize: 10, // megabytes MaxBackups: 30, MaxAge: 7, // days Compress: true, }) if env.IsLocal() { encoder = zapcore.NewConsoleEncoder(encoderConfig) } else { // 其他系统保持 JSON 编码器 encoder = zapcore.NewJSONEncoder(encoderConfig) } core := zapcore.NewCore( encoder, writer, zap.DebugLevel, ) logger = zap.New(core) }) } return logger } func Close() { if logger != nil { _ = logger.Sync() } } // 统一封装日志方法,根据编码器类型处理logid func logWithCtx(ctx context.Context, level zapcore.Level, template string, args ...interface{}) { logid := requestid.GetLogID(ctx) msg := fmt.Sprintf(template, args...) // 根据编码器类型决定 logid 的展示方式 if env.IsMacOS() { // macOS控制台模式:将logid嵌入到消息中,保证文本可读性 msg = fmt.Sprintf("%s %s", logid, msg) _getLogger().Log(level, msg) } else { // 其他系统JSON模式:使用zap字段,保证JSON结构清晰 _getLogger().With(zap.String("logid", logid)).Log(level, msg) } } // CtxInfo 带上下文的Info级别日志 func CtxInfo(ctx context.Context, template string, args ...interface{}) { logWithCtx(ctx, zapcore.InfoLevel, template, args...) } // CtxError 带上下文的Error级别日志 func CtxError(ctx context.Context, template string, args ...interface{}) { logWithCtx(ctx, zapcore.ErrorLevel, template, args...) } // CtxWarn 带上下文的Warn级别日志 func CtxWarn(ctx context.Context, template string, args ...interface{}) { logWithCtx(ctx, zapcore.WarnLevel, template, args...) } // CtxDebug 带上下文的Debug级别日志 func CtxDebug(ctx context.Context, template string, args ...interface{}) { logWithCtx(ctx, zapcore.DebugLevel, template, args...) }