云日志查询写得好,排障时间能砍一半
排障慢,往往不是日志不够
线上出问题时,最常见的困境不是「没有日志」,而是「日志太多,找不到那一条」。几百万条日志里翻一条异常,靠关键词搜索和肉眼扫,效率极低。
真正决定排障速度的,是两件事:日志字段设计得好不好,以及查询语句会不会写。
字段设计:先把结构留出来
如果日志是一整行自由文本,后续任何分析都要靠正则去抠。正确的做法是在写日志时就把它结构化成键值对,让查询系统能按字段过滤和聚合。
一个后端服务的最小字段集建议包含:
level:日志级别,便于先按错误过滤;trace_id:全链路追踪 ID,串起一次请求的所有日志;service/instance:哪个服务、哪个实例;method/path:接口维度;status:HTTP 状态码或业务码;cost_ms:耗时,用于找慢请求;user_id(脱敏后):定位到具体用户的影响面。
有了这些字段,绝大多数排障问题都能变成一句结构化查询,而不是翻页。
查询的四个基本套路
套路一:先按 trace_id 串链路
用户报「下单失败」时,第一件事不是搜「下单失败」这个关键词,而是拿到那次请求的 trace_id,把这一个请求涉及的所有服务的日志全捞出来按时间排序。这样能立刻看出卡在哪个环节,以及上游传给下游的参数是什么。
trace_id: "a1b2c3d4" | sort by time asc
套路二:用状态码 + 耗时找异常面
不知道具体是哪条请求出问题时,先看异常的整体分布:
status >= 500 | select count(*) as cnt, path group by path order by cnt desc
这条能立刻告诉你哪几个接口在报错、各报了多少次。然后针对具体的 path 再往下钻。
套路三:找慢请求不看平均值
平均值是最没用的指标。要定位慢,看分位数:
cost_ms > 1000 | select count(*) as slow_cnt, path group by path
再结合时间分布,判断是持续的慢还是某个时间点的尖峰。尖峰通常意味着某个下游抖动或者缓存集中失效。
套路四:新版本上线后的对比
发布之后要快速判断有没有引入回归。按分钟聚合错误数和 P99 耗时,把发布时间点画在图上,能直接看出曲线有没有拐点。这一步用固定查询语句做成模板,每次发布后跑一遍,比人工盯监控可靠。
几个容易被忽略的细节
时间范围不要开太大
查一周的日志和查十分钟的日志,性能差几个数量级。排障应该先锁定时间窗口(比如用户报障的时间点前后 10 分钟),再逐步扩大。上来就查全天的做法,在日志量大的服务上会直接超时。
关键词要加引号匹配整句
搜 error message 不加引号会被拆成两个词做 OR 匹配,结果里混进大量无关日志。要匹配完整短语必须加引号。
注意日志采样的影响
如果开启了采样,某些日志可能根本没被采集。这时候「查不到」不代表「没发生」。判断某个异常是否存在时,要确认采样策略是否覆盖了这个级别——很多配置只对 INFO 采样,ERROR 全量保留,这种情况下 ERROR 的连续性结论是可信的。
结构化字段和全文索引不是一回事
把 JSON 写进日志,不代表字段就自动可查。需要在采集配置里配置字段提取规则(JSON 解析或者正则提取),字段才会进索引。这一点在接入初期最容易漏,导致「日志里有字段但查不出来」。
告警和查询要联动
好的做法是把常用的排障查询保存成模板,告警通知里直接带上对应查询的链接或者参数。收到告警点进去就能看到相关日志,而不是从头写查询语句。这一条能省下大量重复劳动,尤其在半夜被告警叫起来的时候。
小结
日志系统用得好不好,差别不在工具,在「写日志的时候有没有想着以后怎么查」。结构化字段 + 固定查询套路 + 告警联动,这三件事做好,排障从小时级降到分钟级是可以实现的。
- 点赞
- 收藏
- 关注作者
评论(0)