diff --git a/internal/app/service/task/delay_task.go b/internal/app/service/task/delay_task.go index 3f7dead..058260e 100644 --- a/internal/app/service/task/delay_task.go +++ b/internal/app/service/task/delay_task.go @@ -24,7 +24,7 @@ type DelayTask struct { func (d *DelayTask) Execute() error { d.logger.Infof("任务 %v: 开始延迟 %v...", d.executionTask.TaskID, d.duration) time.Sleep(d.duration) - d.logger.Infof("任务 %v: 延迟结束。\n", d.executionTask.TaskID) + d.logger.Infof("任务 %v: 延迟结束。", d.executionTask.TaskID) return nil } diff --git a/internal/infra/logs/logs.go b/internal/infra/logs/logs.go index 422e2dc..0b758eb 100644 --- a/internal/infra/logs/logs.go +++ b/internal/infra/logs/logs.go @@ -13,11 +13,25 @@ import ( "git.huangwc.com/pig/pig-farm-controller/internal/infra/config" "go.uber.org/zap" + "go.uber.org/zap/buffer" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" gormlogger "gorm.io/gorm/logger" ) +// ANSI 颜色代码常量 +const ( + reset = "\033[0m" + red = "\033[31m" + green = "\033[32m" + yellow = "\033[33m" + blue = "\033[34m" + magenta = "\033[35m" + cyan = "\033[36m" + white = "\033[37m" + bold = "\033[1m" +) + // Logger 是一个封装了 zap.SugaredLogger 的日志记录器。 // 它提供了结构化日志记录的各种方法,并实现了 io.Writer 接口以兼容 Gin。 type Logger struct { @@ -54,13 +68,70 @@ func NewLogger(cfg config.LogConfig) *Logger { func GetEncoder(format string) zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 时间格式: 2006-01-02T15:04:05.000Z0700 - encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 日志级别大写: INFO + encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 日志级别大写: INFO (由 coloredConsoleEncoder 处理颜色) if format == "json" { return zapcore.NewJSONEncoder(encoderConfig) } - // 默认或 "console" - return zapcore.NewConsoleEncoder(encoderConfig) + // 默认或 "console" 格式,使用自定义的带颜色编码器 + return NewColoredConsoleEncoder(encoderConfig) +} + +// coloredConsoleEncoder 是一个自定义的 zapcore.Encoder,用于为整个日志行添加颜色。 +type coloredConsoleEncoder struct { + zapcore.Encoder // 嵌入默认的 ConsoleEncoder,以便委托其大部分功能 + cfg zapcore.EncoderConfig +} + +// NewColoredConsoleEncoder 创建一个新的 coloredConsoleEncoder 实例。 +func NewColoredConsoleEncoder(cfg zapcore.EncoderConfig) zapcore.Encoder { + // 创建一个标准的 ConsoleEncoder 作为基础 + baseEncoder := zapcore.NewConsoleEncoder(cfg) + return &coloredConsoleEncoder{ + Encoder: baseEncoder, + cfg: cfg, + } +} + +// EncodeEntry 重写 EncodeEntry 方法,在原始日志输出前后添加颜色代码。 +func (c *coloredConsoleEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) { + // 首先,让嵌入的默认编码器生成原始的日志行 + buf, err := c.Encoder.EncodeEntry(entry, fields) + if err != nil { + return nil, err + } + + // 根据日志级别确定颜色 + var color string + switch entry.Level { + case zapcore.DebugLevel: + color = blue + case zapcore.InfoLevel: + color = green + case zapcore.WarnLevel: + color = yellow + case zapcore.ErrorLevel: + color = red + case zapcore.DPanicLevel, zapcore.PanicLevel, zapcore.FatalLevel: + color = bold + red + default: + color = reset + } + + // 创建一个新的 buffer 来存储带颜色的日志行 + coloredBuf := buffer.NewPool().Get() + coloredBuf.AppendString(color) + coloredBuf.Write(buf.Bytes()) + coloredBuf.AppendString(reset) + + buf.Free() // 释放原始 buffer 回池中 + + return coloredBuf, nil +} + +// Clone 方法也需要重写,以确保返回一个新的 coloredConsoleEncoder 实例。 +func (c *coloredConsoleEncoder) Clone() zapcore.Encoder { + return NewColoredConsoleEncoder(c.cfg) } // getWriteSyncer 根据配置创建日志写入目标。