Webhook
通用 webhook 通道是兜底。当你要把告警推到 Ongrid 不原生支持的聊天平台、工单系统或内部转发(Microsoft Teams、Mattermost、Rocket Chat、OpsGenie、PagerDuty、你自家的路由),就用通用 webhook 指过去,告警流水线会把标准的 Ongrid 消息 JSON 推过去。
有专用通道就用专用通道
Slack / 飞书 / 钉钉 / 企微 / Telegram 的专用通道渲染更丰富的载荷(Slack attachments、签名)。只有没有专用通道时才用通用 webhook。
载荷
body 是标准的 notify.Message 形态,原样 JSON 序列化:
{
"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"
}没有 envelope、没有 msgtype、没有扁平化。接收方拿到的就是告警流水线产出的字段。由 NewGenericWebhookSender 构造。
可选 HMAC 签名
填了 Secret 字段之后,每次请求都带 X-Ongrid-Signature 头:
X-Ongrid-Signature: sha256=<hex><hex> 是 hex(HMAC-SHA256(secret, body)),对 POST 出去的确切字节计算。签名器是 signGenericWebhook。
在接收侧校验
# 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)
}端点公网就必须校签
没签名的通用 webhook URL 谁知道谁就能投。签名头是唯一能证明"这条是 Ongrid 发的"的依据。
请求形态
| 属性 | 取值 |
|---|---|
| Method | POST |
Content-Type | application/json |
User-Agent | ongrid-notify/1.0 |
| Body | notify.Message 的 JSON |
| 签名头 | X-Ongrid-Signature: sha256=…(仅当有 secret) |
| 超时 | 单请求 http.Client 超时(默认 15s) |
成功判定
Sender 把 HTTP 2xx(200–299)当成功。其他 —— 包括 3xx 跳转、4xx、5xx —— 都算 unexpected status: …,降噪流水线里记为失败投递。响应 body 不解析;Ongrid 不关心你的转发回什么 JSON。
重试与降噪
重试语义归 告警流水线 管,不归 Sender 管。Sender 每次 Send(ctx, msg) 只 POST 一次。流水线决定:
- 降噪窗口。 按规则配,默认 5 分钟。同一 dedupe key 每个窗口最多触发一次。
- 持续触发重复通知。 默认 1 小时。incident 仍开着的话,过了这个窗口给通道再发一次,避免它埋在聊天历史里。
- 恢复消息。 告警结束时发出。
Sender 的活是推字节。流水线的活是决定什么时候推。
传输失败不自动重试
如果 Sender POST 的那一刻接收方挂了,这条消息就丢了(作为投递错误进日志、出现在按通道的投递统计里)。流水线不排队也不晚些再试。理由:在恢复 3 分钟之后再投递一条 5 分钟前的旧告警,比缺一条更让人困惑。请用健壮的接收方,或者在 Ongrid 和不可靠下游之间自己加队列。
配置
- 起一个接受
POST+application/json的 HTTP 端点。挑一个你会和 Ongrid 共享的强 secret。 - 在 Ongrid:Settings → Channels → New → Provider =
webhook→ Endpoint = 你的 URL → Secret = 共享 secret。 - 点 Test。测试消息是合成的
notify.Message{Severity: "info", Subject: "Ongrid test", …}。在你的接收方日志里校验签名头。
配方
Microsoft Teams(incoming webhook)
Teams incoming webhook 接受的是另一种载荷形态(MessageCard)。最简单的路径是在 Ongrid 和 Teams 之间挂一个小转发:
# 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)Ongrid 这边通道指向 https://your-relay/ongrid-to-teams。
PagerDuty Events API v2
同样的模式:写一个小转发,把 {severity, subject, body, dedupe_key} 翻译成 PagerDuty events.v2 载荷。PD 的 dedup_key 字段和 Ongrid 的 dedupe_key 一一对应,所以同一个 incident 在两边是同一条告警。
Splunk HEC / Elastic ingest
通道指向 HEC 端点,URL 里带 Splunk token。Splunk 接受标准 Ongrid JSON;按 severity 和 labels.rule 索引以便下游搜索。
字段参考
参见 Message 作为唯一真相源。稳定字段:
| 字段 | 类型 | 说明 |
|---|---|---|
severity | string | critical / warning / info。 |
subject | string | 规则名 + 目标 —— 一行。 |
body | string | 多行细节。可能含换行。 |
source | string | alert / test / 等。 |
labels | map[string]string | rule、incident_id、device_id、自定义。 |
dedupe_key | string | pipeline:rule:label-set。按身份稳定。 |
occurred_at | RFC3339 string | UTC。告警 evaluator 触发的那一刻。 |
新字段只增不减 —— 接收方应忽略未知 key。
相关
- 通道总览
- 告警规则 schema ——
labels.rule的含义和 dedupe key 的构成。