Кейс: сводка алертов мониторинга через Heli API

Когда падает один компонент, дежурный получает десятки похожих алертов. Небольшой сервис может принимать их вебхуком, отправлять в Heli API и публиковать в чат одну сводку: что сломалось, где и с чего начать. Ниже — типовая схема для Prometheus Alertmanager; в Grafana ту же роль играет контактная точка типа Webhook.

Настройка Alertmanager

Alertmanager уже группирует алерты: group_by определяет, какие попадут в одно уведомление, а group_wait и group_interval — как часто оно отправляется. В теле вебхука приходят общий status, commonLabels и массив alerts; у каждого алерта есть labels, annotations, startsAt и свой status.

code
route:
  receiver: llm-digest
  group_by: ["alertname", "cluster"]
  group_wait: 30s
  group_interval: 5m

receivers:
  - name: llm-digest
    webhook_configs:
      - url: "http://alert-digest:8080/alerts"
        send_resolved: true
        max_alerts: 50

Сервис сводки

Если Heli или модель недоступны, сервис отправляет исходный список алертов: уведомления не должны теряться из-за сводки. Вместо Slack incoming webhook можно отправлять сообщение в Telegram через Bot API.

python
import os
import httpx
from fastapi import FastAPI, Request
from openai import AsyncOpenAI

app = FastAPI()
heli = AsyncOpenAI(base_url="https://getheli.ru/v1", api_key=os.environ["HELI_API_KEY"])

@app.post("/alerts")
async def alerts(request: Request):
    payload = await request.json()
    lines = [
        f'{a["status"]} {a["labels"].get("alertname", "")} '
        f'{a["labels"].get("instance", "")}: {a["annotations"].get("summary", "")}'
        for a in payload.get("alerts", [])[:50]
    ]
    try:
        resp = await heli.chat.completions.create(
            model="openai/gpt-5.4-mini",
            messages=[
                {"role": "system", "content": "Ты помощник дежурного. Сожми алерты в сводку: "
                 "что сломалось, где, возможная общая причина (пометь как гипотезу), "
                 "с чего начать проверку. Не придумывай фактов. До 5 пунктов."},
                {"role": "user", "content": "\n".join(lines)},
            ],
            max_tokens=600,
        )
        text = resp.choices[0].message.content
    except Exception:
        text = "Сводка недоступна, исходные алерты:\n" + "\n".join(lines)
    async with httpx.AsyncClient() as client:
        await client.post(os.environ["SLACK_WEBHOOK_URL"], json={"text": text})
    return {"ok": True}

Slack-бот на Heli

Кейс: Telegram-бот на Heli

Ограничения

  • Сводка дополняет алерты, а не заменяет их: критичные уведомления должны по-прежнему приходить дежурному напрямую.
  • Возможная причина в сводке — гипотеза модели. Проверяйте её по метрикам и логам.
  • Не отправляйте в модель секреты: убедитесь, что в метках и аннотациях нет токенов и паролей.

Модель и расход

Для сводки хватает быстрой модели вроде openai/gpt-5.4-mini или google/gemini-3.5-flash. Частоту вызовов определяет group_interval: модель вызывается на каждое групповое уведомление, а не на каждый алерт. Задайте ключу сервиса бюджет и лимит запросов в минуту во вкладке «Лимиты» — это защитит от лавины вызовов во время крупного инцидента.

Лимиты и контроль расходов

Проверка до запуска

Отправьте тестовый алерт через amtool alert add или POST-запросом на /api/v2/alerts Alertmanager и убедитесь, что сводка пришла в чат. Затем возьмите алерты нескольких прошлых инцидентов и проверьте, не теряет ли сводка важные алерты и не объединяет ли несвязанные проблемы.

Первое время отправляйте сводку параллельно с обычными уведомлениями, а не вместо них, и собирайте отзывы дежурных. Если сводки часто ошибаются, уточните промпт или передавайте модели больше полей, например severity и runbook_url из аннотаций.

Попробуйте Heli

Ключ sk-heli- появляется после подтверждения почты. Через Google и Яндекс — сразу в кабинете.

Документация API · Модели и цены

Читайте также