package log import ( "context" "fmt" "os" "strings" "time" "github.com/natefinch/lumberjack" "github.com/spf13/viper" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gorm.io/gorm/logger" ) var Log *zap.Logger type ZapStarter struct { } func (s *ZapStarter) Init() error { Init() return nil } func Init() { // 编码器 encoderConfig := zap.NewProductionEncoderConfig() // NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式 encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 指定时间格式 encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 按级别显示不同颜色,不需要的话取值 CapitalLevelEncoder 就可以了 encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder // 是否显示完整文件路径 encoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000") env := viper.GetString("env") //encoder := zapcore.NewJSONEncoder(encoderConfig) encoder := zapcore.NewConsoleEncoder(encoderConfig) // todo if env != "dev" { fmt.Printf("zap log with %s env\n", env) encoder = zapcore.NewConsoleEncoder(encoderConfig) } normalPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { // info 级别 return lev < zap.ErrorLevel && lev >= zap.InfoLevel }) errorPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { // info 级别 return lev > zap.InfoLevel }) normalWriteSyncer := zapcore.AddSync(&lumberjack.Logger{ Filename: viper.GetString("log.normal.file"), // 日志文件存放目录 MaxSize: viper.GetInt("log.normal.size"), // 文件大小限制,单位MB MaxBackups: viper.GetInt("log.normal.backups"), // 最大保留日志文件数量 MaxAge: viper.GetInt("log.normal.age"), // 日志文件保留天数 Compress: viper.GetBool("log.normal.compress"), // 是否压缩处理 LocalTime: true, }) errorWriteSyncer := zapcore.AddSync(&lumberjack.Logger{ Filename: viper.GetString("log.error.file"), MaxSize: viper.GetInt("log.error.size"), MaxBackups: viper.GetInt("log.error.backups"), MaxAge: viper.GetInt("log.error.age"), Compress: viper.GetBool("log.error.compress"), LocalTime: true, }) Log = zap.New(zapcore.NewTee( []zapcore.Core{ zapcore.NewCore( encoder, zapcore.NewMultiWriteSyncer(normalWriteSyncer, zapcore.AddSync(os.Stdout)), normalPriority, ), zapcore.NewCore( encoder, zapcore.NewMultiWriteSyncer(errorWriteSyncer, zapcore.AddSync(os.Stdout)), errorPriority, ), }..., ), zap.AddCaller(), zap.AddCallerSkip(1)) } func traceID(ctx context.Context, fields ...zap.Field) []zap.Field { sp := trace.SpanContextFromContext(ctx) traceID := zap.String("trace_id", sp.TraceID().String()) fields = append(fields, traceID) return fields } func InfoWithCtx(ctx context.Context, msg string, fields ...zap.Field) { Info(msg, traceID(ctx, fields...)...) } func Info(msg string, fields ...zap.Field) { if strings.Contains(msg, "SHOW STATUS") { return } if strings.Contains(msg, "GET _health") { return } if strings.Contains(msg, "GET url: /health") { return } Log.Info(msg, fields...) } func WarnWithCtx(ctx context.Context, msg string, fields ...zap.Field) { Warn(msg, traceID(ctx, fields...)...) } func Warn(msg string, fields ...zap.Field) { Log.Warn(msg, fields...) } func ErrorWithCtx(ctx context.Context, msg string, fields ...zap.Field) { Log.Error(msg, traceID(ctx, fields...)...) } func Error(msg string, fields ...zap.Field) { Log.Error(msg, fields...) } func InfoFWithCtx(ctx context.Context, msg string, args ...any) { Log.Info(fmt.Sprintf(msg, args...), traceID(ctx)...) } func InfoF(msg string, args ...any) { msg = fmt.Sprintf(msg, args...) Info(msg) } func WarnFWithCtx(ctx context.Context, msg string, args ...any) { Log.Warn(fmt.Sprintf(msg, args...), traceID(ctx)...) } func WarnF(msg string, args ...any) { Log.Warn(fmt.Sprintf(msg, args...)) } func ErrorFWithCtx(ctx context.Context, msg string, args ...any) { Log.Warn(fmt.Sprintf(msg, args...), traceID(ctx)...) } func ErrorF(msg string, args ...any) { Log.Error(fmt.Sprintf(msg, args...)) } type GLog struct { } func (g GLog) LogMode(_ logger.LogLevel) logger.Interface { return &g } func (g GLog) Info(_ context.Context, msg string, args ...any) { Info(fmt.Sprintf(msg, args...)) } func (g GLog) Warn(_ context.Context, msg string, args ...any) { Warn(fmt.Sprintf(msg, args...)) } func (g GLog) Error(_ context.Context, msg string, args ...any) { Error(fmt.Sprintf(msg, args...)) } func (g GLog) Trace(_ context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { sql, ra := fc() if sql == "SHOW STATUS" { return } Info("gorm callback trace", zap.String("sql", sql), zap.Int64("rows", ra), zap.Error(err)) } func (g GLog) Printf(msg string, args ...any) { Info(fmt.Sprintf(msg, args...)) } // CLog cron logger type CLog struct { } func (c CLog) Info(msg string, keysAndValues ...any) { InfoF(msg, keysAndValues...) } // Error logs an error condition. func (c CLog) Error(err error, msg string, keysAndValues ...any) { ErrorF(msg, keysAndValues...) } func (c CLog) Printf(msg string, args ...any) { InfoF(msg, args...) }