把日志写清楚,比加一层监控更能救命

一次线上支付失败,团队第一反应是加监控:又做了三个告警面板,两天后屏幕上仍然只有「支付失败」四个字。

真正缺的不是监控,是一条能回答「哪个用户、卡在哪一步、耗时多久」的日志。

指标和日志解决的不是同一个问题

指标回答「整体是否异常」,日志回答「这一次请求发生了什么」。用指标替代日志,你只能知道异常范围,无法还原路径。

反过来,把每一条请求细节都做成指标标签,成本会失控,查询也会变慢。两者是互补关系,不是可替换关系。

把信息放进字段,而不是句子里

「用户 12345 支付失败」看起来清楚,但无法查询。改成事件名加上独立字段,就能直接写条件、做告警、做聚合。

工程实践里比较一致的经验是:不要把可变数据写进消息字符串。基于字段的规则可以长期稳定运行;靠正则匹配句子,一旦有人改了措辞就会失效。

一条日志该带的字段

  • timestamp(ISO 8601,UTC)、level、service、environment:每条日志都必须有
  • trace_id 或 request_id:把跨服务的同一次请求串起来,这是收益最高的单个字段
  • event:稳定的机器可读事件名,例如 order_placed、payment_failed,而不是一句话叙述
  • 业务上下文:user_id、order_id、duration_ms,字段名要带单位,避免 size、amount 这类模糊命名
  • 失败时补上 error 类型与堆栈,但不要顺手把整个请求体塞进去

命名与类型必须统一

一个服务写 user_id,另一个写 userId,第三个写 uid,跨服务查询就会漏数据,而且不会报错。判断标准很直白:能不能用一条查询拿到某个用户的全部日志。

类型同样要统一。duration_ms 在一处是数字、另一处是带单位的字符串,平均值计算会悄悄算错,只统计到其中一部分日志。

采样与脱敏

生产环境默认 INFO,DEBUG 只在排查问题时临时开启。5xx 响应、重试后最终失败的任务、安全与审计事件保留百分之百。

高频成功日志和健康检查按比例采样,并在日志里带上 sample_rate。漏了这个字段,事后统计会低估真实数量,可能差出十几倍。

密码、令牌、卡号、授权头这类敏感字段,应该在日志库层面自动脱敏,而不是指望每个开发者都记得。

三个常见误区

误区一,把日志当指标用。统计请求量与错误率应该交给指标系统,日志负责个案细节,混用两边都不准。

误区二,「先全量记下来以后再说」。完整对象会推高成本,也让真正有用的字段淹没在噪音里。

误区三,一次改造全部服务。应该先改最常出问题、最常被值守的那个服务,收益最快体现,也最容易说服团队继续推进。

如果今天只加一个字段

加 trace_id。在系统边界处生成或透传,通过请求作用域自动附加到这条请求产生的每一条日志上,让开发者无法遗漏。

一个月后你会得到一个新的验收标准:排查一次故障,不需要改代码、不需要问其他团队,只用查询就能回答「这位用户最近一小时失败的每一步是什么」。

标签:#, #