Перейти к основному содержимому

Интеграции

Интеграции​

Pingera напрямую отправляет оповещения в Telegram, MAX, по Email и SMS — настройка описана в разделе Каналы оповещений.

Для остальных сервисов используйте канал типа Webhook. Pingera отправляет JSON в собственном формате, а Slack, Mattermost, PagerDuty и похожие сервисы ожидают свой. Поэтому между ними нужен небольшой обработчик, который преобразует сообщение. Его можно разместить в любой serverless-платформе (Cloudflare Workers, Yandex Cloud Functions и т.п.) или на своём сервере.

Общая схема​

  1. Разверните обработчик и получите его URL.
  2. Создайте канал оповещений типа Webhook с этим URL.
  3. Добавьте в канал заголовок X-Webhook-Token с секретным значением — обработчик будет отклонять запросы без него.
  4. Нажмите «Отправить тест», чтобы проверить цепочку целиком.
  5. Добавьте канал в правила оповещений и в настройки пульсаров.

Обработчик должен быстро отвечать кодом 2xx. Если ответа нет, Pingera повторит отправку — подробнее в разделе Вебхуки.

Разбор сообщения​

Все данные события находятся в поле incident_data:

СобытиеКак определитьГде взять данные
Оповещение по проверкеincident_data.notification_type равен alert или resolutionincident_data.alert.title, severity, check_name
Оповещение по пульсаруincident_data.alert.check_type равен heartbeatincident_data.alert.title, message, alert_type (missed_ping или recovered)
Тестовое сообщениеincident_data.notification_type равен testincident_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 обработчик не нужен: используйте канал типа «Компонент Статус Страницы».