关于日志级别的一点争论
组里为「这条日志该打 INFO 还是 DEBUG」吵了半小时,最后谁也没说服谁。我说说我的看法。
我的标准
只看一个问题:线上出问题时,这条日志能不能帮我定位?
- 能 → 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))
好处是可以按字段检索、聚合、告警。字符串日志再想加个告警,就得写正则,很快就不可维护了。
几个具体建议
- 错误日志一定要带上下文:哪个请求、哪个用户、哪个参数。光打
err等于没打 - 不要在循环里打 INFO。如果一定要,加采样
- 请求入口和出口各一条就够,中间的过程用 DEBUG
- 日志里不要有敏感信息。手机号、身份证、token,该脱敏就脱敏
最后
日志是给未来的人看的,而那个人大概率是三个月后的你自己。写的时候想一下:凌晨三点被叫起来,看到这行日志,你知道该干什么吗?
如果不知道,那这条日志就没什么价值。