缺失的测量与延迟触发的告警
一句话总结
值为 0、当前没有可选择的样本、没有新样本到达,彼此不同。告警首次满足条件后的 pending 状态,也要与实际 firing 状态区分。本实验通过使用虚拟时间的真实规则测试,验证这些差异如何改变告警等待时间。知道告警为 firing,并不等于通知邮件已经送达。
为什么需要它
“没有数据就补 0,图表会更整齐”虽然能美化报告,却可能把消失的测量误说成实际没有请求。支付服务没有请求,与 exporter 不再提供支付 counter,连响应方法都不同:前者应分析需求,后者应检查计量和采集路径。
告警也不只是比较一个数字。如果条件短暂成立后消失,却继续累计此前的等待时间,就可能过早触发。反过来,测试中漏掉数据后假设条件消失,而实际引擎仍选择先前样本,告警等待可能继续进行。涉及时间轴的行为,不要只读说明就确信,应在把事件前后排列的测试中确认。
工作原理
本实验有一项有限约定:每个 route 应有两条输入时间序列。我们在基础 rate 规则后加入保护条件,只保留当前可选择时间序列数为 2 的 route。这不是建议所有服务永远只能有两个实例,而是在本实验中作为比较当前序列数和样本存在性的简单装置。
在显式加入 stale 标记的场景中,/checkout 的 b 从当前选择结果消失。第 6 分钟 count 为 1。移除保护条件后,仍可能用旧范围样本算出请求率;但受保护的 rate 中没有 /checkout 样本。/status 的两个实例和值 2 仍保留。这不是全局空向量,而是某一路径的信息不足。
而在真正无请求的场景中,a 和 b 的 counter 持续观测为 0。当前时间序列数为 2,受保护请求率为 0。如果把期望样本写成空列表,反而会错误拒绝这个正常状态。测试“没有”时,要写明该标签集合不存在于结果;测试 0 时,要写明该标签集合存在且值为 0。
缺失样本与 stale 标记不是同一种输入
测试 values 中的 _ 表示该位置没有样本,stale 则明确标记时间序列已经陈旧。实验只把 b 在第 6 分钟的样本设为 _ 时,引擎会选择第 5 分钟的上一样本。到第 6 分钟样本年龄为 60 秒,当前序列数仍为 2,受保护 rate 为 11。把同一位置改为 stale 后,受保护的 /checkout 结果则会消失。
产生这种差异,是因为最新值选择并不要求每个求值时刻都有新样本;lookback 范围内的上一样本仍可能被选择。因此,count 为 2 不能保证两条输入当前足够新鲜,也不能保证实际 scrape 刚刚成功;实例身份也无法仅凭 count 确认。在生产判定中,需要另外设计预期目标列表、采集状态和样本年龄的契约。本单元不声称已经实现这些契约,而要求学员报告简单 count 保护条件的局限。
也不能把实际 HTTP scrape 失败一概视为与单元测试中的 _ 完全相同。实际采集器会根据情况生成 stale 标记,目标移除和时间戳设置也各有语义。这里是把预先准备的时间序列输入规则引擎;真实网络采集验证要与上一单元的独立 Prometheus 实验区分。
从前后两侧检查告警等待时间
告警 PcaHighRequestRate 设计为:受保护 rate 大于 10.5 的状态必须持续 for: 2m 才 firing,求值间隔为 1 分钟。正常输入的实际结果是第 5 分钟 pending、第 6 分钟 pending、第 7 分钟 firing。必须同时检查首次越过阈值时刻与触发时刻,才能发现删除 for 的规则。如果只检查第 7 分钟 firing,提前触发的规则到该时刻也同样是 firing,错误实现就会通过。
如果在等待中的第 6 分钟加入 stale,条件会消失。第 7 分钟输入恢复后不会立即 firing,而是重新进入 pending;第 8 分钟仍 pending,第 9 分钟才 firing。相反,只在第 6 分钟漏掉一个样本时,由于仍选择上一样本,条件会持续并在第 7 分钟 firing。学员测试必须同时包含两个场景。
alert_rule_test 会比较指定时刻的 firing 告警。只期待没有 firing,无法区分 pending 与完全 inactive。因此,还要在 promql_expr_test 中检查 ALERTS 的 alertstate 标签。第 6 分钟的 stale 场景没有 ALERTS 样本,单纯缺失样本的场景则有 pending 样本。这形成了比“还没响”更强的时间轴契约。
现场会遇到的情况
评审告警时,不应只截取触发后的一个画面。越过阈值前、首次越过、等待中、触发边界、数据缺失与恢复,都要分别测试。把 for 缩短为 1 分钟或增加到 3 分钟的变体,也应分别被识别为过早和过晚触发。因为告警太吵而盲目延长等待时间,同样是在更改需求;必须结合团队响应预算,讨论允许多晚发现哪种事故。
最后,要狭义而准确地报告 firing 的含义。本测试确认的是规则引擎生成的状态。Alertmanager 的分组、静默、路由和邮件发送属于其他阶段;该 VM 实验不会发送外部通知。不要把未经确认的投递也写成“告警正常”,这种习惯和测试质量同样重要。
下一实验要做什么
在 coverage-rules.yml 中删除把不存在值补成 0 的错误处理,同时保留真实的 0。在 coverage-tests.yml 中修正针对缺失路径的错误期望样本。随后设置 alert-rules.yml 的等待时间,并修正 alert-tests.yml 中期待恢复后立即触发的错误答案。观测会保留真实引擎输出。最终报告要明确 count 的新鲜度局限,以及本测试未验证的外部投递范围。