告警表达式语法

夜莺 v9 告警表达式语法:用 `$A`、`$B` 引用查询结果做算术 / 比较 / 逻辑运算,构造任意业务/SQL/Prometheus 数据源的复合告警条件。

概述

告警表达式是夜莺通用的告警判定语言,可以引用一个或多个数据源查询的结果(用 $A$B…),用算术/关系/逻辑运算符合成布尔表达式,作为告警是否触发的判定。

侧栏路径:告警规则编辑页 → 查询条件区域 → 选用"表达式模式"。

适用场景:

  • 跨查询联合判定$A.qps > 1000 && $B.error_rate > 0.05(QPS 高 + 错误率高);
  • 比率类指标$B.failed_orders / $A.total_orders > 0.1(失败率 > 10%);
  • SQL / 业务库告警:MySQL 数据源查 SQL,按业务字段判定(详见 MySQL 告警举例);
  • PromQL 不易表达的逻辑:复合关系判定、字符串匹配、值范围等。

工作机制:基于标签的对齐

表达式的本质是时序数据之间的运算。运算逻辑:在相同 Label 集合的数据之间做计算,不同 Label 集合的数据无法直接运算。

时序数据格式:<metric name>{<label name>=<label value>, …} value

在告警规则的"查询条件"里有两个关键字段配合:

字段 作用
值字段 指定查询结果的哪一列作为运算"值"(相当于 Metric Name)
标签字段 指定查询结果的哪些列作为标签 — 决定 series 怎么对齐

举例:MySQL 查询返回结果:

product_name price
apple 100
banana 50

设置 值字段 = price标签字段 = product_name,会被识别成时序:

$A.price{product_name=apple}  100
$A.price{product_name=banana}  50

如果再有 $B 查询返回 cost 字段,只有 product_name 标签也对齐的 series才会和 $A.price 做运算($A.price - $B.cost)。

标签不一致时用"字段重命名"统一两侧的标签 key/value。

运算符全集

算术运算符

符号 说明 示例
+ 相加 $A + $B
- 相减 $A - $B
* 相乘 $A * $B
/ 相除 $A / $B
( ) 优先级 ($A - $B) * $C

关系运算符(产出布尔,告警判定的核心)

符号 说明 示例
== 等于 $A == 0
!= 不等于 $A.count != 0
> 大于 $A > $B
< 小于 $A < 0
>= 大于等于 $A >= 100
<= 小于等于 $A <= $B

逻辑运算符

符号 说明 示例
&& 与 — 两边都 true 才 true $A > 0 && $B < 10
|| 或 — 任一边 true 即 true $A + $B > 20 || $A * $B < 50

集合运算

符号 说明 示例
in 元素是否在数组里 $A in ["admin", "moderator"]
not in 元素不在数组里 $A not in [1, 2, 3]

字符串包含

符号 说明 示例
contains 字符串包含 $A contains $B,$A=“hello world” $B=“world” → true
not contains 字符串不包含 同上反逻辑

正则匹配

符号 说明 示例
matches 字符串是否匹配正则 $A matches "^[0-9]+$",$A=“123” → true

值范围

符号 说明 示例
between 在区间内(闭区间) between($A, [100, 200]),$A=155 → true
not between 不在区间内 not between($A, [100, 200])

注意between 适用数值类型(int / float),不支持字符串。

时间戳运算

表达式 说明 示例
now().Unix() 当前 Unix 秒数 now().Unix() - $A.timestamp > 60(超过 60s 未更新)

时间戳仅支持加减运算,不能乘除。

实操:常用告警表达式

场景 表达式
QPS 高 + 错误率高 $A.qps > 1000 && $B.error_rate > 0.05
失败率超过阈值 $B.failed / ($A.total + $B.failed) * 100 > 5
数据 60s 未更新(异常停止) now().Unix() - $A.last_update_ts > 60
状态属于异常集合 $A.status in ["FAILED", "TIMEOUT", "ERROR"]
订单金额超出区间 between($A.amount, [10000, 1000000]) == false
多条件联合(订单已取消且金额大) $A.status == "Order Canceled" && $A.total_amount > 100

更详细的 SQL 类业务告警场景见 MySQL 告警举例

常见问题

Q1:表达式可以引用几个查询?

A:理论上没硬上限,但建议 ≤ 3 个$A / $B / $C)。查询数越多对齐越复杂、表达式越难维护、性能开销也越大。

Q2:两个查询的标签不一致,表达式不生效,怎么办?

A:常见对齐技巧:

  • 在查询本身的"标签字段"里对齐字段名(重命名字段统一);
  • 用聚合把不需要的标签去掉(如 PromQL 用 sum without (instance));
  • 检查返回数据的实际标签集合(数据预览功能可看)。

Q3:== 比浮点数为什么经常不准?

A:浮点比较的常见陷阱。例如 0.1 + 0.2 == 0.3 在大多数语言里是 false。建议用:

  • 范围判定:between($A, [0.299, 0.301])
  • 差值阈值:$A - 0.3 < 0.001 && $A - 0.3 > -0.001

Q4:表达式里能调用自定义函数吗?

A:目前不支持用户定义函数。内置的运算符 + 函数(如 betweennow()containsmatches)覆盖绝大多数场景。需要复杂逻辑建议在数据源那边(SQL/PromQL)就把结果算好,表达式里只做布尔判定。

参考资料

更新时间 2026-05-20

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云