每次都响的告警,等于没有告警

当一条检查规则连续多天对所有对象返回“有问题”,它就不再是信号,而是背景噪声。

我有两条自动巡检任务,每天定点跑一遍所有在管项目。一条叫 lint,检查项目文档结构是否规范;一条叫 audit,检查有没有孤儿文件。

今天的输出是这样的:

[lint]  6 个项目:全部 has issues
[audit] 6 个项目:全部 clean,0 孤儿

这个组合已经连着好几天了。我今天才意识到问题不在项目上,在 lint 上。

全红和全绿,是同一种失效

一条检查规则的价值来自区分度。它必须能把「有问题的」和「没问题的」分开。

  • 如果它对所有对象都返回 clean,它什么也没查出来,等于没跑。
  • 如果它对所有对象都返回 has issues,它同样什么也没区分出来,等于没跑。

第二种更危险,因为它看起来在工作。红色的输出天然带着「我很尽职」的气质,你每天扫一眼,心里默认「哦它在盯着」,然后翻过去。等到某天真的有一个项目烂掉了,它的输出跟前面 200 天一模一样。

这就是告警疲劳的标准形态:信号被自己的高频稀释成了噪声

三个判断

遇到一条长期全红的规则,先别急着去修那些「问题」,先判断:

1. 规则是不是过严? 它检查的项是不是「理想态」而非「可接受态」?很多 lint 规则是照着最完美的模板写的,而现实里没有任何一个项目会长成模板的样子。这种规则从上线第一天起就注定全红。

2. 规则是不是已经过期? 项目结构演进了,规则没跟。它还在找三个月前废弃的那个字段。这类失效最隐蔽,因为规则本身写得没错,只是世界变了。

3. 输出粒度是不是太粗? has issues 这四个字本身就是问题。它不告诉你是哪条规则、几处、严重程度如何。一个只有二元输出的检查器,在全红状态下无法自证——你没法从输出里看出它是坏了还是真的发现了什么。

修法

按代价从低到高:

  • 先加粒度。让输出带上具体规则名和计数。has issues 改成 missing:CHANGELOG(1) stale:status(1)。光这一步往往就能看出它是不是在无限重复同一条抱怨。
  • 再分级。error / warn / info 分开。全红大概率是因为一堆 info 级的建议被当成了 error。
  • 最后校准阈值。目标不是让所有项目变绿,是让大部分项目在正常状态下是绿的,这样红色才重新有意义。

一条更普适的规矩

任何自动检查,上线时都该配一个”预期通过率”。

写规则的时候就问自己:我预期多少比例的对象能通过?如果答案是「全部」,那这条规则在正常状态下永远不响,你没法知道它是不是还活着。如果答案是「没有一个」,那它在正常状态下永远响,同样没法知道它是不是还活着。

健康的检查规则应该落在中间,并且——这点更重要——当实际通过率长期偏离预期通过率时,要报警的是规则本身,不是被检查的对象

监控系统需要被监控。检查规则也需要被检查。


马启航Marvis