Nightingale 创建 VictoriaLogs 日志告警规则:LogsQL stats 管道语法与 rule_config 实战指南
【免费下载链接】nightingaleNightingale is to monitoring and alerting what Grafana is to visualization.项目地址: https://gitcode.com/GitHub_Trending/ni/nightingale
本文是 Nightingale(N9E)监控告警平台中VictoriaLogs 日志数据源告警规则创建的专项实战指南。全文围绕 create-alert-rule 技能(技能入口)中datasources/victorialogs.md的规范展开,讲解 LogsQL 聚合查询必须遵循的| stats管道语法、rule_config的 JSON 结构、trigger 表达式(exp)的变量引用规则,并结合 dskit/victorialogs/victorialogs.go 源码揭示底层/select/logsql/stats_query端点的实现原理。读完本文,你将能够手写并正确提交一条可稳定运行的 VictoriaLogs 日志告警规则,并学会排查"规则保存成功但永远无数据"这一类高频问题。
1. 定位:VictoriaLogs 告警规则的三个关键标识
在 Nightingale 中,VictoriaLogs 属于日志型(log type)数据源,创建告警规则时必须显式携带以下标识:
| 字段 | 取值 | 含义 |
|---|---|---|
prod | "logging" | 产品类型标记为日志场景 |
cate | "victorialogs" | 数据源类别,驱动告警引擎走 VictoriaLogs 查询路径 |
recover_config.judge_type | 0 | 恢复判定类型:0表示日志型(以查询结果有无/计数来判定),而指标型数据源(prometheus/mysql/pgsql/ck/tdengine)使用1 |
cate取值在 aiagent/tools/alert_rule.go 中被白名单校验,可选值包括prometheus/loki/elasticsearch/opensearch/tdengine/ck/mysql/pgsql/doris/victorialogs/host,victorialogs是其中明确支持的一类。用户在对话中表达"应用错误日志""VictoriaLogs 日志"等诉求时,Agent 应选择cate=victorialogs并走 create-alert-rule 的通用路径(SKILL.md 中 B-1 步骤)。
2. 核心约束:VictoriaLogs 告警查询必须使用| stats管道语法
VictoriaLogs 告警查询最终通过/select/logsql/stats_query端点执行。在 dskit/victorialogs/victorialogs.go 中,StatsQuery函数将query参数原样 POST 到该端点,并将响应解析为 Prometheus 风格的PrometheusResponse(status/data.resultType/data.result)。该端点只接受带| stats管道的聚合查询,不接受纯过滤查询——这是整篇文档最重要的约束。
- 错误写法(只会报错或返回空结果):
_msg:error service:payment AND level:error- 正确写法:
<filter condition> | stats <aggregation function>2.1 常用聚合场景与 LogsQL 写法
| 需求 | LogsQL |
|---|---|
| 最近 5 分钟错误日志条数 | _msg:error \| stats count() as value |
| 某服务错误日志条数 | service:payment AND level:error \| stats count() as value |
| 按服务分组统计条数 | level:error \| stats by (service) count() as value |
| 平均响应时间 | * \| stats avg(duration) as value |
| 多个聚合同时输出 | _msg:error \| stats count() as error_count, avg(duration) as avg_dur |
注意上表中 LogsQL 里的\|是 Markdown 表格转义写法,实际写入 JSON 时应还原为单个|。
2.2 四条关键规则
| stats之后的每个聚合函数都必须起别名(as value/as count等);- 别名即返回结果的字段名,告警引擎按别名匹配取值;
- 分组使用
stats by (field1, field2) ...; - 过滤部分可以是任意 LogsQL 过滤条件:
_msg:keyword、field:value、field:"value with space"、_time:5m等。
源码层面的佐证来自 dskit/victorialogs/victorialogs_test.go:测试用例TestVictoriaLogs_StatsQuery使用* | stats count() as total验证单点统计,TestVictoriaLogs_StatsQueryByField使用* | stats by (level) count() as cnt验证分组统计,TestVictoriaLogs_StatsQueryRange使用* | stats count() as total加step="5m"验证时间范围统计——这些正是文档中推荐写法的直接回归证据。此外,若需要获取"命中的日志总数"(如用于大盘展示),HitsLogs走/select/logsql/hits端点,与告警用的stats_query是两条不同的路径,不要把二者混淆。
3. triggers 硬性规则(必读)
VictoriaLogs 告警的触发条件(triggers)有三条硬性规则,违反任何一条都会导致规则"静默失效":
exp必填,且是告警引擎唯一求值的字段——一条没有exp的规则创建后永远不会触发,并且不会报任何错误;- 变量语法为
$<ref>.<stats输出别名>,例如$A.value > 20(对应stats count() as value);当只有一个 stats 输出时,可以省略别名直接写$A; mode固定为1(表达式模式,前端按原样展示 exp);多个条件用&&/||连接,例如"$A.value > 10 && $B.value < 5"。
这一"exp 是唯一求值入口、缺失即静默"的设计,要求使用者必须在提交前自检 exp 是否填写完整。
4. rule_config 结构详解
VictoriaLogs 告警规则的完整rule_config骨架如下:
{ "rule_config": { "queries": [ { "ref": "A", "query": "_msg:error | stats count() as value", "interval": 60 } ], "triggers": [ { "mode": 1, "exp": "$A.value > 20", "severity": 2, "recover_config": {"judge_type": 0} } ] } }通过create_alert_rule工具的通用路径创建时,需要把上述rule_config对象序列化为 JSON字符串传给rule_config_json参数(在 aiagent/tools/alert_rule.go 中,该参数必须是可解析的合法 JSON 对象,否则会返回带datasources/<cate>.md提示的解析错误)。调用格式可参考 SKILL.md 中 MySQL 示例的形态,将cate换成victorialogs、rule_config_json换成上文结构即可。
5. query 字段参考
| 字段 | 必填 | 说明 |
|---|---|---|
ref | ✅ | 查询引用名(如A),供 exp 引用 |
query | ✅ | LogsQL 查询,必须为<filter> \| stats <function>格式 |
interval | ❌ | 查询时间窗口,单位为总秒数(60=1 分钟,300=5 分钟)。不要写interval_unit |
关于interval的单位,SKILL.md 通用规则有补充说明:前端保存时会把值 × 单位换算成秒,读取时再反推显示单位;因此写"interval": 5, "interval_unit": "min"会被前端显示为 5 秒。工具侧有防御性兜底(误写interval_unit或小于 60 的裸值会自动换算成秒),但最佳实践仍是直接写对总秒数。
6. 完整示例:应用错误日志告警
以下是一条完整可提交的规则 JSON(可直接用于import_alert_rule批量导入接口,或作为create_alert_rule构造参考):
[{ "name": "Application error log alert", "note": "More than 20 error logs for the payment service in the last 1 minute", "prod": "logging", "cate": "victorialogs", "datasource_ids": [11], "datasource_queries": [{"match_type": 0, "op": "in", "values": [11]}], "disabled": 0, "prom_eval_interval": 30, "prom_for_duration": 60, "rule_config": { "queries": [ { "ref": "A", "query": "service:payment AND _msg:error | stats count() as value", "interval": 60 } ], "triggers": [ { "mode": 1, "exp": "$A.value > 20", "severity": 2, "recover_config": {"judge_type": 0} } ] }, "notify_version": 1 }]字段拆解:
name/note:规则名与告警说明(note 同时作为告警通知正文);datasource_ids: [11]与datasource_queries:将规则绑定到具体的 VictoriaLogs 数据源(ID 11 为示例,实际以list_datasources返回为准);prom_eval_interval: 30:每 30 秒评估一次;prom_for_duration: 60:持续 60 秒满足条件才触发(注意应大于eval_interval);query:过滤service=payment且_msg含error的日志,统计 1 分钟(interval: 60)内的条数;exp: "$A.value > 20":引用查询 A 的value别名,超过 20 即触发;severity: 2:Warning 级别(1=Critical,2=Warning,3=Info,默认 2)。
7. 故障排查
| 症状 | 原因 | 修复 |
|---|---|---|
| 规则保存成功但一直无数据 | 查询只有过滤条件,缺少\| stats | 追加\| stats count() as value或其他聚合 |
no stats clause错误 | 同上 | 同上 |
| 拿不到聚合值 | 聚合没有起别名 | 给聚合加as value,并让value与阈值一致 |
这三个症状本质上是同一类问题:stats_query端点只接受聚合查询(对应 StatsQuery 的实现约束),以及别名是引擎取值的唯一入口。排查顺序建议为:先确认 query 带| stats且聚合有别名 → 再确认 exp 的$A.<别名>与as <别名>完全一致 → 最后确认interval是总秒数、recover_config.judge_type为0。
8. 小结:VictoriaLogs 告警规则四步自检
- 标识:
prod="logging"、cate="victorialogs"、recover_config.judge_type=0; - 查询:
<filter> | stats <聚合> as <别名>,过滤部分任意,聚合必须起别名,必要时用stats by (...)分组; - 触发器:
mode=1,exp必填且格式为$<ref>.<别名> <比较符> <阈值>,多条件用&&/||连接; - 参数:
interval写总秒数,不写interval_unit。
按照这四步,配合 create-alert-rule 技能与 VictoriaLogs 驱动源码,即可在 Nightingale 中稳定落地日志驱动的告警规则。
【免费下载链接】nightingaleNightingale is to monitoring and alerting what Grafana is to visualization.项目地址: https://gitcode.com/GitHub_Trending/ni/nightingale
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考