夜莺社区的朋友如果问时序库的选型,我一般都会推荐 VictoriaMetrics。除了性能、稳定性、集群扩展能力之外,另一个重要原因是 VictoriaMetrics 扩展了 PromQL,提供了 MetricsQL,增强了指标查询和告警表达能力。
下面这个告警场景,就很适合用 MetricsQL 来解决。
核心要点摘要
- 本文讨论的场景是:某个指标每分钟上报一次,如果 5 分钟内有 3 次大于阈值
x,就触发告警。 - MetricsQL 可以用
count_gt_over_time(interface_status[5m], x) >= 3直接表达这个条件。 - 同一类函数还包括
count_le_over_time、count_ne_over_time、count_eq_over_time,分别用于统计小于等于、不等于、等于某个值的次数。 - 这类函数适合处理“窗口期内满足条件的次数”问题,比单纯判断瞬时值或窗口最大值更贴近部分告警需求。
- 如果使用 PromQL,也可以尝试表达类似逻辑,但写法通常不如 MetricsQL 直观。
需求:5 分钟内超过阈值 3 次就告警
某个指标( 假设指标名字是 interface_status )每分钟上报一次,如果 5 分钟内有 3 次大于 x 的值,就报警。
这个需求的关键点不是“当前值是否大于 x”,也不是“5 分钟内最大值是否大于 x”,而是“5 分钟这个时间窗口里,满足大于 x 条件的样本数量是否达到 3 次”。
解法:使用 count_gt_over_time
如果使用 PromQL,就比较难写了,而 MetricsQL 就很简单,如下:
count_gt_over_time(interface_status[5m], x) >= 3
看到这个写法,基本能直观理解其含义了 count_gt_over_time(series_selector[d], gt) 函数有两个参数,一个是 range-vector,一个是标量 gt,表示在 range-vector 中大于 gt 的个数,如果大于等于 3,就报警。除了 count_gt_over_time 函数之外,还有 count_le_over_time、count_ne_over_time、count_eq_over_time 道理相同。
| 函数 | 语义 | 典型用途 |
|---|---|---|
count_gt_over_time(series_selector[d], gt) |
统计时间窗口内大于 gt 的样本数 |
多次超过阈值才告警 |
count_le_over_time(series_selector[d], le) |
统计时间窗口内小于等于 le 的样本数 |
多次低于或等于阈值才告警 |
count_ne_over_time(series_selector[d], ne) |
统计时间窗口内不等于 ne 的样本数 |
状态值多次偏离预期才告警 |
count_eq_over_time(series_selector[d], eq) |
统计时间窗口内等于 eq 的样本数 |
状态值多次命中特定值才告警 |
这类函数适合什么告警
这类函数适合“窗口期内命中次数”型告警。例如:
- 某个接口状态在 5 分钟内多次异常,而不是偶发一次就告警。
- 某个状态码连续或多次等于异常值,才认为故障成立。
- 某个业务指标在一个时间窗口内多次低于阈值,才通知值班人员。
它的优势是表达清晰:告警条件直接对应“时间窗口、比较条件、命中次数”这三个要素。
思考
假设我们知道原始数据上报频率,如果使用 promql 来实现上述需求,应该怎么写呢?欢迎评论区留言分享 :)
Flashduty 告警引擎补充
最近我们开放了 Flashduty 的告警引擎能力,可以直接对接各类时序库、数据库、ClickHouse、ElasticSearch、Loki 等日志库,对数据做异常判断,直接生成告警事件。换句话说,不再需要夜莺、Alertmanager、Elastalert 等告警引擎,Flashduty 就可一肩挑。在线体验地址:https://console.flashcat.cloud/ 菜单入口:「告警管理」。截图如下:

总结
MetricsQL 的价值之一,是把一些原本不太好写的告警逻辑变得直观。对于“5 分钟内超过阈值 3 次”这类需求,count_gt_over_time 能把时间窗口、比较条件和次数判断放在一个表达式里。
如果你的告警规则里经常出现“偶发一次不要告警,多次出现才告警”的需求,可以重点关注 count_gt_over_time、count_le_over_time、count_ne_over_time、count_eq_over_time 这几个函数。
FAQ
Q1:count_gt_over_time(interface_status[5m], x) >= 3 表达的是什么?
A:它表示在最近 5 分钟的样本中,interface_status 大于 x 的次数是否大于等于 3。
Q2:为什么不用最大值判断?
A:最大值只能说明窗口内是否出现过一次高值,不能说明出现了几次。本文场景关注的是命中次数,所以更适合用 count_gt_over_time。
Q3:这 4 个函数只能用于告警吗?
A:不只用于告警。它们也可以用于查询分析,只是窗口期次数判断在告警规则里特别常见。
