陈默的笔记

关于日志级别的一点争论

· 工程

组里为「这条日志该打 INFO 还是 DEBUG」吵了半小时,最后谁也没说服谁。我说说我的看法。

我的标准

只看一个问题:线上出问题时,这条日志能不能帮我定位?

常见的过度打日志

log.Infof("enter function Foo, param=%v", p)
log.Infof("leaving function Foo")
log.Infof("query sql: %s", sql)

这类日志在 QPS 上千之后会把磁盘写满,而且真正的错误被淹没在里面。我见过一个服务,一分钟 40 万行日志,出故障时根本找不到关键信息。

结构化日志

能用结构化就别用字符串拼接:

log.Info("order created",
    zap.Int64("order_id", id),
    zap.Int64("user_id", uid),
    zap.Duration("cost", cost))

好处是可以按字段检索、聚合、告警。字符串日志再想加个告警,就得写正则,很快就不可维护了。

几个具体建议

  1. 错误日志一定要带上下文:哪个请求、哪个用户、哪个参数。光打 err 等于没打
  2. 不要在循环里打 INFO。如果一定要,加采样
  3. 请求入口和出口各一条就够,中间的过程用 DEBUG
  4. 日志里不要有敏感信息。手机号、身份证、token,该脱敏就脱敏

最后

日志是给未来的人看的,而那个人大概率是三个月后的你自己。写的时候想一下:凌晨三点被叫起来,看到这行日志,你知道该干什么吗?

如果不知道,那这条日志就没什么价值。