Вебхуки и интеграции uptime-мониторинга: соберите свои workflow
Как подключить uptime-мониторинг к вашим системам через вебхуки. Полный гид по автоматизации инцидентов, кастомным уведомлениям и шаблонам интеграций.
Зачем вебхуки в мониторинге
Email-алерты доходят до вас рано или поздно. Slack-алерты появляются в канале. А вебхуки позволяют что-то делать в момент инцидента.
Без вебхуков:
- Алерт → вы вручную создаёте Jira-тикет → вручную обновляете страницу статуса → вручную поднимаете дежурного
- Время реакции: 5–10 минут
С вебхуками:
- Алерт → срабатывает вебхук → автоматически создаётся Jira-тикет → обновляется страница статуса → поднимается дежурный
- Время реакции: 10 секунд
Для критичной инфраструктуры эта разница в 5 минут предотвращает влияние на клиентов.
Как работают вебхуки
Когда сайт падает и мониторинг это замечает:
1. Сервис мониторинга Nova Uptime обнаруживает сбой
2. Nova Uptime вызывает ваш webhook URL с данными инцидента
3. Ваш сервер получает HTTP POST с:
- Доменом
- Статусом
- Временем обнаружения
- Временем отклика
- Результатом предыдущей проверки
4. Ваша система решает, что делать
- Создать Jira-тикет?
- Поднять дежурного?
- Обновить страницу статуса?
- Запостить в Slack?
5. Действия выполняются автоматически
Настройка вебхуков
Шаг 1. Создайте приёмник вебхука#
Приёмник — это простой HTTP-эндпоинт, принимающий данные инцидентов.
Пример: приёмник на Express.js
const express = require('express');
const app = express();
app.use(express.json());
app.post('/webhooks/uptime-incident', async (req, res) => {
const { domain, status, detectedAt, responseTime } = req.body;
console.log(`Incident detected: ${domain} is ${status}`);
// Handle the incident
await handleIncident({
domain,
status,
detectedAt,
responseTime
});
// Respond with 200 OK to acknowledge receipt
res.json({ success: true });
});
app.listen(3000, () => {
console.log('Webhook receiver listening on port 3000');
});
Шаг 2. Настройте вебхук в Nova Uptime#
- Войдите на go.novauptime.com
- Настройки домена → Webhooks
- «Добавить вебхук»
- URL вашего эндпоинта:
https://yourdomain.com/webhooks/uptime-incident - События для триггера:
- ✅ Сайт упал
- ✅ Сайт восстановлен
- ✅ Предупреждение по времени отклика
- Сохраните
Шаг 3. Протестируйте#
В большинстве инструментов есть кнопка «Test Webhook»:
- В настройках вебхука нажмите «Тест»
- Ваш эндпоинт получает тестовые данные
- Убедитесь, что система отвечает 200 OK
Реальные шаблоны вебхуков
Шаблон 1. Создание тикетов инцидентов#
При падении автоматически создавайте Jira-тикет.
async function handleIncident({ domain, status, detectedAt }) {
if (status === 'down') {
// Create Jira ticket
const ticket = await createJiraTicket({
project: 'OPS',
issueType: 'Incident',
summary: `Production Incident: ${domain} is down`,
description: `
Domain: ${domain}
Detected: ${detectedAt}
Status: DOWN
Actions:
1. Check server status
2. Review recent deployments
3. Check error logs
`,
priority: 'Critical',
labels: ['incident', 'production']
});
console.log(`Created ticket: ${ticket.key}`);
}
}
Шаблон 2. Обновление страницы статуса#
При инциденте автоматически обновляйте публичную страницу статуса.
async function handleIncident({ domain, status, detectedAt }) {
if (status === 'down') {
// Create incident on status page
await createStatusPageIncident({
name: `${domain} is Down`,
status: 'investigating',
body: `We're investigating an issue with ${domain}. More info coming soon.`,
affectedComponents: [domain]
});
} else if (status === 'up') {
// Resolve incident on status page
await updateStatusPageIncident({
status: 'resolved',
body: `${domain} is now back online. We apologize for the inconvenience.`
});
}
}
Шаблон 3. Поднять дежурного#
Слать SMS дежурному немедленно при критичных инцидентах.
async function handleIncident({ domain, status, detectedAt }) {
if (status === 'down') {
// Get current on-call engineer from PagerDuty
const oncall = await getOnCallEngineer();
// Send SMS
await sendSMS({
to: oncall.phone,
message: `CRITICAL: ${domain} is down. Incident ticket: JIRA-123`
});
// Also post to #incidents Slack channel
await postToSlack({
channel: '#incidents',
text: `@${oncall.slackHandle}: ${domain} is down. See JIRA-123`
});
}
}
Шаблон 4. История инцидентов#
Логировать все инциденты в БД для аналитики.
async function handleIncident({ domain, status, detectedAt, responseTime }) {
// Store in database
const incident = await Incident.create({
domain,
status,
detectedAt,
responseTime,
createdAt: new Date(),
handledAt: new Date(),
ticketCreated: false,
statusPageUpdated: false
});
console.log(`Stored incident: ${incident._id}`);
// Later: calculate MTTR, uptime %, etc.
await updateIncidentMetrics(domain);
}
Шаблон 5. Multi-service оркестрация#
Один сбой запускает действия в нескольких платформах.
async function handleIncident({ domain, status, detectedAt }) {
if (status === 'down') {
// Parallel actions: Don't wait for each to finish
await Promise.all([
createJiraTicket({ domain, status }),
createStatusPageIncident({ domain }),
pageOnCallEngineer({ domain }),
postSlackAlert({ domain }),
storeIncidentHistory({ domain, detectedAt }),
triggerPostmortemWorkflow({ domain })
]);
}
}
Продвинутые шаблоны
Шаблон 6. Условная логика по серьёзности#
Разные действия для разных уровней серьёзности.
async function handleIncident({ domain, status, severity }) {
if (severity === 'critical') {
// Critical: Page everyone
await pageOnCall({ priority: 'high' });
await updateStatusPage({ status: 'major_outage' });
await createJiraTicket({ priority: 'Critical' });
} else if (severity === 'warning') {
// Warning: Slack + Jira, no SMS
await postSlackAlert({ channel: '#alerts' });
await createJiraTicket({ priority: 'Medium' });
} else if (severity === 'info') {
// Info: Log only, no alert
await storeIncidentHistory({ domain });
}
}
Шаблон 7. Дедупликация#
Чтобы не плодить тикеты/алерты при многократных падениях одного домена.
async function handleIncident({ domain, status }) {
if (status === 'down') {
// Check if active incident already exists
const activeIncident = await Incident.findOne({
domain,
status: 'active',
createdAfter: new Date(Date.now() - 15 * 60 * 1000) // Last 15 mins
});
if (activeIncident) {
// Incident already reported, just update
activeIncident.lastSeen = new Date();
await activeIncident.save();
console.log(`Updated existing incident: ${activeIncident._id}`);
} else {
// New incident, create everything
await createJiraTicket({ domain });
await pageOnCall({ domain });
// ... etc
}
}
}
Шаблон 8. Ретраи неуспешных вебхуков#
Если приёмник упал, Nova Uptime должен повторять.
Конфигурация Nova Uptime:
- Настройки домена → Webhooks
- Откройте вебхук
- Advanced settings → Retry Policy
- Включите: «Retry on failure»
- Max retries: 3
- Задержка: экспоненциально (5с, 10с, 20с)
Ваш приёмник должен быть идемпотентным (безопасным к многократным вызовам):
// Good: Idempotent
async function handleIncident({ domain, status, eventId }) {
// Check if already processed
const processed = await ProcessedEvents.findOne({ eventId });
if (processed) {
return res.json({ success: true, cached: true });
}
// Process incident
await doActualWork();
// Record as processed
await ProcessedEvents.create({ eventId, processedAt: new Date() });
res.json({ success: true });
}
Примеры интеграций через вебхуки
Интеграция 1. Zapier#
Не хочется писать вебхуки — используйте Zapier:
- Nova Uptime → Zapier → Slack/Jira/Email/и т. п.
- Без кода
- Ограничения: меньше контроля, добавляется задержка
Интеграция 2. GitHub Actions#
При инциденте триггерим GitHub Action (например, авто-скейлинг, rollback):
async function handleIncident({ domain, status }) {
if (status === 'down') {
// Trigger GitHub Actions workflow
await triggerGitHubAction({
repo: 'mycompany/infrastructure',
workflow: 'incident-response.yml',
inputs: {
domain,
action: 'scale-up'
}
});
}
}
Интеграция 3. AWS Lambda#
Lambda для serverless-обработки вебхуков:
# AWS Lambda function
import json
import boto3
def lambda_handler(event, context):
body = json.loads(event['body'])
domain = body['domain']
status = body['status']
if status == 'down':
# Auto-scale on AWS
ec2 = boto3.client('ec2')
ec2.start_instances(InstanceIds=['i-1234567890abcdef0'])
return {
'statusCode': 200,
'body': json.dumps({'success': True})
}
Безопасность вебхуков
Проверка подписи вебхука
Nova Uptime подписывает каждый вебхук HMAC-SHA256. Проверяйте до обработки:
const crypto = require('crypto');
app.post('/webhooks/uptime-incident', (req, res) => {
const signature = req.headers['x-gum-signature'];
const body = JSON.stringify(req.body);
const secret = process.env.NOVAUPTIME_WEBHOOK_SECRET;
// Compute expected signature
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
if (signature !== expected) {
console.error('Invalid webhook signature');
return res.status(401).json({ error: 'Unauthorized' });
}
// Process webhook
handleIncident(req.body);
res.json({ success: true });
});
Rate limiting#
Приёмник должен ограничивать частоту:
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100 // max 100 requests per minute
});
app.post('/webhooks/uptime-incident', limiter, (req, res) => {
// Handle webhook
});
Обработка таймаутов
Приёмник должен отвечать быстро:
app.post('/webhooks/uptime-incident', async (req, res) => {
// Respond immediately
res.json({ success: true });
// Do real work in background
setTimeout(async () => {
await handleIncident(req.body);
}, 0);
});
Тестирование вебхуков
Метод 1. Локально через ngrok#
- Запустите локальный приёмник на localhost:3000
- Запустите ngrok:
ngrok http 3000 - Получите публичный URL:
https://abc123.ngrok.io - Настройте в Nova Uptime:
https://abc123.ngrok.io/webhooks/uptime-incident - Нажмите «Тест» в Nova Uptime → увидите запрос в локальной консоли
Метод 2. Webhook tester#
Используйте webhook.site бесплатно:
- Откройте webhook.site
- Скопируйте уникальный URL
- Настройте в Nova Uptime как приёмник
- Тест → запрос виден на webhook.site
Мониторинг ваших вебхуков
Отслеживайте здоровье:
async function monitorWebhookHealth() {
const stats = await WebhookEvent.aggregate([
{
$group: {
_id: null,
totalEvents: { $sum: 1 },
successCount: { $sum: { $cond: ['$success', 1, 0] } },
failureCount: { $sum: { $cond: ['$success', 0, 1] } },
avgResponseTime: { $avg: '$responseTime' }
}
}
]);
const successRate = stats[0].successCount / stats[0].totalEvents;
if (successRate < 0.95) {
// Alert: Webhook success rate below 95%
await alertSlack(`
Webhook health: ${(successRate * 100).toFixed(1)}% success rate
Failed events: ${stats[0].failureCount}
`);
}
}
Итог: чек-лист интеграции вебхуков
- ✅ Соберите эндпоинт-приёмник
- ✅ Настройте вебхук в Nova Uptime
- ✅ Протестируйте с тестовыми данными
- ✅ Проверяйте подпись (HMAC-SHA256)
- ✅ Реализуйте ретраи и идемпотентность
- ✅ Добавьте rate-limit на приёмник
- ✅ Обрабатывайте таймауты ответа
- ✅ Постройте workflow инцидентов (Jira + страница статуса + Slack)
- ✅ Протестируйте на реальном или симулированном инциденте
- ✅ Мониторьте здоровье вебхуков и долю успехов
- ✅ Документируйте эндпоинты для команды
Запускайтесь сегодня
Вебхуки превращают мониторинг из «только алертов» в полностью автоматизированную реакцию на инциденты.
Если у вас Nova Uptime — зайдите в настройки домена и добавьте первый вебхук. Начинайте с простого: просто логируйте инциденты в БД. Потом добавляйте интеграции по одной.
Документация по вебхукам: Документация API Nova Uptime
Monitor Your Website Before It Goes Down
Get uptime monitoring, SSL tracking, domain expiry alerts, and email health checks. Free plan — no credit card required.
Start Monitoring FreeПохожие статьи
Как интегрировать мониторинг uptime со Slack: гайд по алертам в реальном времени
Настройте Slack-алерты для простоев сайта за 10 минут. Маршрутизируйте инциденты в #alerts и сократите время реакции с 30 минут до 60 секунд.
Мониторинг сайтов через AI на MCP-сервере Nova Uptime
Подключите Nova Uptime к AI-ассистентам вроде Claude и Cursor через MCP. Настройте AI-мониторинг и проверки здоровья email за минуты.
Кастомные email-алерты и эскалации: продвинутая маршрутизация инцидентов
Спроектируйте процессы эскалации, поднимающие нужного человека в нужный момент. Гайд по маршрутизации алертов, on-call интеграциям и политикам эскалации.