Skip to content

Schéma de règle d'alerte

Les règles d'alerte sont stockées dans la table alert_rules et soumises à POST /v1/alert-rules. Cette page est le format wire. Source de vérité : internal/manager/model/alert/model.go.

Forme 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
}

Référence des champs

Identité

ChampTypeRequisDescription
rule_keystringouiIdentifiant stable lower_snake utilisé dans les clés de dédoublonnage et incident.rule. Unique.
namestringouiNom d'affichage.
enabledboolnon (défaut true)Les règles désactivées sont sautées par l'evaluator et cachées des filtres « actifs ».

Source / scope

ChampTypeRequisDescription
source_typeenumouiongrid_builtin, prometheus_external. Les règles intégrées portent des valeurs rule_key canoniques ; les règles externes proviennent d'un fichier de règles d'alerte Prometheus importé.
scope_typeenumouihost, global, monitoring_pipeline. Détermine sur quelle dimension l'evaluator groupe — host produit un incident par device_id ; global produit un incident system-wide ; monitoring_pipeline est pour les règles internes de santé du pipeline.
join_modeenumouiall (chaque condition doit matcher), any (n'importe quelle condition matche). Pertinent seulement quand conditions a plus d'un élément.

Kind

kind discrimine comment l'evaluator interprète conditions. Chaque kind pilote un sub-evaluator différent.

KindStatutCe que ça faitForme conditions
metric_thresholdinput UI-onlyFormulaire amical. La couche biz le réécrit en metric_raw au moment du save ; vous ne verrez jamais ce kind sur disque.[{ "metric": "cpu_pct", "operator": ">=", "threshold": 90, "window": "5m", "for": "2m", "aggregator": "avg" }]
metric_rawlivePromQL arbitraire. Driven par ticker.[{ "expr": "rate(http_500[5m]) > 0.1" }]
metric_anomalyliveDéviation d'une baseline glissante (z-score). Driven par ticker via le PromQuerier.[{ "metric": "node_cpu_usage_percent", "window": "1h", "z_threshold": 3.0 }]
metric_forecastliveExtrapolation linéaire (predict_linear) traversant un seuil statique dans une fenêtre future.[{ "metric": "node_filesystem_avail_bytes", "window": "1h", "forecast_for": "24h", "below": 1073741824 }]
metric_burn_rateliveMulti-window multi-burn-rate de budget d'erreur SLO (Google SRE Workbook).[{ "good": "sum(rate(http_2xx[1h]))", "total": "sum(rate(http_total[1h]))", "slo": 0.999, "long": "1h", "short": "5m" }]
log_matchlive (Phase-B)Pattern LogQL qui, quand il hit, part.[{ "expr": "{device_id=\"{{.device_id}}\"} |= \"panic\"" }]
log_volumelive (Phase-B)Taux de stream LogQL au-dessus du seuil.[{ "expr": "sum(rate({app=\"foo\"}[5m])) > 100" }]
trace_latencylive (Phase-B)TraceQL p95 / p99 au-dessus du seuil pour un service.[{ "service": "payments", "percentile": 95, "above_ms": 800, "window": "5m" }]
trace_error_ratelive (Phase-B)Fraction de span d'erreur TraceQL au-dessus du seuil.[{ "service": "payments", "above_percent": 1.0, "window": "5m" }]

L'enum Go complet vit dans 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"
)

Les kinds legacy (edge_offline, prom_query, ingest_health, edge_absence, health_ingest, event_internal) sont silencieusement aliasés à metric_raw au save.

Conditions

conditions est un array. La forme de chaque élément dépend de kind — voir le tableau ci-dessus. join_mode décide si tous les éléments doivent matcher (all) ou n'importe lequel (any).

Pour metric_threshold (le formulaire UI), chaque condition est une 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
}

La couche biz les compile en expr metric_raw au moment du save en utilisant l'ensemble fermé canonique de métriques host (node_cpu_usage_percent, node_memory_used_percent, node_filesystem_used_percent, node_load1, ...).

Sévérité

ValeurTraitement
infoenregistrée ; notifications gatées par le match_severity_min du canal (la plupart des canaux sautent ce plancher)
warningdéfaut
criticaltoujours notifiée sauf si silenced

Un match_severity_min de canal posé à warning accepte warning + critical ; critical n'accepte que critical. Vide matche n'importe quoi.

Labels & annotations

Maps libres clé/valeur stockées comme JSON.

  • labels sont ajoutés aux labels de l'incident au moment du fire et utilisés pour le groupement / dédoublonnage. Courants : service, team, env.
  • annotations sont templatées au moment du fire en utilisant la syntaxe template Go avec le snapshot d'incident — par exemple summary: "CPU on {{$labels.device_id}} above 90%".

Runbook

runbook_url est affiché verbatim dans le détail d'incident et sur la surface de chat aux côtés du rapport d'investigation IA. Utilisez-le pour lier à vos runbooks / playbooks internes.

Dampening de notification

ChampTypeDéfautDescription
notify_window_secondsint0Fenêtre glissante pour le dampening. 0 désactive.
notify_min_firesint0Nombre minimum de firings à l'intérieur de la fenêtre avant que la notification soit envoyée. 0 désactive.
notify_channel_idsint[]videÉpingle les notifications à des IDs de canaux spécifiques (sous réserve des filtres enabled / sévérité / scope propres à chaque canal). Vide = router global.

Une règle qui part moins de notify_min_fires fois à l'intérieur du notify_window_seconds traînant écrit un événement repeat_suppressed à la timeline (pour que vous puissiez voir que le dampening a pris effet) mais ne notifie pas. Les deux à zéro = dampening off, chaque firing notifie sous réserve des gates de cooldown + silence + inhibition.

Mixte (un zéro, un >0) est rejeté à la couche biz avec invalid_argument: notify_window_seconds and notify_min_fires must both be zero or both > 0.

Cycle de vie d'incident

Les champs ci-dessus décrivent une règle (la définition de déclenchement). Quand une règle part, elle produit un incident (table alert_incidents) avec ces statuts :

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

Les incidents auto-résolvent quand la condition sous-jacente se dégage pendant un cycle d'evaluator complet. La machine à états est documentée dans internal/manager/biz/alert/.

Types d'événement

Chaque transition d'état enregistre une ligne alert_events. Chaînes stables de type d'événement :

Type d'événementQuand
firingla règle part pour la première fois (incident créé ou réouvert)
repeat_suppressedfiring à l'intérieur de la fenêtre de cooldown / dampening
acknowledgedl'utilisateur clique Ack
silencedl'utilisateur silence pour N heures
resolvedla condition s'est dégagée ou l'utilisateur a cliqué Resolve
reopenedun incident résolu est reparti avant suppression
notecommentaire ajouté par l'utilisateur
notification_sentune livraison de canal a réussi
notification_failedune livraison de canal a échoué
inhibitedsupprimé par un incident actif de sévérité supérieure
ai_initial_diagnosispremière prise de l'investigator IA proactif, écrit quand un incident part pour la première fois

Types de canal

POST /v1/notification-channels accepte :

TypeValeur channel_typeSource
Webhookwebhookenv ou UI
Slackslackenv ou UI
Larksuite / Feishufeishuenv ou UI
DingTalkdingtalkenv ou UI
WeCom (企业微信)wecomUI seulement
TelegramtelegramUI seulement

Le type de canal legacy log a été retiré en 2026-05 — alert_events lui-même est l'audit de livraison.

Voir aussi