Aviator 表达式指南
概述
Aviator 是一个高性能的 Java 表达式引擎,1Duty 使用它来对告警 JSON 数据进行动态匹配、计算和修改。通过 Aviator 表达式,您可以编写灵活的规则来控制告警的降噪、聚合、分派和数据预处理流程。
Aviator 表达式在 1Duty 中的核心特性:
- 安全沙箱 - 禁止访问 Java 类,循环上限 100 次,执行超时 5 秒
- 字段直接引用 - 直接使用字段名引用告警 JSON 中的数据
- JSON 原地修改 - 通过
json.xxx = yyy语法可以直接修改告警 JSON,修改会传递到外部 - 丰富的内置函数 - 正则匹配/提取/替换、字符串操作、HTML 清理等
在 1Duty 中的使用场景
Aviator 表达式在以下功能中使用,每个场景对表达式的返回值要求不同:
| 使用场景 | 位置 | 返回值要求 | 说明 |
|---|---|---|---|
| 排除规则 | 集成详情 > 降噪配置 > 排除规则 | 返回 true/false |
返回 true 的告警将被丢弃 |
| 静默策略 | 集成详情 > 降噪配置 > 静默策略 | 返回 true/false |
返回 true 的告警将被静默(不发通知) |
| 自动关闭 | 集成详情 > 降噪配置 > 自动关闭 | 返回 true/false |
返回 true 的告警对应的事件将被自动关闭 |
| 聚合规则 | 集成详情 > 降噪配置 > 告警聚合 | 返回 字符串 |
返回字符串作为聚合 Key,相同 Key 合并到同一事件 |
| 分派条件 | 集成详情 > 分派策略 > 条件过滤 | 返回 true/false |
返回 true 则匹配该分派策略 |
| 数据预处理 | 集成编辑 > Webhook > 数据预处理 | 返回 json 对象 |
修改 JSON 字段值,返回修改后的 json |
| 主动探测条件 | 主动探测 > 触发条件 | 返回 true/false |
返回 true 则判定探测异常并触发告警 |
基本语法
引用字段
系统接收到告警后,会将 JSON 数据的所有字段展开到表达式上下文中。你可以直接使用字段名来引用告警中的任意字段,嵌套字段用点号访问。
假设收到以下告警 JSON:
{
"title": "CPU 使用率过高",
"severity": "CRITICAL",
"source": "prometheus",
"host": "web-server-01",
"description": "CPU usage is 95%, threshold 80%",
"labels": {
"env": "production",
"region": "cn-east-1",
"team": "infra"
},
"value": 95.2,
"status": "firing"
}
| 表达式 | 含义 | 结果 |
|---|---|---|
title | 引用顶层字段 | "CPU 使用率过高" |
severity | 引用告警级别 | "CRITICAL" |
value | 引用数值字段 | 95.2 |
labels.env | 引用嵌套字段(点号访问) | "production" |
labels.region | 引用嵌套字段 | "cn-east-1" |
notExist | 不存在的字段返回 nil | nil |
比较运算符
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
== | 等于 | severity == 'CRITICAL' | true |
!= | 不等于 | severity != 'INFO' | true |
> | 大于 | value > 90 | true |
>= | 大于等于 | value >= 95.2 | true |
< | 小于 | value < 50 | false |
<= | 小于等于 | value <= 80 | false |
逻辑运算符
| 运算符 | 说明 | 示例 | 结果 |
|---|---|---|---|
&& | 与(AND) | severity == 'CRITICAL' && value > 90 | true |
|| | 或(OR) | severity == 'INFO' || value > 90 | true |
! | 非(NOT) | !(severity == 'INFO') | true |
字符串函数
| 函数 | 说明 | 示例 |
|---|---|---|
string.contains(s, sub) | 字符串是否包含子串 | string.contains(title, 'CPU') → true |
string.startsWith(s, prefix) | 前缀匹配 | string.startsWith(host, 'web-') → true |
string.endsWith(s, suffix) | 后缀匹配 | string.endsWith(host, '-01') → true |
string.length(s) | 字符串长度 | string.length(title) → 8 |
string.substring(s, start, end) | 截取子串 | string.substring(host, 0, 3) → "web" |
正则表达式函数
1Duty 提供了三个自定义正则函数,底层使用 RE2/J 引擎确保安全(不会因正则回溯导致性能问题):
| 函数 | 说明 | 示例 |
|---|---|---|
regex_match(text, pattern) | 是否匹配正则 | regex_match(title, '.*CPU.*') → true |
regex_extract(text, pattern) | 提取第一个捕获组(无捕获组则返回完整匹配) | regex_extract(description, 'is (\d+)%') → "95" |
regex_replace(text, pattern, replacement) | 替换所有匹配 | regex_replace(title, '过高', '异常') → "CPU 使用率异常" |
其他内置函数
| 函数 | 说明 | 示例 |
|---|---|---|
html2text(html) | 去除 HTML 标签 | html2text('<b>Error</b>') → "Error" |
nil 安全判断
当引用的字段可能不存在时,建议先做 nil 判断,避免执行错误:
## 安全判断字段是否存在
labels != nil && labels.env == 'production'
## 结合默认值(三元表达式)
severity != nil ? severity : 'UNKNOWN'
JSON 原地修改(核心特性)
这是 1Duty 中 Aviator 表达式最强大的特性之一。在数据预处理场景中,Aviator 脚本可以通过 json.xxx = yyy 语法直接修改告警的 JSON 数据,修改会传递到外部,后续的告警处理流程将使用修改后的数据。
只有在数据预处理(Aviator 脚本规则)中才需要使用 JSON 修改功能。排除规则、静默策略等场景只需要返回 true/false。
工作原理
- 读取字段 - 直接使用字段名,如
title、severity、labels.env - 修改字段 - 使用
json.字段名 = 新值,如json.title = '[P0] ' + title - 返回结果 - 脚本最后需要
return json;返回修改后的 JSON 对象
这意味着你可以在 Webhook 接收到告警后、系统处理之前,对告警数据进行任意修改和增强。
数据预处理示例
示例 1:给标题添加前缀
json.title = '[P0] ' + title;
return json;
示例 2:从描述中提取错误码并添加为新字段
let code = regex_extract(description, 'code: (\d+)');
if code != nil {
json.error_code = code;
}
return json;
示例 3:根据标题关键词自动设置严重级别
if string.contains(title, 'OOM') || string.contains(title, '宕机') {
json.severity = 'CRITICAL';
} elsif string.contains(title, '超时') {
json.severity = 'WARNING';
}
return json;
示例 4:清理 HTML 描述并提取关键信息
json.description = html2text(description);
let ip = regex_extract(description, '(\d+\.\d+\.\d+\.\d+)');
if ip != nil {
json.source_ip = ip;
}
return json;
示例 5:修改嵌套字段
if labels != nil && labels.env == 'staging' {
json.title = '[Staging] ' + title;
}
return json;
各场景完整示例
场景一:排除规则 / 静默策略 / 自动关闭(返回 true/false)
这些场景中,表达式返回 true 表示命中规则,返回 false 表示不命中。
## 排除 INFO 级别的告警
severity == 'INFO'
## 排除测试环境的告警
labels != nil && labels.env == 'test'
## 静默包含特定关键词的告警
string.contains(title, '健康检查') || string.contains(title, 'heartbeat')
## 自动关闭已恢复的告警
status == 'resolved' || status == 'ok'
## 组合条件:排除低级别 + 特定来源
severity == 'INFO' && source == 'prometheus' && value < 50
## 使用正则匹配
regex_match(title, '(?i).*test.*|.*debug.*')
场景二:聚合规则(返回字符串作为聚合 Key)
表达式返回字符串,系统对结果取 MD5 后作为聚合 Key。相同 Key 的告警会被合并到同一事件。
## 按标题聚合(等效于智能聚合)
title
## 按标题 + 主机名聚合
title + '_' + host
## 按来源 + 级别聚合
source + '_' + severity
## 使用正则提取关键信息聚合
regex_extract(title, '(\S+)\s+') + '_' + severity
场景三:分派策略条件(返回 true/false)
在分派策略中,Aviator 条件用于判断告警是否匹配该策略。
## 按严重级别分派
severity == 'CRITICAL'
## 按来源 + 标签分派
source == 'prometheus' && labels != nil && labels.team == 'infra'
## 按标题关键词分派到不同团队
string.contains(title, '数据库') || string.contains(title, 'MySQL')
场景四:主动探测条件(返回 true/false)
在主动探测中,可用变量包括 status_code、response_time、body_size、body_text 等。
## 状态码不是 200 或响应时间超过 3 秒
status_code != 200 || response_time > 3000
## 响应体包含错误关键词
string.contains(body_text, 'error') || string.contains(body_text, 'failed')
## 状态码正常但响应时间过长
status_code == 200 && response_time > 5000
安全限制
为了保障系统安全和稳定,1Duty 对 Aviator 表达式施加了以下限制:
| 限制项 | 限制值 | 说明 |
|---|---|---|
| 脚本最大长度 | 10,000 字符 | 超出长度的脚本将被拒绝 |
| 执行超时 | 5 秒 | 超时的脚本将被终止 |
| 循环上限 | 100 次 | for/while 循环最多执行 100 次 |
| Java 类访问 | 完全禁止 | 无法访问任何 Java 类 |
| 属性缺失处理 | 返回 nil | 访问不存在的字段返回 nil 而非报错 |
常见错误
| 错误信息 | 原因 | 修复方法 |
|---|---|---|
| Could not find variable: xxx | 字段名拼写错误或字段不存在 | 确认 JSON 中有该字段,或加 nil 判断 |
| NullPointerException | 对 nil 值进行操作 | 加 field != nil && ... 前置判断 |
| ClassCastException | 类型不匹配(如数值与字符串比较) | 确保比较类型一致 |
| Timeout | 表达式执行超过 5 秒 | 简化表达式,减少循环 |
在配置规则时,建议使用每个配置页面内置的「测试」功能来验证表达式的正确性。输入示例 JSON 数据,点击测试按钮即可查看表达式的执行结果。