Zerolog 实战指南:Go 语言的结构化日志库

Zerolog 中文实战指南:面向低分配的高性能设计、链式 API、七个日志级别、ConsoleWriter 开发友好输出、With 绑定上下文字段、Hooks 与采样、context.Context 集成、错误堆栈记录,以及观测云 DataKit 采集落地方案。

最佳实践
Zerolog 实战指南:Go 语言的结构化日志库技术指南封面

Zerolog 是 Go 生态中以性能著称的结构化日志库,核心设计目标是零内存分配——实际分配和 GC 开销仍取决于字段类型、格式化、writer 和调用路径。它默认输出 JSON,API 采用流畅的链式调用。本文覆盖 Zerolog 的核心用法、上下文绑定、采样降噪与生产配置,并给出观测云平台的落地方案。

核心要点速览

  • Zerolog 面向低分配的结构化日志场景:实际吞吐和分配需在目标负载中验证,不能保证所有调用路径都零分配。
  • 默认输出 JSON:每条日志天然是结构化文档,开发期可用 ConsoleWriter 转成彩色可读格式。
  • 链式事件 API:log.Info().Str("user", u).Int("code", c).Msg("..."),字段在 Msg 前的链上逐个附加。
  • 生产落地:JSON 输出 stdout,观测云 DataKit 采集解析,监控器告警,多索引控成本。

快速上手:链式 API 与日志级别

package main

import (
    "errors"
    "github.com/rs/zerolog/log"
)

func main() {
    log.Debug().Msg("调试细节")  // 默认级别 trace,全都输出
    log.Info().Str("user", "zhangsan").Msg("用户登录")
    log.Warn().Msg("配置项缺失,使用默认值")
    err := errors.New("insufficient balance")
    log.Error().Err(err).Str("order_id", "A-1024").Msg("扣款失败")
}

输出(包级默认 logger 写入 stderr,格式为 JSON):

{"level":"info","user":"zhangsan","time":"2026-08-25T14:35:10+08:00","message":"用户登录"}
{"level":"error","error":"insufficient balance","order_id":"A-1024","time":"...","message":"扣款失败"}

Zerolog 提供七个级别:Trace、Debug、Info、Warn、Error、Fatal、Panic。Fatal 在事件由 Msg/Send 等提交时调用 os.Exit(1),Panic 在提交时 panic——生产代码慎用。

全局级别用 zerolog.SetGlobalLevel(zerolog.InfoLevel) 设置;字段方法覆盖所有常见类型:Str()、Int()、Bool()、Dur()、Time()、Err() 等。

如何创建定制 Logger?

包级 log 是全局默认 logger,生产建议显式创建实例。下面片段需导入 os 和 github.com/rs/zerolog;新建 logger 需显式添加 Timestamp 才有时间戳:

logger := zerolog.New(os.Stdout).
    With().
    Timestamp().
    Str("service", "order-api").
    Logger()

With() 返回 Context 对象,链上绑定的字段(service、版本、实例 ID)会出现在该 logger 的所有日志里;再加 Caller() 可附带源码位置。

开发环境:ConsoleWriter 友好输出

logger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).
    Level(zerolog.DebugLevel).With().Timestamp().Caller().Logger()

此片段还需导入 time。彩色对齐的纯文本输出,开发体验拉满;生产切回 JSON 输出即可。

错误与堆栈怎么记?

Err(err) 会把错误写入 error 字段。需要堆栈时,配合 pkg/errors 并启用:

zerolog.ErrorStackMarshaler = func(err error) interface{} {
    return pkgerrors.MarshalStack(err)
}

上述 pkgerrors 指 github.com/rs/zerolog/pkgerrors;err 应由 github.com/pkg/errors.New 或 Wrap 等产生并携带堆栈。之后 log.Error().Stack().Err(err).Msg("...") 才能序列化已有堆栈;不能为普通 errors.New 错误重建创建现场。

高级能力:Hook、采样与 context 集成

Hook:给特定级别统一附加字段

logger = logger.Hook(zerolog.HookFunc(func(e *zerolog.Event, level zerolog.Level, msg string) {
    if level >= zerolog.ErrorLevel {
        e.Str("alert_hint", "check-oncall")
    }
}))

采样:高频日志降噪

sampled := logger.Sample(&zerolog.BasicSampler{N: 100})  // 每 100 条只记 1 条
sampled.Info().Msg("高频心跳日志")

BasicSampler 会对该 sampled logger 的事件采样,不会自动豁免 Error。高频流水使用 sampled,关键错误应使用未采样的 logger,并测试保留比例与上下文。

从 context.Context 取 logger

Zerolog 提供 zerolog.Ctx(ctx) 与 (*Logger).WithContext(ctx) 帮助函数,实现"logger 随请求 context 流转":

ctx := reqLogger.WithContext(r.Context())
// 下游:
log := zerolog.Ctx(ctx)
log.Info().Msg("处理中")

请求级字段(request_id 等)绑在 reqLogger 上一次,通过该 context 获取的 logger 才会携带;若 context 未绑定 logger,则使用 DefaultContextLogger,若它也未配置则返回禁用的 logger。

检查 Zerolog 输出与采集字段

先保留一条 info、一条 error 和一条带请求上下文的 JSON 日志。使用观测云时,按 DataKit 日志配置接入输出位置,在 Pipeline 中解析 time 并将 level 映射到 status,核对 warn、fatal、panic 等级的转换结果。

若已在 Go 服务中接入链路,将当前请求的 trace_id 写入日志,再用同一次请求检查日志与 Span 是否对应。开启采样后还要检查关键错误是否保留;成本变化应按实际保留量和存储配置计算。

常见问题(FAQ)

Zerolog 和标准库 slog 怎么选?

新项目默认建议 slog(标准库、零依赖、生态在向它收敛);确认日志吞吐是性能瓶颈、或需要 Zerolog 独有的采样/二进制 CBOR 输出时选 Zerolog。也可选用经核对版本和能力的 slog Handler 适配器接入 Zerolog,不能假定任意版本都原生提供所需适配。

Zerolog 支持文本格式输出吗?

只支持 JSON(及 CBOR 二进制)。文本输出靠 ConsoleWriter 在写入前转换,本质是开发期工具;生产请保持 JSON,交给日志平台解析。

Fatal 和 Panic 级别会导致程序退出吗?

Fatal 事件提交后调用 os.Exit(1)(defer 不会执行);Panic 事件提交后触发 panic,可由同一 goroutine 调用栈中的 deferred recover 捕获,因此不一定终止整个进程。只在确实不可恢复的启动期错误使用 Fatal;请求处理路径上的错误用 Error。

Zerolog 如何做日志轮转?

库本身不管轮转——它只写 io.Writer。主机部署如用 logrotate 重命名文件,应用需重新打开 writer;copytruncate 有复制/截断窗口丢失日志的风险;需要应用内轮转时用 lumberjack 作为 writer;容器部署直接 stdout 最省心。

系列阅读


[1]: 观测云文档《DataKit 日志采集综述》https://docs.guance.com/integrations/logging/
[2]: 观测云文档《日志查看器》https://docs.guance.com/logs/explorer/
[3]: 观测云文档《监控》https://docs.guance.com/monitoring/
[4]: 观测云文档《日志-索引》https://docs.guance.com/logs/multi-index/

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台