Flashduty 不但是一个一站式告警 OnCall 平台,也提供告警引擎能力,可以对接各种监控系统并执行告警判定。本文说明 Flashduty 告警规则中多个 PromQL 查询的使用方式。
多个 PromQL 查询主要有两类场景:一类是多个指标要参与同一次联合运算,另一类是多个指标只是放在同一条规则里并行判断。两者的配置方式不同,尤其要注意标签是否一致。
核心要点
- 多指标联合运算适合使用「阈值计算」,前提是参与运算的多个查询结果标签完全一致。
- 多指标之间没有关系、标签也不一致时,不适合做阈值计算,应该优先拆成多条告警规则。
- 如果多个查询属于同一类对象、为了管理方便必须放在一起,可以使用「数据存在」模式并行计算。
- 并行告警时如果需要在事件里带上指标名,可以用 PromQL 的
label_replace额外生成metric_name标签。
场景一:多个指标联合运算
多个指标联合运算的关键是:这些指标共同描述同一个监控对象,而且需要同时满足条件才告警。
举个例子,硬盘 IO.UTIL 大于 99%,同时写延迟超过 10ms 才告警,可以这样配置:

当然了,也可以直接在一个 Promql 中来写,比如
irate(diskio_io_time[2m])/10 > 99 and irate(diskio_write_time[2m])/irate(diskio_writes[2m]) > 10。我这里故意拆成两个查询条件只是为了演示功能。
这个配置可以达到多指标联合运算的效果,但有一个前提:两个查询得到的结果,其标签必须完全一致。
原因很简单:只有标签一致,才意味着参与运算的数据指向同一个监控对象。比如同一块磁盘的利用率和写延迟可以联合判断;但 CPU 指标和磁盘指标的标签通常不同,就不能直接拿来做同一次阈值计算。
| 使用条件 | 说明 |
|---|---|
| 结果标签一致 | 多个查询结果能一一对应到同一个对象 |
| 指标之间存在业务关系 | 例如 IO 利用率和写延迟共同描述磁盘压力 |
| 需要同时满足条件才告警 | 例如 $A > 99 且 $B > 10 |
如果这些条件不成立,就不要强行把多个查询塞进阈值计算里。
场景二:多个指标并行告警
如果多个指标之间没有关系,就不应该使用「阈值计算」做联合运算。更稳妥的做法是拆成多条告警规则,让每条规则只负责一个清晰的告警语义。
也有一种折中方式:不使用「阈值计算」,改用「数据存在」告警模式。比如:

上图中两个查询条件,一个是 mem_available_percent,另一个是 net_bits_recv。这两个指标标签不同,没法联合运算,但可以在「数据存在」模式下并行计算。
不过,这种方式并不是首选。更推荐的方式仍然是拆成多个告警规则,因为每条规则的告警语义更清晰,后续也更容易维护、静默、路由和复盘。
只有在多个查询条件很像、属于同一类东西,拆成多个告警规则会明显增加管理成本时,才建议使用这种并行模式。
如何在并行告警中带上指标名
在「数据存在」模式下并行计算时,产生的告警事件里可能没有指标名字。这里有一个 workaround:利用 label_replace 函数额外生成一个 label,让它和 __name__ 的值保持一致。
示例 PromQL 如下:
label_replace(mem_available_percent{ident="dev-backup-01"}, "metric_name", "$1", "__name__", "(.*)") > 0

之后产生的告警事件中,会有 metric_name 这个 label,值就是指标名字。这样后续在通知模板、事件详情、筛选和分析里,都能更容易看出是哪一个指标触发了告警。
选择建议
| 需求 | 推荐方式 | 原因 |
|---|---|---|
| 多个指标共同判断同一个对象 | 阈值计算 | 标签一致时可以做联合运算 |
| 多个指标互不相关 | 拆成多条告警规则 | 告警语义清晰,后续治理更简单 |
| 多个查询属于同一类,拆分后管理成本高 | 数据存在模式 | 可以并行判断,但要补充指标名标签 |
FAQ
Q1:多个 PromQL 查询一定要标签完全一致吗? A:如果要参与阈值计算或联合运算,标签需要完全一致。否则系统无法判断不同查询结果是否对应同一个监控对象。
Q2:CPU 指标和磁盘指标能不能放进同一条规则? A:技术上可以在「数据存在」模式下并行放置,但不适合用阈值计算做联合运算。更推荐拆成不同告警规则。
Q3:为什么并行告警时建议补 metric_name?
A:因为多个查询放在同一条规则中时,事件里需要清楚标识到底是哪一个指标触发了告警。metric_name 可以把这个信息显式带出来。
结语
多个 PromQL 查询不是越集中越好。判断方式很直接:如果多个指标共同描述同一个对象,并且标签一致,可以使用阈值计算;如果只是多个指标并行判断,优先拆成多条规则;如果确实要放在一起,则使用数据存在模式,并通过 label_replace 补足指标名信息。