PartyFlow

Guide: Grafana alerts → PartyFlow#

Настроить Grafana Alerting так, чтобы алерты приходили в канал PartyFlow с цветной полоской, полями и push-уведомлением только для critical-алертов.

Рабочее время — около 10 минут, если у вас уже есть права admin в space PartyFlow и права editor в Grafana.


Что получится#

  • Сообщения от Grafana попадают в канал как structured message с color bar, title, fields.
  • severity: critical в Grafana-правиле → push пробивает DND дежурного.
  • severity: warning / info → в канал попадает, но без push (чтобы не разбудить команду ночью скучными алертами).
  • Подпись HMAC — опциональна, но рекомендуется для прод-Grafana.

Шаг 1. Создать webhook в PartyFlow#

В space → IntegrationsIncoming webhooksNew webhook:

Поле Значение
Name grafana-alerts
Channel #alerts (или какой у вас)
Require signature On для прода. Off для быстрого старта.
Default push Off — мы хотим, чтобы push решался per-alert через severity.

Сохраните:

  • Webhook URL (https://api.partyflow.ru/api/v1/webhooks/incoming/whk_...)
  • Signing secret (если выбрали Require signature: On)

Шаг 2. Contact Point в Grafana#

В Grafana → AlertingContact points+ Add contact point:

Поле Значение
Name partyflow
Integration Webhook
URL <webhook URL из шага 1>
HTTP Method POST
Authorization Header — Scheme оставить пустым
Max Alerts 0 (без ограничения)
Custom payload см. ниже

Payload template#

Grafana умеет шаблонизировать JSON. Вставьте в "Optional Webhook settings → Custom payload":

{
  "text": "{{ range .Alerts }}{{ .Labels.alertname }} — {{ .Annotations.summary }}\n{{ end }}",
  "severity": "{{ if eq (index .Alerts 0).Labels.severity \"critical\" }}critical{{ else if eq (index .Alerts 0).Labels.severity \"warning\" }}warning{{ else }}info{{ end }}",
  "mentions": {{ if eq (index .Alerts 0).Labels.severity "critical" }}["<user-id-oncall>"]{{ else }}[]{{ end }},
  "attachments": [
    {{ range $i, $a := .Alerts }}{{ if $i }},{{ end }}{
      "color": "{{ if eq $a.Status \"firing\" }}#E01E5A{{ else }}#2EB67D{{ end }}",
      "title": "[{{ $a.Status | ToUpper }}] {{ $a.Labels.alertname }}",
      "title_link": "{{ $a.GeneratorURL }}",
      "text": "{{ $a.Annotations.description }}",
      "fields": [
        { "title": "Severity", "value": "{{ $a.Labels.severity }}", "short": true },
        { "title": "Instance", "value": "{{ $a.Labels.instance }}", "short": true }
      ],
      "ts": {{ $a.StartsAt.Unix }}
    }{{ end }}
  ]
}

Подставьте в "mentions" реальный user_id дежурного (узнать в PartyFlow → профиль → Copy user ID).

Для signed webhook'а#

Grafana сам не умеет считать HMAC. Есть два варианта:

Вариант A (простой): Webhook в режиме Require signature: Off. Безопасность держится на URL-токене — достаточно для multi-tenant прод-Grafana, если URL не попадает в публичные репо/PR.

Вариант B (надёжный): Прокси-сервис между Grafana и PartyFlow. Grafana шлёт в прокси, прокси подписывает и форвардит. Пример прокси — в guides/verify-signatures.md.


Шаг 3. Attach к Alert Rule#

В Alerting → Notification policies убедитесь, что matchers вашего правила направляют его на contact point partyflow. По default — root policy.


Шаг 4. Тест#

В Grafana → Contact points → partyflow → Test. В канале должно появиться test-сообщение с color bar.

Если не пришло:

Симптом Диагностика
В логе Grafana HTTP 400 Payload невалиден. Скопируйте body из "Test alert" Grafana и прогоните через jq . — что-то не JSON.
В логе Grafana HTTP 401 Неверный URL или (если Require signature: On) нет подписи.
В логе Grafana HTTP 413 Payload > 256 KB. Урежьте шаблон — например, уберите .Annotations.description из text attachment'а.
В логе Grafana HTTP 429 Rate limit. У вас десятки alerts в секунду — сгруппируйте в Notification policy (grouping by alertname).
200, но нет в канале Проверьте ID канала; возможно webhook создан на другой канал.

Шаг 5. Настроить push для critical#

По дефолту push придёт только если в payload есть хоть одно из:

  • mentions[] с user_id
  • @channel или @here в text

Что настроили в шаблоне выше:

  • severity: "critical" + mentions: [oncall] → push дежурному, пробивает DND.
  • severity: "warning" + mentions: [] → в канал, без push.
  • severity: "info" + mentions: [] → в канал, без push.

Для ротации дежурных — проще использовать канал типа @oncall-team и в шаблоне подставлять "text": "... @here" или перечислять user_id через PagerDuty-like schedule-aware скрипт в прокси.


Частые правки#

Убрать дубли одного alert'а#

Grafana периодически переотправляет все firing-alerts. Если не хотите этого, в Notification policies → Group interval поставьте бОльшее значение (например, 4h) — PartyFlow покажет повторы только при эскалации.

Показывать только changes (firing/resolved)#

Добавьте в Notification policies → Repeat interval: 0 или очень большое значение, чтобы resolved приходил отдельно, а firing — только при новом событии.

Собрать подпись на стороне прокси (Вариант B)#

См. guides/verify-signatures.md — взять snippet на Python, поставить Flask/FastAPI-прокси между Grafana и PartyFlow.


Связанное#