Интеграции
Интеграции
Pingera напрямую отправляет оповещения в Telegram, MAX, по Email и SMS — настройка описана в разделе Каналы оповещений.
Для остальных сервисов используйте канал типа Webhook. Pingera отправляет JSON в собственном формате, а Slack, Mattermost, PagerDuty и похожие сервисы ожидают свой. Поэтому между ними нужен небольшой обработчик, который преобразует сообщение. Его можно разместить в любой serverless-платформе (Cloudflare Workers, Yandex Cloud Functions и т.п.) или на своём сервере.
Общая схема
- Разверните обработчик и получите его URL.
- Создайте канал оповещений типа Webhook с этим URL.
- Добавьте в канал заголовок
X-Webhook-Tokenс секретным значением — обработчик будет отклонять запросы без него. - Нажмите «Отправить тест», чтобы проверить цепочку целиком.
- Добавьте канал в правила оповещений и в настройки пульсаров.
Обработчик должен быстро отвечать кодом 2xx. Если ответа нет, Pingera повторит отправку — подробнее в разделе Вебхуки.
Разбор сообщения
Все данные события находятся в поле incident_data:
| Событие | Как определить | Где взять данные |
|---|---|---|
| Оповещение по проверке | incident_data.notification_type равен alert или resolution | incident_data.alert.title, severity, check_name |
| Оповещение по пульсару | incident_data.alert.check_type равен heartbeat | incident_data.alert.title, message, alert_type (missed_ping или recovered) |
| Тестовое сообщение | incident_data.notification_type равен test | incident_data.alert.title |
Slack и Mattermost
Slack и Mattermost принимают входящие вебхуки в одинаковом формате {"text": "..."}. Создайте входящий вебхук в Slack или Mattermost и используйте обработчик ниже.
Пример для Cloudflare Workers. Задайте переменные окружения TARGET_WEBHOOK_URL (URL входящего вебхука) и PINGERA_TOKEN (значение заголовка X-Webhook-Token):
export default {
async fetch(request, env) {
if (request.method !== "POST" || request.headers.get("X-Webhook-Token") !== env.PINGERA_TOKEN) {
return new Response("Forbidden", { status: 403 });
}
const message = await request.json();
const data = message.incident_data || {};
const alert = data.alert || {};
let text;
if (alert.check_type === "heartbeat") {
const icon = alert.alert_type === "recovered" ? "✅" : "🔴";
text = `${icon} Пульсар «${alert.check_name}»: ${alert.message}`;
} else if (data.notification_type === "resolution") {
text = `✅ Восстановлено: ${alert.title} (длительность ${alert.duration})`;
} else if (data.notification_type === "test") {
text = `🧪 ${alert.title}`;
} else {
text = `🔴 [${alert.severity}] ${alert.title}\n${alert.description}`;
}
await fetch(env.TARGET_WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text }),
});
return new Response("ok");
},
};
PagerDuty
PagerDuty принимает события через Events API v2. Создайте в сервисе PagerDuty интеграцию типа Events API v2 и используйте её Integration Key (routing_key).
Обработчик ниже создаёт инцидент при срабатывании оповещения и закрывает его при восстановлении. В качестве dedup_key используется ID оповещения или пульсара, поэтому повторные доставки не создают дубликатов.
const SEVERITY = { critical: "critical", high: "error", medium: "warning", low: "info" };
export default {
async fetch(request, env) {
if (request.method !== "POST" || request.headers.get("X-Webhook-Token") !== env.PINGERA_TOKEN) {
return new Response("Forbidden", { status: 403 });
}
const message = await request.json();
const data = message.incident_data || {};
const alert = data.alert || {};
let event;
if (alert.check_type === "heartbeat") {
event = {
event_action: alert.alert_type === "recovered" ? "resolve" : "trigger",
dedup_key: `pingera-heartbeat-${alert.check_id}`,
payload: { summary: alert.message, source: alert.check_name, severity: "error" },
};
} else if (data.notification_type === "alert" || data.notification_type === "resolution") {
event = {
event_action: data.notification_type === "resolution" ? "resolve" : "trigger",
dedup_key: `pingera-alert-${data.alert_id}`,
payload: {
summary: alert.title,
source: alert.check_name,
severity: SEVERITY[alert.severity] || "warning",
custom_details: alert.alert_metadata,
},
};
} else {
return new Response("ignored");
}
await fetch("https://events.pagerduty.com/v2/enqueue", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ routing_key: env.PAGERDUTY_ROUTING_KEY, ...event }),
});
return new Response("ok");
},
};
Другие сервисы
Тот же подход работает для любого сервиса с HTTP API: Jira, YouTrack, Opsgenie, корпоративных мессенджеров. Возьмите нужные поля из incident_data и отправьте их в формате целевого сервиса.
Для Статус Страниц Pingera обработчик не нужен: используйте канал типа «Компонент Статус Страницы».