zerolog 默认不输出 info 级日志,因默认全局级别为 tracelevel,info 被静默丢弃且不报错;必须在首条 log 调用前执行 zerolog.setgloballevel(zerolog.infolevel),自定义 logger 需新建时显式设 .level(),输出目标仅限 os.stdout/os.stderr,结构化字段(如 service_name、env)须通过 .with().str() 预置,trace_id 需手动提取并随 context 透传至 goroutine。

zerolog 默认不输出 Info 级日志,且容器里写文件会破坏日志采集链路——必须用 os.Stdout 输出 JSON,并显式设级别。
为什么 log.Info().Msg("x") 什么都没打印?
zerolog 默认只输出 TraceLevel 及以上日志,InfoLevel 被静默丢弃,也不报错。这不是 bug,是设计:它假设你明确知道自己要什么级别。
- 必须在任何
log.Xxx()调用前执行zerolog.SetGlobalLevel(zerolog.InfoLevel) - 若用了自定义 logger(如
zerolog.New(os.Stdout).With().Logger()),它**不响应**SetGlobalLevel后续变更,得在新建时传.Level(zerolog.InfoLevel) - 别依赖全局 logger 的“默认行为”,生产环境一律显式构造带级别的 logger
如何让每条日志都带 service_name、env、container_id?
结构化日志的价值在于字段可提取。这些字段不能靠运行时拼接字符串,而应通过 With() 预置,确保每条日志天然携带上下文。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 从环境变量读取:
os.Getenv("SERVICE_NAME")、os.Getenv("ENV")、os.Getenv("HOSTNAME") - 用
Timestamp()替代手写时间格式,避免时区/精度问题 - 示例初始化:
log := zerolog.New(os.Stdout).With().Str("service_name", os.Getenv("SERVICE_NAME")).Str("env", os.Getenv("ENV")).Str("container_id", os.Getenv("HOSTNAME")).Timestamp().Logger() - 禁止在 handler 里重复加这些字段——它们属于服务级元数据,不是业务事件属性
如何注入 trace_id 并穿透 goroutine?
zerolog 不自动解析 HTTP 请求或 context,trace_id 必须手动提取并随上下文传递。常见错误是只在入口加一次,后续 goroutine 或异步调用就丢失。
- HTTP 中间件里从
X-Request-ID或traceparentheader 提取,存入context.WithValue - 每次需要打日志时,用
zerolog.Ctx(r.Context()).With().Str("trace_id", tid).Logger()创建子 logger - 启动 goroutine 时,必须把带 context 的 logger 传进去,或用
zerolog.Ctx(ctx)重新获取,不能复用外部 logger - gRPC 场景下,在
UnaryServerInterceptor做同样操作,并通过metadata.MD向下游透传
要不要用 ecszerolog?
如果你的日志最终进 Elasticsearch 且要求严格遵循 ECS 规范(比如字段名必须是 log.level 而非 level),ecszerolog 是轻量适配方案;否则纯 zerolog 更直接、更可控。
- 引入后只需替换初始化:
logger := ecszerolog.New(os.Stdout) - 它自动添加
@timestamp、ecs.version、log.level等字段,但也会覆盖你自定义的level字段名 - 注意:ECS 字段命名与多数日志系统(如 Loki、Datadog)默认 schema 不一致,确认采集端支持再上
- 非 ECS 场景下,硬编码字段名反而增加维护成本,不如用标准 zerolog + 自定义 formatter
最易被忽略的点:日志输出目标必须是 os.Stdout 或 os.Stderr,绝不能写文件。容器运行时只接管标准流,写文件会导致日志不可采集、不可轮转、不可压缩——等于没日志。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










