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

Go中Zerolog日志级别差异化配置:仅终端显示ERROR级日志

问题

我在Go应用中使用zerolog库,有如下需求:

  • 仅将ERROR级别的日志消息显示在终端/控制台
  • 所有日志消息(无论DEBUG、INFO、WARNING、ERROR级别)均需发送至自定义Hook进行后续处理

现有代码如下:

func InitLogger(ctx context.Context, cfg *config, mc *mongo.Client) *zerolog.Logger {
    once.Do(func() {
        var multi zerolog.LevelWriter

        consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true, TimeFormat: time.RFC3339}

        multi = zerolog.MultiLevelWriter(consoleWriter)

        logger := zerolog.New(multi).Level(zerolog.TraceLevel).With().Timestamp().Logger()

        logger = logger.Hook(&ZerologHook{
            mClient:     mc,
        })

        zLog = &logger

    })

    return zLog
}


type ZerologHook struct {
    mClient     *mongo.Client
}

func (zh *ZerologHook) Run(e *zerolog.Event, level zerolog.Level, message string) {

    wg.Add(1)
    go func() {
    
        logData := LogData{}

        _ = zh.sendLogToMongoDB(e.GetCtx(), message, logData)

        wg.Done()
    }()
}
解决方案

完全可以实现这个需求,核心是给控制台输出的Writer添加级别过滤,同时保证Hook能接收所有级别的日志。具体修改如下:

  1. 为ConsoleWriter添加级别过滤
    zerolog提供了LevelWriter的包装器zerolog.LevelFilter,可以指定只让ERROR级别及以上的日志通过控制台输出。

  2. 保持Logger的全局级别为TraceLevel
    这样所有级别的日志都会被Hook捕获,不会被Logger本身的级别过滤掉。

修改后的完整代码:

func InitLogger(ctx context.Context, cfg *config, mc *mongo.Client) *zerolog.Logger {
    once.Do(func() {
        // 初始化控制台Writer,并添加级别过滤:仅ERROR级别
        consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: true, TimeFormat: time.RFC3339}
        filteredConsoleWriter := zerolog.LevelFilter{
            Level: zerolog.ErrorLevel,
            Writer: consoleWriter,
        }

        // 初始化Logger,全局级别设为TraceLevel以保留所有日志
        logger := zerolog.New(filteredConsoleWriter).Level(zerolog.TraceLevel).With().Timestamp().Logger()

        // 注册自定义Hook,Hook会接收所有级别的日志
        logger = logger.Hook(&ZerologHook{
            mClient: mc,
        })

        zLog = &logger
    })

    return zLog
}

type ZerologHook struct {
    mClient *mongo.Client
}

func (zh *ZerologHook) Run(e *zerolog.Event, level zerolog.Level, message string) {
    wg.Add(1)
    go func() {
        defer wg.Done() // 建议添加defer,避免panic导致WaitGroup计数泄漏
        logData := LogData{}
        _ = zh.sendLogToMongoDB(e.GetCtx(), message, logData)
    }()
}

关键说明:

  • zerolog.LevelFilter会检查日志级别,只有大于等于指定Level的日志才会被写入对应的Writer,这里设置为zerolog.ErrorLevel,就只会输出ERROR级别的日志到控制台。
  • Logger的Level(zerolog.TraceLevel)确保所有级别的日志都会被生成并传递给Hook,不会被Logger本身过滤掉。
  • 额外优化:在Hook的goroutine里添加defer wg.Done(),防止sendLogToMongoDB发生panic时导致WaitGroup计数无法减少,造成程序阻塞。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:12:47