Webhook
Der generische Webhook-Kanal ist der Fallback. Wenn Sie Alarme an eine Chat-Oberfläche, ein Ticketing-System oder ein hauseigenes Relay pushen müssen, das Ongrid nicht nativ spricht (Microsoft Teams, Mattermost, Rocket Chat, OpsGenie, PagerDuty, Ihr eigener Router), richten Sie einen generischen Webhook darauf aus, und die Alarmpipeline postet das kanonische Ongrid-Message-JSON.
Verwenden Sie den dedizierten Kanal, wenn es einen gibt
Für Slack / Feishu / DingTalk / WeCom / Telegram rendern die dedizierten Kanäle reichere Payloads (Slack-Attachments, Signatur). Greifen Sie nur dann zum generischen Webhook, wenn es keinen dedizierten Kanal gibt.
Payload
Der Body ist die kanonische notify.Message-Form, JSON-kodiert wörtlich:
{
"severity": "critical",
"subject": "node-01 swap_high",
"body": "swap_in_pages > 1000 for 5m",
"source": "alert",
"labels": {
"rule": "swap_high",
"incident_id": "1234",
"device_id": "7",
"host": "node-01"
},
"dedupe_key": "alert:swap_high:device=7",
"occurred_at": "2026-05-30T14:02:35Z"
}Kein Envelope, kein msgtype, kein Flattening. Der Empfänger bekommt exakt die Felder, die die Alarmpipeline produzierte. Gebaut von NewGenericWebhookSender.
Optionale HMAC-Signatur
Wenn Sie das Secret-Feld ausfüllen, trägt jede Anfrage einen X-Ongrid-Signature-Header:
X-Ongrid-Signature: sha256=<hex>Wo <hex> hex(HMAC-SHA256(secret, body)) über die exakten Bytes gepostet ist. Der Signer ist signGenericWebhook.
Verifizierung auf der Empfängerseite
# Python receiver
import hmac, hashlib
def verify(secret, body_bytes, header):
expected = "sha256=" + hmac.new(
secret.encode(), body_bytes, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header)// Go receiver
func verify(secret string, body, header []byte) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
expected := []byte("sha256=" + hex.EncodeToString(mac.Sum(nil)))
return hmac.Equal(expected, header)
}Verifizieren Sie die Signatur immer, wenn der Endpunkt öffentlich ist
Eine generische Webhook-URL ohne Signatur ist offen für jeden, der die URL erfährt. Der Signaturheader ist das Einzige, was authentifiziert, „dies ist von Ongrid".
Request-Form
| Eigenschaft | Wert |
|---|---|
| Methode | POST |
Content-Type | application/json |
User-Agent | ongrid-notify/1.0 |
| Body | JSON von notify.Message |
| Sig-Header | X-Ongrid-Signature: sha256=… (nur wenn Secret) |
| Timeout | Per-Request http.Client-Timeout (Default 15s) |
Erfolgskriterium
Der Sender behandelt HTTP 2xx (200–299) als Erfolg. Alles andere — einschließlich 3xx-Redirects, 4xx, 5xx — ist unexpected status: … und zählt als fehlgeschlagene Zustellung für die Dämpfungspipeline. Der Body der Antwort wird nicht geparst; Ongrid kümmert sich nicht, welches JSON Ihr Relay zurückechot.
Retry und Dämpfung
Retry-Semantik gehört der Alarmpipeline, nicht dem Sender. Der Sender postet genau einmal pro Send(ctx, msg)-Aufruf. Die Pipeline entscheidet:
- Dämpfungsfenster. Pro-Regel, Default 5 Minuten. Derselbe Dedupe-Key feuert höchstens einmal pro Fenster.
- Repeat-on-still-firing. Default 1 Stunde. Wenn ein Incident nach diesem Fenster noch offen ist, bekommt der Kanal eine Re-Notifizierung, damit er nicht in der Chat-Historie verloren geht.
- Recovery-Nachricht. Feuert, wenn der Alarm sich klärt.
Die Aufgabe des Senders ist es, die Bytes zu pushen. Die Aufgabe der Pipeline ist es, zu entscheiden, wann.
Kein automatisches Retry bei Transport-Fehler
Wenn der Empfänger im Moment des Sender-Posts down ist, ist die Nachricht verloren (als Zustellungs-Fehler geloggt, in den Per-Kanal-Zustellungsstatistiken sichtbar). Die Pipeline queued und versucht später nicht erneut. Die Begründung: ein 5-Minuten-stale Alarm, drei Minuten nach der Erholung zugestellt, ist verwirrender als ein fehlender. Verwenden Sie einen robusten Empfänger, oder schichten Sie Ihre eigene Queue zwischen Ongrid und ein wackeliges Downstream.
Setup
- Einen HTTP-Endpunkt aufstellen, der
POST+application/jsonakzeptiert. Ein starkes Secret wählen, das Sie mit Ongrid teilen. - In Ongrid: Settings → Channels → New → Provider =
webhook→ Endpoint = Ihre URL → Secret = das geteilte Secret. - Test klicken. Die Testnachricht ist die synthetische
notify.Message{Severity: "info", Subject: "Ongrid test", …}. Verifizieren Sie den Signaturheader in Ihren Empfänger-Logs.
Rezepte
Microsoft Teams (Incoming Webhook)
Teams Incoming Webhook akzeptiert eine andere Payload-Form (eine MessageCard). Der einfachste Weg ist, einen winzigen Adapter zwischen Ongrid und Teams zu setzen:
# server.py - listens on /ongrid-to-teams
@app.post("/ongrid-to-teams")
def relay(msg: dict):
teams_url = os.environ["TEAMS_WEBHOOK"]
card = {
"@type": "MessageCard",
"@context": "https://schema.org/extensions",
"themeColor": {"critical":"D92F2F","warning":"F2C037","info":"36A64F"}.get(msg["severity"], "6F7A87"),
"title": msg["subject"],
"text": msg["body"],
}
requests.post(teams_url, json=card)Richten Sie den Ongrid-Webhook-Kanal auf https://your-relay/ongrid-to-teams.
PagerDuty Events API v2
Gleiches Muster: ein kleines Relay, das {severity, subject, body, dedupe_key} in ein PagerDuty events.v2-Payload übersetzt. Das PD dedup_key-Feld mapped 1:1 zu Ongrids dedupe_key, sodass derselbe Incident in Ongrid derselbe Alarm in PD ist.
Splunk HEC / Elastic Ingest
Richten Sie den Kanal auf den HEC-Endpunkt mit dem Splunk-Token in der URL aus. Splunk akzeptiert das kanonische Ongrid-JSON; indizieren Sie auf severity und labels.rule für Downstream-Suche.
Feld-Referenz
Siehe Message für die Quelle der Wahrheit. Stabile Felder:
| Feld | Typ | Notizen |
|---|---|---|
severity | string | critical / warning / info. |
subject | string | Regelname + Ziel — eine Zeile. |
body | string | Mehrzeiliges Detail. Kann Newlines enthalten. |
source | string | alert / test / etc. |
labels | map[string]string | rule, incident_id, device_id, custom. |
dedupe_key | string | pipeline:rule:label-set. Stabil pro Identität. |
occurred_at | RFC3339-String | UTC. Der Moment, in dem der Alarm-Evaluator feuerte. |
Neue Felder sind additiv — Empfänger sollten unbekannte Keys ignorieren.
Verwandt
- Kanäle-Übersicht
- Alarmregel-Schema — für was
labels.rulebedeutet und wie Dedupe-Keys gebaut werden.