告警规则评估 PromQL 表达式,并持续跟踪表达式返回的标签集。Prometheus 判断每个告警是等待还是触发,Alertmanager 接收告警信息后负责通知路由、分组、静默与抑制。排查时应分别追踪这些环节:规则显示正在触发,是规则状态的证据,不能直接证明某个人已经收到消息。把状态和送达混为一谈,会使漏通知问题很难定位。
表达式返回元素就会激活告警候选项
表达式返回的每个元素代表一个活动告警候选项。queue_depth > 5 这样的比较会过滤不满足条件的数值;但加上 bool 修饰符之后,不满足条件的比较仍会留下数值为零的元素。告警规则依据元素是否存在来激活候选项,因此误用该修饰符,可能让数值已经为零的结果也进入告警流程。这是查询看似合理、规则却持续激活的常见原因。
标签定义告警身份。服务、队列与严重程度等稳定路由维度适合放在标签中,变化中的说明值则适合放在注解中。如果把当前队列大小写进标签,每次数值变化都可能创建一个新身份,重新开始等待。把大小写进注解则可以解释现场状态,同时保留原有告警身份。需要审阅的不只是阈值,还有标签和注解承担的职责。
等待时长通过评估时刻观察
配置 for: 2m 后,一个新出现的标签集会先等待,直到它在评估中持续活动两分钟。如果规则每分钟评估一次,第一分钟首次看到异常,就可能在第三分钟进入触发状态。引擎观察的是评估结果,不是样本之间连续发生的全部物理事实。因此,实际发现时间还包括等待下一次评估的时间,不能只用配置的等待时长计算最坏延迟。
省略 for 时,活动表达式可以在第一次评估就触发。这可能适合含义明确且必须立即处理的故障,但也意味着一个异常样本便足够触发。应根据失败语义主动选择,而不是由于忘记配置而意外采用默认行为。
若表达式在触发前不再返回该标签集,等待状态会清除。本例采用默认恢复行为,已经触发的告警也会在条件消失后清除。显式配置 keep_firing_for 可以在条件消失后继续保持一段触发时间,但本实验没有使用这个选项。不能把所有告警都描述为必须人工确认才能消除的事故记录;规则状态和事故管理系统的关闭流程是不同概念。
坏掉的样子
对缺失序列做阈值比较通常返回空结果。这可能让告警清除,但应用其实已经停止输出指标。应明确缺失是否需要独立规则,不能一律当成恢复。在测试阈值上下变化的同时,也要测试标签变更与样本缺失。语法检查只能证明文件能够解析,并不能揭示这类条件含义错误,更不能证明规则在真实数据中一定符合预期。
告警已经触发却没有页面通知,原因可能是静默、抑制、路由选择、分组等待或发送失败。这些机制属于通知链路,不会改变 Prometheus 对阈值的评估。应先查看活动告警标签,再查看 Alertmanager 匹配了哪个接收器,以及是否真正产生送达证据。延长 for 不会修复接收器配置错误,也不会自动补上路由所需但缺少的标签。
快速验证
把下面程序保存为 alert-state.py,在 PATH 中准备已安装的 promtool,或用 PROMTOOL 指定其可执行文件,再运行 python3 alert-state.py。完整程序在 promtool 3.14.0 与 Python 3.12.14 上通过,直接在本地评估真实规则,不需要 Docker,不启动监听端、Alertmanager 或外部通知目标,也不会向他人发送消息。
from pathlib import Path
from tempfile import TemporaryDirectory
import os
import shutil
import subprocess
promtool = shutil.which(os.environ.get("PROMTOOL", "promtool"))
if promtool is None:
raise SystemExit("Set PROMTOOL to an installed promtool executable")
promtool = str(Path(promtool).resolve())
tests = r"""evaluation_interval: 1m
rule_files:
- rules.yml
tests:
- interval: 1m
input_series:
- series: "queue_depth{queue=\"orders\"}"
values: "0 6 6 6 0 6 0 0"
promql_expr_test:
- expr: 'sum(ALERTS{alertname="BooleanTrap",alertstate="firing"}) or vector(0)'
eval_time: 0m
exp_samples:
- labels: "{}"
value: 1
- expr: "sum(ALERTS{alertname=\"QueueBacklog\",alertstate=\"pending\"}) or vector(0)"
eval_time: 1m
exp_samples:
- labels: "{}"
value: 1
- expr: "sum(ALERTS{alertname=\"QueueBacklog\",alertstate=\"firing\"}) or vector(0)"
eval_time: 2m
exp_samples:
- labels: "{}"
value: 0
- expr: "sum(ALERTS{alertname=\"QueueBacklog\",alertstate=\"firing\"}) or vector(0)"
eval_time: 3m
exp_samples:
- labels: "{}"
value: 1
- expr: "sum(ALERTS{alertname=\"QueueBacklog\"}) or vector(0)"
eval_time: 4m
exp_samples:
- labels: "{}"
value: 0
- expr: "sum(ALERTS{alertname=\"QueueBacklog\",alertstate=\"pending\"}) or vector(0)"
eval_time: 5m
exp_samples:
- labels: "{}"
value: 1
- expr: "sum(ALERTS{alertname=\"QueueBacklog\"}) or vector(0)"
eval_time: 6m
exp_samples:
- labels: "{}"
value: 0
- interval: 1m
input_series:
- series: 'queue_depth{queue="orders"}'
values: "6 6 stale"
promql_expr_test:
- expr: 'sum(ALERTS{alertname="QueueBacklog"}) or vector(0)'
eval_time: 2m
exp_samples:
- labels: "{}"
value: 0
"""
rules = r"""groups:
- name: queue-alerts
interval: 1m
rules:
- alert: QueueBacklog
expr: queue_depth{queue="orders"} > 5
for: 2m
labels:
severity: page
annotations:
summary: Orders queue remains above five
- alert: BooleanTrap
expr: queue_depth{queue="orders"} > bool 5
annotations:
summary: Deliberately incorrect boolean alert for this test
"""
with TemporaryDirectory(prefix="prom-rule-test-") as directory:
work = Path(directory)
(work / "tests.yml").write_text(tests, encoding="utf-8")
(work / "rules.yml").write_text(rules, encoding="utf-8")
subprocess.run([promtool, "test", "rules", "tests.yml"], cwd=work,
check=True, timeout=45)
预期输出是 SUCCESS。第一分钟告警进入等待,第二分钟尚未触发,第三分钟触发;第四分钟条件恢复,不再有活动的 ALERTS 元素。第五分钟第二次短促升高再次进入等待,第六分钟便恢复,因此这一波不会达到触发状态。两次变化共享同一个队列身份,可以直接检查等待是否在恢复后重新开始。
断言检查的是系统生成的 ALERTS 序列,其中 or vector(0) 仅用于在测试中把没有活动元素表示成可比较的零,不是生产告警表达式的一部分。刻意写错的 BooleanTrap 规则在第零分钟比较为假时仍然触发;独立的陈旧标记样本则在触发前清除等待状态。后者验证显式陈旧标记,不能代表所有抓取失败时间线。临时规则文件在结束后清理,实验验证的是给定时间线的状态转换;接收器匹配、分组延迟与实际消息送达,仍需使用目标 Alertmanager 配置单独测试,不能从规则通过推导出来。
延伸阅读
来源
- Prometheus: alerting rules,活动标签集、等待时长和系统生成的 ALERTS 序列,已核验 2026-10-15。
- Prometheus: unit testing rules,评估时间线与断言输入,已核验 2026-10-15。
- Prometheus: Alertmanager,通知分组、路由、静默和抑制,已核验 2026-10-15。