Skip to content

Webhook

O canal de webhook genérico é o fallback. Quando você precisa empurrar alertas para uma superfície de chat, sistema de tickets, ou relay interno que o Ongrid não fala nativamente (Microsoft Teams, Mattermost, Rocket Chat, OpsGenie, PagerDuty, seu próprio router), aponte um webhook genérico para lá e o pipeline de alerta posta o JSON canônico de mensagem Ongrid.

Use o canal dedicado quando houver um

Para Slack / Feishu / DingTalk / WeCom / Telegram, os canais dedicados renderizam payloads mais ricos (attachments Slack, assinatura). Recorra ao webhook genérico só quando não há um canal dedicado.

Payload

O body é o formato canônico notify.Message, JSON-encoded verbatim:

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

Sem envelope, sem msgtype, sem achatamento. O receiver recebe exatamente os campos que o pipeline de alerta produziu. Montado por NewGenericWebhookSender.

Assinatura HMAC opcional

Quando você preenche o campo Secret, cada requisição carrega um header X-Ongrid-Signature:

text
X-Ongrid-Signature: sha256=<hex>

Onde <hex> é hex(HMAC-SHA256(secret, body)) sobre os bytes exatos postados. O signer é signGenericWebhook.

Verificando no lado receiver

python
# 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
// 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)
}

Sempre verifique a assinatura quando o endpoint é público

Uma URL de webhook genérico sem assinatura é aberta a qualquer um que descobre a URL. O header de assinatura é a única coisa que autentica "isto é do Ongrid".

Formato da requisição

PropriedadeValor
MétodoPOST
Content-Typeapplication/json
User-Agentongrid-notify/1.0
BodyJSON de notify.Message
Header de sigX-Ongrid-Signature: sha256=… (só quando há secret)
TimeoutTimeout por requisição do http.Client (padrão 15s)

Critério de sucesso

O Sender trata HTTP 2xx (200–299) como sucesso. Qualquer outra coisa — incluindo redirects 3xx, 4xx, 5xx — é unexpected status: … e conta como entrega falha para o pipeline de dampening. O body da resposta não é parseado; o Ongrid não se importa com qual JSON seu relay devolve.

Retry e dampening

A semântica de retry pertence ao pipeline de alerta, não ao Sender. O Sender posta exatamente uma vez por chamada de Send(ctx, msg). O pipeline decide:

  • Janela de dampening. Por rule, padrão 5 minutos. A mesma dedupe key dispara no máximo uma vez por janela.
  • Repetir-em-ainda-disparando. Padrão 1 hora. Se um incidente ainda está aberto após essa janela, o canal recebe um re-notify para que não se perca no histórico do chat.
  • Mensagem de recovery. Disparada quando o alerta limpa.

A função do Sender é empurrar os bytes. A função do pipeline é decidir quando.

Sem retry automático em falha de transporte

Se o receiver está fora no momento que o Sender posta, a mensagem está perdida (logada como erro de entrega, exposto nas estatísticas de entrega por canal). O pipeline não enfileira e re-tenta depois. O raciocínio: um alerta com 5 minutos de stale entregue três minutos após o recovery é mais confuso que um ausente. Use um receiver robusto, ou camade sua própria fila entre o Ongrid e um downstream instável.

Configuração

  1. Suba um endpoint HTTP que aceite POST + application/json. Escolha um secret forte que você compartilhará com o Ongrid.
  2. No Ongrid: Settings → Channels → New → Provider = webhook → Endpoint = sua URL → Secret = o secret compartilhado.
  3. Clique Test. A mensagem de teste é a sintética notify.Message{Severity: "info", Subject: "Ongrid test", …}. Verifique o header de assinatura nos logs do seu receiver.

Receitas

Microsoft Teams (incoming webhook)

O incoming webhook do Teams aceita um formato de payload diferente (um MessageCard). O caminho mais simples é colocar um adapter pequeno entre o Ongrid e o Teams:

python
# 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)

Aponte o canal webhook do Ongrid para https://your-relay/ongrid-to-teams.

PagerDuty Events API v2

Mesmo padrão: um pequeno relay que traduz {severity, subject, body, dedupe_key} num payload events.v2 do PagerDuty. O campo dedup_key do PD mapeia 1:1 ao dedupe_key do Ongrid, então o mesmo incidente no Ongrid é o mesmo alerta no PD.

Splunk HEC / Elastic ingest

Aponte o canal para o endpoint HEC com o token Splunk na URL. O Splunk aceita o JSON canônico do Ongrid; indexe em severity e labels.rule para busca downstream.

Referência de campos

Veja Message para a fonte de verdade. Campos estáveis:

CampoTipoNotas
severitystringcritical / warning / info.
subjectstringNome da rule + alvo — uma linha.
bodystringDetalhe multi-linha. Pode conter newlines.
sourcestringalert / test / etc.
labelsmap[string]stringrule, incident_id, device_id, custom.
dedupe_keystringpipeline:rule:label-set. Estável por identidade.
occurred_atstring RFC3339UTC. O momento em que o evaluator de alerta disparou.

Campos novos são aditivos — receivers devem ignorar chaves desconhecidas.

Relacionado