Skip to content

告警规则 schema

告警规则存在 alert_rules 表,提交到 POST /v1/alert-rules。这一页是 wire format。真理之源:internal/manager/model/alert/model.go

wire 形状

json
{
  "rule_key": "host_cpu_high",
  "kind": "metric_raw",
  "name": "Host CPU pegged",
  "source_type": "ongrid_builtin",
  "scope_type": "host",
  "join_mode": "all",
  "severity": "warning",
  "enabled": true,
  "conditions": [
    { "expr": "node_cpu_usage_percent > 90" }
  ],
  "labels":      { "team": "sre", "service": "host" },
  "annotations": { "summary": "CPU on {{$labels.device_id}} above 90%" },
  "runbook_url": "https://wiki.example.com/runbooks/host-cpu",
  "notify_channel_ids": [12, 17],
  "notify_window_seconds": 600,
  "notify_min_fires": 3
}

字段参考

身份

字段类型必填描述
rule_keystring稳定的 lower_snake 标识符,用在 dedupe key 和 incident.rule 里。唯一。
namestring显示名。
enabledbool否(默认 true禁用的规则被 evaluator 跳过,并从 "active" 过滤里隐藏。

source / scope

字段类型必填描述
source_typeenumongrid_builtinprometheus_external。内置规则带规范 rule_key;外部规则来自导入的 Prometheus alerting rule 文件。
scope_typeenumhostglobalmonitoring_pipeline。决定 evaluator 按哪个维度分组 —— host 每个 device_id 出一条 incident;global 全系统一条 incident;monitoring_pipeline 给内部 pipeline 健康规则用。
join_modeenumall(每个 condition 都得匹配)、any(任一匹配)。只在 conditions 有多个元素时相关。

kind

kind 判别 evaluator 怎么解读 conditions。每个 kind 驱动一个不同的子 evaluator。

Kind状态做什么conditions 形状
metric_threshold仅 UI 输入友好表单。biz 层在保存时改写成 metric_raw;你在磁盘上永远看不到这种 kind。[{ "metric": "cpu_pct", "operator": ">=", "threshold": 90, "window": "5m", "for": "2m", "aggregator": "avg" }]
metric_raw上线任意 PromQL。ticker 驱动。[{ "expr": "rate(http_500[5m]) > 0.1" }]
metric_anomaly上线偏离滚动基线(z-score)。通过 PromQuerier ticker 驱动。[{ "metric": "node_cpu_usage_percent", "window": "1h", "z_threshold": 3.0 }]
metric_forecast上线线性外推(predict_linear)在未来窗口里穿过静态阈值。[{ "metric": "node_filesystem_avail_bytes", "window": "1h", "forecast_for": "24h", "below": 1073741824 }]
metric_burn_rate上线SLO 错误预算多窗口多 burn 率(Google SRE Workbook)。[{ "good": "sum(rate(http_2xx[1h]))", "total": "sum(rate(http_total[1h]))", "slo": 0.999, "long": "1h", "short": "5m" }]
log_match上线(Phase-B)LogQL 模式,命中即触发。[{ "expr": "{device_id=\"{{.device_id}}\"} |= \"panic\"" }]
log_volume上线(Phase-B)LogQL stream 速率超阈值。[{ "expr": "sum(rate({app=\"foo\"}[5m])) > 100" }]
trace_latency上线(Phase-B)TraceQL p95 / p99 超阈值(按服务)。[{ "service": "payments", "percentile": 95, "above_ms": 800, "window": "5m" }]
trace_error_rate上线(Phase-B)TraceQL error span 比例超阈值。[{ "service": "payments", "above_percent": 1.0, "window": "5m" }]

完整 Go 枚举在 model/alert/model.go

go
const (
    RuleKindMetricThreshold = "metric_threshold" // UI-only input
    RuleKindMetricAnomaly   = "metric_anomaly"
    RuleKindMetricForecast  = "metric_forecast"
    RuleKindMetricBurnRate  = "metric_burn_rate"
    RuleKindMetricRaw       = "metric_raw"
    RuleKindLogMatch        = "log_match"
    RuleKindLogVolume       = "log_volume"
    RuleKindTraceLatency    = "trace_latency"
    RuleKindTraceErrorRate  = "trace_error_rate"
)

遗留 kind(edge_offlineprom_queryingest_healthedge_absencehealth_ingestevent_internal)在保存时静默别名到 metric_raw

conditions

conditions 是数组。每个元素的形状取决于 kind —— 见上表。join_mode 决 定是否所有元素都得匹配(all)还是任一(any)。

metric_threshold(UI 表单)的每个 condition 是一个 RuleCondition

go
type RuleCondition struct {
    Metric     string  `json:"metric"`            // e.g. "cpu_pct"
    Operator   string  `json:"operator"`          // ">", ">=", "<", "<=", "=="
    Threshold  float64 `json:"threshold"`         // numeric trigger
    Window     string  `json:"window,omitempty"`  // e.g. "5m"
    For        string  `json:"for,omitempty"`     // sustain duration
    Aggregator string  `json:"aggregator,omitempty"` // avg / max / min
}

biz 层在保存时把它们编译成 metric_rawexpr,用规范闭合集主机指标 (node_cpu_usage_percentnode_memory_used_percentnode_filesystem_used_percentnode_load1……)。

severity

处理
info记录;通知由通道 match_severity_min 卡(多数通道跳过这个地板)
warning默认
critical一直通知,除非被静默

通道 match_severity_min 设为 warning 接受 warning + criticalcritical 只接受 critical。空匹配任何。

labels & annotations

自由 key/value 映射,JSON 存。

  • labels 在触发时追加到 incident 的 label 上,用于分组 / dedupe。常见: serviceteamenv
  • annotations 在触发时用 Go 模板语法基于 incident 快照渲染 —— 比如 summary: "CPU on {{$labels.device_id}} above 90%"

runbook

runbook_url 在 incident detail 和 chat 面 AI 调查报告旁逐字显示。用来链 到你的内部 runbook / playbook。

通知抑噪

字段类型默认描述
notify_window_secondsint0抑噪滚动窗口。0 禁用。
notify_min_firesint0窗口内触发至少这么多次才发通知。0 禁用。
notify_channel_idsint[]把通知钉到具体 channel ID(受每个 channel 自己的启用 / severity / scope 过滤约束)。空 = 全局路由器。

在尾随 notify_window_seconds 窗口里触发少于 notify_min_fires 次的规则 写一条 repeat_suppressed 事件到 timeline(让你看到抑噪起作用了)但 通知。两个都 0 = 抑噪关闭,每次触发按冷却 + 静默 + 抑制门发通知。

混合(一个 0、一个 >0)在 biz 层被拒:invalid_argument: notify_window_seconds and notify_min_fires must both be zero or both > 0

incident 生命周期

上面字段描述的是规则(触发定义)。规则触发产生一条incidentalert_incidents 表),有这些状态:

text
open ─┬─> acknowledged ─> resolved
      ├─> silenced ─> resolved
      └─> resolved

底层条件清掉一整个 evaluator 周期后 incident 自动 resolve。状态机在 internal/manager/biz/alert/ 里记录。

事件类型

每次状态转换记一行 alert_events。稳定的事件类型字符串:

事件类型何时
firing规则首次触发(incident 创建或重开)
repeat_suppressed冷却 / 抑噪窗口内触发
acknowledged用户点 Ack
silenced用户静默 N 小时
resolved条件清掉或用户点 Resolve
reopened已 resolve 的 incident 在删除前再次触发
note用户添加的评论
notification_sent一个 channel 投递成功
notification_failed一个 channel 投递失败
inhibited被更高 severity 的 active incident 抑制
ai_initial_diagnosis主动 AI investigator 的第一个看法,incident 首次触发时写

通道类型

POST /v1/notification-channels 接受:

类型channel_type来源
Webhookwebhookenv 或 UI
Slackslackenv 或 UI
Larksuite / 飞书feishuenv 或 UI
钉钉dingtalkenv 或 UI
企业微信wecom仅 UI
Telegramtelegram仅 UI

遗留 log channel 类型 2026-05 移除 —— alert_events 本身就是投递审计。

另见