Esquema de reglas de alerta
Las reglas de alerta se almacenan en la tabla alert_rules y se envían a POST /v1/alert-rules. Esta página es el formato wire. Fuente de verdad: internal/manager/model/alert/model.go.
Forma 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
}Referencia de campos
Identidad
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
rule_key | string | sí | Identificador estable en lower_snake usado en claves de dedupe y en incident.rule. Único. |
name | string | sí | Nombre para mostrar. |
enabled | bool | no (por defecto true) | Las reglas deshabilitadas son omitidas por el evaluator y ocultadas de los filtros "active". |
Source / scope
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
source_type | enum | sí | ongrid_builtin, prometheus_external. Las reglas integradas llevan valores rule_key canónicos; las reglas externas provienen de un archivo de reglas de alerta de Prometheus importado. |
scope_type | enum | sí | host, global, monitoring_pipeline. Determina la dimensión por la que el evaluator agrupa — host produce un incidente por device_id; global produce un único incidente a nivel sistema; monitoring_pipeline es para reglas internas de salud del pipeline. |
join_mode | enum | sí | all (todas las condiciones deben coincidir), any (cualquier condición coincide). Solo relevante cuando conditions tiene más de un elemento. |
Kind
kind discrimina cómo interpreta conditions el evaluator. Cada kind dirige a un sub-evaluator distinto.
| Kind | Estado | Qué hace | Forma de conditions |
|---|---|---|---|
metric_threshold | solo entrada de UI | Formulario amigable. La capa biz lo reescribe a metric_raw al guardar; nunca verás este kind en disco. | [{ "metric": "cpu_pct", "operator": ">=", "threshold": 90, "window": "5m", "for": "2m", "aggregator": "avg" }] |
metric_raw | en vivo | PromQL arbitrario. Disparado por ticker. | [{ "expr": "rate(http_500[5m]) > 0.1" }] |
metric_anomaly | en vivo | Desviación respecto a una baseline rodante (z-score). Disparado por ticker vía el PromQuerier. | [{ "metric": "node_cpu_usage_percent", "window": "1h", "z_threshold": 3.0 }] |
metric_forecast | en vivo | Extrapolación lineal (predict_linear) que cruza un umbral estático dentro de una ventana futura. | [{ "metric": "node_filesystem_avail_bytes", "window": "1h", "forecast_for": "24h", "below": 1073741824 }] |
metric_burn_rate | en vivo | Multi-ventana multi-burn-rate de presupuesto de error SLO (Google SRE Workbook). | [{ "good": "sum(rate(http_2xx[1h]))", "total": "sum(rate(http_total[1h]))", "slo": 0.999, "long": "1h", "short": "5m" }] |
log_match | en vivo (Phase-B) | Patrón LogQL que, cuando hace match, dispara. | [{ "expr": "{device_id=\"{{.device_id}}\"} |= \"panic\"" }] |
log_volume | en vivo (Phase-B) | Tasa de stream LogQL por encima de un umbral. | [{ "expr": "sum(rate({app=\"foo\"}[5m])) > 100" }] |
trace_latency | en vivo (Phase-B) | TraceQL p95 / p99 por encima de un umbral para un servicio. | [{ "service": "payments", "percentile": 95, "above_ms": 800, "window": "5m" }] |
trace_error_rate | en vivo (Phase-B) | Fracción de spans con error en TraceQL por encima de un umbral. | [{ "service": "payments", "above_percent": 1.0, "window": "5m" }] |
El enum Go completo vive en 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"
)Los kinds legacy (edge_offline, prom_query, ingest_health, edge_absence, health_ingest, event_internal) son aliased silenciosamente a metric_raw al guardar.
Conditions
conditions es un array. La forma de cada elemento depende de kind — ver la tabla de arriba. join_mode decide si todos los elementos deben coincidir (all) o cualquiera (any).
Para metric_threshold (el formulario UI), cada condición es un 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
}La capa biz compila eso en una expr metric_raw al guardar usando las métricas de host canónicas de conjunto cerrado (node_cpu_usage_percent, node_memory_used_percent, node_filesystem_used_percent, node_load1, ...).
Severidad
| Valor | Tratamiento |
|---|---|
info | se registra; las notificaciones se filtran por el match_severity_min del canal (la mayoría de canales omiten este piso) |
warning | por defecto |
critical | siempre se notifica salvo que esté silenciado |
El match_severity_min de un canal con valor warning acepta warning + critical; critical acepta solo critical. Vacío acepta cualquiera.
Labels y annotations
Mapas clave/valor de forma libre almacenados como JSON.
- Las
labelsse anexan a las labels del incidente en el momento de fire y se usan para agrupamiento / dedupe. Comunes:service,team,env. - Las
annotationsse templatean en el momento de fire usando sintaxis de templates de Go con el snapshot del incidente — por ejemplosummary: "CPU on {{$labels.device_id}} above 90%".
Runbook
runbook_url se muestra textualmente en el detalle del incidente y en la superficie de chat junto al informe de investigación de IA. Úsalo para enlazar a tus runbooks / playbooks internos.
Atenuación de notificaciones
| Campo | Tipo | Por defecto | Descripción |
|---|---|---|---|
notify_window_seconds | int | 0 | Ventana rodante para la atenuación. 0 deshabilita. |
notify_min_fires | int | 0 | Disparos mínimos dentro de la ventana antes de enviar notificación. 0 deshabilita. |
notify_channel_ids | int[] | vacío | Fija notificaciones a IDs de canal específicos (sujeto a los filtros propios de cada canal de enabled / severidad / scope). Vacío = router global. |
Una regla que dispara menos de notify_min_fires veces dentro de los notify_window_seconds trailing escribe un evento repeat_suppressed en la línea de tiempo (para que veas que la atenuación tuvo efecto) pero no notifica. Ambos en cero = atenuación desactivada, cada disparo notifica sujeto a los gates de cooldown + silence + inhibition.
Mixto (uno cero, otro >0) es rechazado en la capa biz con invalid_argument: notify_window_seconds and notify_min_fires must both be zero or both > 0.
Ciclo de vida del incidente
Los campos de arriba describen una regla (la definición del trigger). Cuando una regla dispara produce un incidente (tabla alert_incidents) con estos estados:
open ─┬─> acknowledged ─> resolved
├─> silenced ─> resolved
└─> resolvedLos incidentes se auto-resuelven cuando la condición subyacente se despeja durante un ciclo completo del evaluator. La máquina de estados está documentada en internal/manager/biz/alert/.
Tipos de evento
Cada transición de estado registra una fila de alert_events. Cadenas estables de tipo de evento:
| Tipo de evento | Cuándo |
|---|---|
firing | la regla dispara por primera vez (incidente creado o reabierto) |
repeat_suppressed | disparo dentro de la ventana de cooldown / atenuación |
acknowledged | el usuario hace clic en Ack |
silenced | el usuario silencia por N horas |
resolved | condición despejada o el usuario hizo clic en Resolve |
reopened | un incidente resuelto disparó de nuevo antes de eliminarse |
note | comentario añadido por el usuario |
notification_sent | una entrega de canal tuvo éxito |
notification_failed | una entrega de canal falló |
inhibited | suprimido por un incidente activo de mayor severidad |
ai_initial_diagnosis | primera toma proactiva del investigador IA, escrita cuando el incidente dispara por primera vez |
Tipos de canal
POST /v1/notification-channels acepta:
| Tipo | Valor de channel_type | Origen |
|---|---|---|
| Webhook | webhook | env o UI |
| Slack | slack | env o UI |
| Larksuite / Feishu | feishu | env o UI |
| DingTalk | dingtalk | env o UI |
| WeCom (企业微信) | wecom | solo UI |
| Telegram | telegram | solo UI |
El tipo de canal legacy log se eliminó en 2026-05 — alert_events mismo es la auditoría de entrega.
Véase también
- REST API — endpoints para estos objetos.
- Capacidades → Alertas — recorrido para operadores.
- Canales — cableado de la entrega saliente hacia las superficies de chat.