告警应让读者知道第一步该查什么,而不只是展示一个红色标记。它需要说明观察到的条件、受影响范围、持续时间、负责团队,以及接下来要看的证据。这些内容属于规则的可观察行为,应当和触发条件一起测试,不能等事故发生以后才把通知文案当作装饰补上。
把观察与解释分开
一次 scrape 失败,说明 Prometheus 没有成功收集目标的指标,并不能独立证明公共 API 已经不可用。服务可能仍能处理用户请求,但指标处理器失败;也可能指标采集正常,业务操作却一直报错。应该组合面向用户症状的探测与内部证据,并在告警里准确说明本次到底是哪一种观察触发,避免把采集失败直接写成业务停机。
最近发布是有价值的排查线索,却不是因果证明。证书到期、依赖故障、资源短缺或网络异常,都可能发生在没有部署的时刻。把相关变更记录和状态、日志、用户侧指标放在一起比较;在没有建立关联之前,不要把最近一次提交自动标记为根因。好的上下文帮助缩小范围,而不是提前替调查下结论。
保持身份稳定,让上下文可用
Prometheus 根据表达式返回的每组标签识别告警实例。服务、团队等稳定路由属性可以放进 labels;当前数值、解释文字和 runbook 链接放进 annotations。如果把不断变化的时间戳或测量值塞进标签,告警身份也会不断改变,pending 状态可能始终等不到持续时间结束。注解可以随情况变化提供解释,而不重新定义这是否还是同一条告警。
runbook 开头应给出可访问、只读的检查:先看目标的具体采集错误,再比较指标端点和用户请求路径,最后关联相关日志与变更记录。同时写清正常时应看到什么、看不到时进入哪个分支、什么时候升级求助。通知链接不要带凭据或敏感查询参数,还要实际确认值班读者有权访问目标页面。链接存在但读者无法打开,同样不能算有效的排查入口。
坏掉的样子
规则可能正确触发,却没有路由到任何接收人;也可能链接的文档已被删除,或者聚合时丢失了本应定位实例的标签。噪声阈值则会为不需要决策的短暂现象反复打断人。只有确实需要及时人工判断时才使用 page,其他情况应进入合适的看板、工单或自动处理。Alertmanager 的分组和抑制,与 Prometheus 判断规则是否 firing,是两段需要分别验证的流程。
可选的 for 要求表达式在连续评估中持续保持 active,达到指定时长后才进入 firing。它不是滑动平均窗口,也没有包含通知发送的等待时间。如果表达式不再产生该标签集合,本例规则就会停止活跃。尤其要注意,stale 或完全缺失的序列不是显式的零,因此告警安静不等于业务恢复;采集链路和预期目标清单需要独立监控,不能把“看不见”解释为健康。
快速验证
使用 Prometheus 发行包中的 promtool;下面实验已用 3.14.0 执行。在一个空的本地目录里,把接下来的两个代码块分别保存成 alerts.yml 和 alerts.test.yml。规则故意只描述指标采集可用性,不代表 API 可用性 SLO。severity 和 team 是测试标签,执行测试不会发送通知或改动任何现有告警配置。
groups:
- name: api-scrape
rules:
- alert: APIScrapeUnavailable
expr: up{job="api"} == 0
for: 2m
labels:
severity: page
team: platform
annotations:
summary: 'Cannot scrape {{ $labels.job }} on {{ $labels.instance }}'
description: 'up == 0 for 2m. Inspect the target error and /metrics handler; scrape failure alone does not prove API downtime.'
runbook_url: https://www.xbcatm.com/posts/a-purpose-built-health-check-is-worth-keeping/
测试使用一分钟间隔的人工样本。零分钟的失败先进入 pending,到第二分钟才 firing;第三分钟恢复后,后面再次失败仍须等待新的持续周期。预期注解不仅核对有没有告警,还核对展开后的目标名称、排查文字和 runbook URL,防止规则通过而通知内容已经失去用途。
rule_files:
- alerts.yml
evaluation_interval: 1m
tests:
- name: sustained failure, recovery, and recurrence
interval: 1m
input_series:
- series: 'up{job="api",instance="api.example:9090"}'
values: '0 0 0 1 0 0 0'
alert_rule_test:
- eval_time: 0m
alertname: APIScrapeUnavailable
exp_alerts: []
- eval_time: 1m
alertname: APIScrapeUnavailable
exp_alerts: []
- eval_time: 2m
alertname: APIScrapeUnavailable
exp_alerts: &firing
- exp_labels:
job: api
instance: api.example:9090
severity: page
team: platform
exp_annotations:
summary: 'Cannot scrape api on api.example:9090'
description: 'up == 0 for 2m. Inspect the target error and /metrics handler; scrape failure alone does not prove API downtime.'
runbook_url: https://www.xbcatm.com/posts/a-purpose-built-health-check-is-worth-keeping/
- eval_time: 3m
alertname: APIScrapeUnavailable
exp_alerts: []
- eval_time: 5m
alertname: APIScrapeUnavailable
exp_alerts: []
- eval_time: 6m
alertname: APIScrapeUnavailable
exp_alerts: *firing
promql_expr_test:
- expr: 'ALERTS{alertname="APIScrapeUnavailable",alertstate="pending"}'
eval_time: 1m
exp_samples:
- labels: 'ALERTS{alertname="APIScrapeUnavailable",alertstate="pending",instance="api.example:9090",job="api",severity="page",team="platform"}'
value: 1
- name: transient failure does not fire
interval: 1m
input_series:
- series: 'up{job="api",instance="api.example:9090"}'
values: '1 0 1 1'
alert_rule_test:
- eval_time: 2m
alertname: APIScrapeUnavailable
exp_alerts: []
- eval_time: 3m
alertname: APIScrapeUnavailable
exp_alerts: []
- name: stale series is not an explicit zero
interval: 1m
input_series:
- series: 'up{job="api",instance="api.example:9090"}'
values: '0 stale _ _'
alert_rule_test:
- eval_time: 2m
alertname: APIScrapeUnavailable
exp_alerts: []
promql_expr_test:
- expr: 'ALERTS{alertname="APIScrapeUnavailable"}'
eval_time: 2m
exp_samples: []
在同一目录执行:
promtool --version
promtool check rules alerts.yml
promtool test rules alerts.test.yml
规则检查和单元测试都应报告 SUCCESS。用例覆盖持续失败、pending 状态、恢复、再次触发、短暂失败,以及在触发前变为 stale 的目标。stale 用例刻意证明检测盲区,而不是把缺失样本冒充健康。全部预期标签和注解都必须相符;例如实例标签丢失或 runbook 地址变化,测试都不应默默通过。
再做一次反例检查:只修改规则里的 runbook URL,不改测试期望,测试应当失败;恢复原值后重新通过。把 for 从两分钟改为一分钟,应让第一分钟的断言失败;更小的改动可能在这个评估间隔下不可见。这样的验证能证明规则评估和说明性上下文确实受检,但不证明真实 scrape、文档访问权限、Alertmanager 分组或呼叫设备送达。生产启用前还要沿这些真实链路分别演练,不能把本地 SUCCESS 当作整条值班链路已经验收。
延伸阅读
来源
- Prometheus:告警规则,标签身份、等待时间和模板注解,已核验 2026-09-09。
- Prometheus:规则单元测试,人工样本、stale 标记和预期告警输出,已核验 2026-09-09。
- Google SRE:监控分布式系统,可执行的呼叫、症状和低噪声监控,已核验 2026-09-09。