You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Go的Zap日志库所有日志消息添加指定前缀?

问题

已通过以下配置完成Zap日志库的搭建:

outLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
    return level < zapcore.WarnLevel
})

// Warnings and everything above will be printed to stderr
errorLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
    return level >= zapcore.WarnLevel
})

stdoutSyncer := zapcore.Lock(os.Stdout)
stderrSyncer := zapcore.Lock(os.Stderr)

config := zap.NewDevelopmentConfig()
config.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
config.EncoderConfig.TimeKey = ""

core := zapcore.NewTee(
    zapcore.NewCore(
        zapcore.NewConsoleEncoder(config.EncoderConfig),
        stdoutSyncer,
        outLevel,
    ),
    zapcore.NewCore(
        zapcore.NewConsoleEncoder(config.EncoderConfig),
        stderrSyncer,
        errorLevel,
    ),
)

logger := zap.New(core)

zap.ReplaceGlobals(logger)

希望实现类似Go标准库log的SetPrefix功能,为所有DEBUG、INFO级别的日志消息添加前缀"=>"。例如执行:

zap.L().Info("this is new message") 

最终日志输出格式为:

=> this is new message

尝试使用log.With API,但生成的是JSON对象,不符合需求,寻求解决方案。

解决方案

无需使用With API(它会添加结构化字段导致JSON格式输出),可以通过自定义ConsoleEncoder的消息编码逻辑实现需求,具体代码如下:

import (
    "os"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)

func main() {
    outLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
        return level < zapcore.WarnLevel
    })

    errorLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
        return level >= zapcore.WarnLevel
    })

    stdoutSyncer := zapcore.Lock(os.Stdout)
    stderrSyncer := zapcore.Lock(os.Stderr)

    config := zap.NewDevelopmentConfig()
    config.EncoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
    config.EncoderConfig.TimeKey = ""

    // 自定义带前缀的ConsoleEncoder
    customEncoder := func(cfg zapcore.EncoderConfig) zapcore.Encoder {
        baseEncoder := zapcore.NewConsoleEncoder(cfg)
        return &prefixEncoder{base: baseEncoder}
    }

    core := zapcore.NewTee(
        zapcore.NewCore(
            customEncoder(config.EncoderConfig),
            stdoutSyncer,
            outLevel,
        ),
        zapcore.NewCore(
            zapcore.NewConsoleEncoder(config.EncoderConfig), // 错误级别保持原格式
            stderrSyncer,
            errorLevel,
        ),
    )

    logger := zap.New(core)
    zap.ReplaceGlobals(logger)

    // 测试输出
    zap.L().Info("this is new message")
    zap.L().Debug("debug message")
    zap.L().Warn("warn message")
}

// prefixEncoder 包装原生ConsoleEncoder,给特定级别消息添加前缀
type prefixEncoder struct {
    base zapcore.Encoder
}

func (e *prefixEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) ([]byte, error) {
    // 仅给DEBUG和INFO级别日志添加前缀
    if entry.Level == zapcore.DebugLevel || entry.Level == zapcore.InfoLevel {
        entry.Message = "=> " + entry.Message
    }
    return e.base.EncodeEntry(entry, fields)
}

func (e *prefixEncoder) Clone() zapcore.Encoder {
    return &prefixEncoder{base: e.base.Clone()}
}

核心逻辑说明:

  • 定义prefixEncoder结构体包装原生ConsoleEncoder,重写EncodeEntry方法
  • 在EncodeEntry中判断日志级别,仅对DEBUG/INFO级消息添加前缀"=>"
  • 错误级别(Warn及以上)保留原编码器,维持原有输出格式
  • 该方案不会引入结构化字段,完全符合纯文本控制台输出的需求

内容的提问来源于stack exchange,提问作者Viren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:57:40