我的告警系统把 90% 的告警判成 high,独立调查器只认同 26%

每个告警工具都说自己能降噪。我想知道我自己写的这个降没降——结果测出来的第一个数字是打脸的。

结论先放前面:我的系统把一周 367 条告警里的 330 条(90%)判成 high;被深度调查过的 80 条里,独立调查器只认同其中 21 条(26%)确实是 high。high 已经退化成”有一条告警”的同义词。修完之后,每周 59% 的告警量不再是 high——但这篇文章最值得写的不是修,是那道拒绝过度修正的护栏

标注集是从哪来的

评估告警分级,最贵的一步是标注:谁来一条条判断”这条到底该不该叫 high”?没人有这个时间。

但我的架构里恰好有个副产品。值得深挖的告警会升级给一个 agent 调查器(hookprobe)——它检索指标、翻日志、查知识库,几分钟后交一份根因报告,报告里带着它自己判定的严重度

调查器判定严重度时手里有廉价关键词判定拿不到的东西:真实的系统状态。于是每一份调查报告,天然就是一条标注——一份没人标注过的标注集,就这么攒出来了。

第一次打分

拿调查器的严重度当基准,给入口处的廉价判定打分:

一周告警总量 367
廉价判定为 high 330(90%)
其中被调查过的 80
调查器也认同是 high 的 21(26%

两个具体例子说明谁对谁错:

  • SES 退信率告警,廉价判定按关键词给了中等——调查器判 critical,理由是 AWS 真的会因为退信率暂停你整个账号的发信能力。它对了。
  • 业务金额类告警(真金白银的业务信号)被判成 medium,淹没在一堆基础设施 high 里。也是调查器对。

廉价判定不是坏——它便宜、快、覆盖 100% 流量。它只是没有校准,而且没人发现它没有校准,因为从来没有基准可以对。

修法:提议权和决定权分开

写了个校准脚本(scripts/ops/severity_calibration.py),逻辑很直白:

  1. 告警规则聚合调查报告,算出每条规则被调查器实际判定的严重度分布;
  2. 对分布明显低于廉价判定的规则,提议一个严重度上限(ceiling);
  3. 人看提议,决定采纳与否——脚本永远不直接改线上。

采纳之后,每周 59% 的告警量不再是 high。值班的注意力第一次开始跟着真实严重度走。

护栏比机制更重要

这是全文最想让你带走的一段。

校准脚本有一条硬性拒绝规则:如果某条告警规则被调查器判为 high 的比例超过三分之一,脚本拒绝为它提议降级——不管它的平均分布多低。

为什么?因为那种规则的问题不是”级别虚高”,是告警本身写得太宽:同一条规则既匹配到真事故又匹配到日常抖动。给它压级别,等于把真事故一起压掉——那是把降噪做成了掩耳盗铃。这种噪音的正确修法是把告警条件写得更具体,让它只在该叫的时候叫。

一句话:降级修的是”级别错了”,改告警修的是”告警错了”,两种病不能用同一种药。

这个闭环的形状

回头看,这套东西的形状是:

  1. 一个便宜的默认路径(关键词判定,覆盖全量);
  2. 一个昂贵的高质量信号(agent 调查,只花在值得的告警上);
  3. 拿 2 给 1 打分——系统自己生产评估自己的标注集;
  4. 修正走”机器提议、人决定”;
  5. 一道防过度修正的护栏。

其中 3 是免费的:调查器本来就要跑,报告本来就带严重度,只是从来没人拿它回头照自己。我怀疑很多系统里都躺着这样一份没被用起来的标注集——你的告警平台、你的工单系统、你的 code review 记录里,可能都有一个”昂贵但准的信号”在给”便宜但糙的判定”默默陪跑。

拿它照一下自己。数字可能很难看,但难看的数字是能修的,没有数字才是真的没救。


代码都开源:WebhookWise(校准脚本在 scripts/ops/,README 第一节就是这个故事)。