我有两条自动巡检任务,每天定点跑一遍所有在管项目。一条叫 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