Схема правила алерта
Правила алертов хранятся в таблице alert_rules и отправляются в POST /v1/alert-rules. Эта страница — wire-формат. Source of truth: internal/manager/model/alert/model.go.
Wire-форма
{
"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_key | string | да | Стабильный lower_snake идентификатор, используемый в dedupe-ключах и incident.rule. Уникальный. |
name | string | да | Display name. |
enabled | bool | нет (по умолчанию true) | Отключённые правила пропускаются evaluator'ом и скрыты из «active» фильтров. |
Source / scope
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
source_type | enum | да | ongrid_builtin, prometheus_external. Встроенные правила несут канонические значения rule_key; внешние правила приходят из импортированного Prometheus alerting rule-файла. |
scope_type | enum | да | host, global, monitoring_pipeline. Определяет, по какому измерению evaluator группирует — host производит один incident на device_id; global производит один incident system-wide; monitoring_pipeline для internal pipeline-health правил. |
join_mode | enum | да | all (каждое условие должно совпадать), any (любое условие совпадает). Релевантно только когда conditions имеет больше одного элемента. |
Kind
kind дискриминирует, как evaluator интерпретирует conditions. Каждый kind управляет другим sub-evaluator'ом.
| Kind | Статус | Что он делает | Форма conditions |
|---|---|---|---|
metric_threshold | UI-only вход | Дружественная форма. Biz-слой переписывает её в metric_raw во время сохранения; вы никогда не увидите этот kind на диске. | [{ "metric": "cpu_pct", "operator": ">=", "threshold": 90, "window": "5m", "for": "2m", "aggregator": "avg" }] |
metric_raw | live | Произвольный PromQL. Ticker-driven. | [{ "expr": "rate(http_500[5m]) > 0.1" }] |
metric_anomaly | live | Отклонение от rolling baseline (z-score). Ticker-driven через PromQuerier. | [{ "metric": "node_cpu_usage_percent", "window": "1h", "z_threshold": 3.0 }] |
metric_forecast | live | Линейная экстраполяция (predict_linear), пересекающая статический порог в будущем окне. | [{ "metric": "node_filesystem_avail_bytes", "window": "1h", "forecast_for": "24h", "below": 1073741824 }] |
metric_burn_rate | live | SLO error-budget multi-window multi-burn-rate (Google SRE Workbook). | [{ "good": "sum(rate(http_2xx[1h]))", "total": "sum(rate(http_total[1h]))", "slo": 0.999, "long": "1h", "short": "5m" }] |
log_match | live (Phase-B) | LogQL-паттерн, который при попадании срабатывает. | [{ "expr": "{device_id=\"{{.device_id}}\"} |= \"panic\"" }] |
log_volume | live (Phase-B) | LogQL stream rate выше порога. | [{ "expr": "sum(rate({app=\"foo\"}[5m])) > 100" }] |
trace_latency | live (Phase-B) | TraceQL p95 / p99 выше порога для сервиса. | [{ "service": "payments", "percentile": 95, "above_ms": 800, "window": "5m" }] |
trace_error_rate | live (Phase-B) | TraceQL error span fraction выше порога. | [{ "service": "payments", "above_percent": 1.0, "window": "5m" }] |
Полный Go-enum живёт в model/alert/model.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"
)Legacy kinds (edge_offline, prom_query, ingest_health, edge_absence, health_ingest, event_internal) молча aliased к metric_raw при сохранении.
Conditions
conditions — массив. Форма каждого элемента зависит от kind — см. таблицу выше. join_mode решает, должны ли все элементы совпадать (all) или любой (any).
Для metric_threshold (UI-форма), каждое условие — это RuleCondition:
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_raw expr во время сохранения, используя канонические closed-set host-метрики (node_cpu_usage_percent, node_memory_used_percent, node_filesystem_used_percent, node_load1, ...).
Severity
| Значение | Обработка |
|---|---|
info | записывается; уведомления гейтятся match_severity_min канала (большинство каналов пропускают этот floor) |
warning | по умолчанию |
critical | всегда уведомляется, если не silenced |
match_severity_min канала, установленный в warning, принимает warning + critical; critical принимает только critical. Пустое совпадает с любым.
Labels & annotations
Свободно-формные key/value мапы, хранящиеся как JSON.
labelsдописываются к labels инцидента во время срабатывания и используются для группировки / дедупликации. Часто:service,team,env.annotationsшаблонизируются во время срабатывания, используя синтаксис Go template с incident-snapshot — например,summary: "CPU on {{$labels.device_id}} above 90%".
Runbook
runbook_url показывается дословно в детали инцидента и на chat-поверхности рядом с AI investigation отчётом. Используйте его, чтобы линковать на ваши внутренние runbook / playbooks.
Дампенинг уведомлений
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
notify_window_seconds | int | 0 | Rolling-окно для дампенинга. 0 отключает. |
notify_min_fires | int | 0 | Минимум срабатываний внутри окна до того, как уведомление отправлено. 0 отключает. |
notify_channel_ids | int[] | empty | Закрепить уведомления на конкретных channel ID (subject to собственным enabled / severity / scope фильтрам каждого канала). Пусто = global router. |
Правило, которое срабатывает меньше, чем notify_min_fires раз внутри trailing notify_window_seconds, пишет событие repeat_suppressed в timeline (чтобы вы могли видеть, что дампенинг вступил в силу), но не уведомляет. Оба нуля = дампенинг выкл, каждое срабатывание уведомляет subject to cooldown + silence + inhibition гейтам.
Смешанный (один нуль, один >0) отвергается на biz-слое с invalid_argument: notify_window_seconds and notify_min_fires must both be zero or both > 0.
Lifecycle инцидента
Поля выше описывают правило (определение триггера). Когда правило срабатывает, оно производит инцидент (таблица alert_incidents) с этими статусами:
open ─┬─> acknowledged ─> resolved
├─> silenced ─> resolved
└─> resolvedИнциденты auto-resolve, когда underlying-условие очищается на один полный evaluator-цикл. State-машина задокументирована в internal/manager/biz/alert/.
Типы событий
Каждый state-переход записывает строку alert_events. Стабильные event-type строки:
| Event type | Когда |
|---|---|
firing | правило срабатывает впервые (инцидент создан или переоткрыт) |
repeat_suppressed | срабатывание внутри cooldown / окна дампенинга |
acknowledged | пользователь кликает Ack |
silenced | пользователь silence'ит на N часов |
resolved | условие очищено или пользователь кликнул Resolve |
reopened | resolved инцидент сработал снова до удаления |
note | user-added комментарий |
notification_sent | одна channel-доставка успешна |
notification_failed | одна channel-доставка провалилась |
inhibited | подавлен инцидентом более высокой severity |
ai_initial_diagnosis | первая интерпретация проактивного AI investigator'а, записанная, когда инцидент впервые срабатывает |
Типы каналов
POST /v1/notification-channels принимает:
| Тип | Значение channel_type | Источник |
|---|---|---|
| Webhook | webhook | env или UI |
| Slack | slack | env или UI |
| Larksuite / Feishu | feishu | env или UI |
| DingTalk | dingtalk | env или UI |
| WeCom (企业微信) | wecom | только UI |
| Telegram | telegram | только UI |
Legacy log channel-тип был удалён в 2026-05 — сам alert_events — это delivery-аудит.
См. также
- REST API — эндпоинты для этих объектов.
- Capabilities → Алерты — operator-facing тур.
- Каналы — wiring исходящей доставки на chat-поверхности.