Активные мониторы
В отличие от heartbeat-а, где «звонит» сам ваш сервис, активный монитор работает наоборот: serverless-функция Notifly сама раз в N секунд дёргает заданный ресурс. Если заданное число попыток подряд завершилось ошибкой — приходит alert; когда связь возвращается — приходит recovery.
Поддерживается 11 типов проверок — от простого HTTP-GET до lightweight
protocol-handshake для SMTP / IMAP / POP3 / SSH / Redis / Postgres / MySQL,
DNS-резолва и проверки срока действия TLS-сертификатов:
kind | Что проверяет | Формат target |
|---|---|---|
http | GET <url>, ожидаем 2xx (или expectedStatus) | https://example.com/health |
tcp | TCP-handshake — порт открыт | host:port |
tls | TCP+TLS handshake; expectedStatus = минимальный запас по сроку сертификата (дней) | host:port |
smtp | TCP, читаем баннер 220, шлём EHLO/QUIT | mx.example.com:25 |
imap | TCP, ждём * OK ..., шлём LOGOUT | imap.example.com:143 |
pop3 | TCP, ждём +OK ..., шлём QUIT | pop3.example.com:110 |
ssh | TCP, читаем баннер SSH-2.0-... | host:22 |
redis | TCP, шлём PING\r\n, ждём +PONG | redis.example.com:6379 |
postgres | TCP, шлём StartupMessage, ждём R/E/N | db.example.com:5432 |
mysql | TCP, читаем handshake-пакет (protocol_version=10) | db.example.com:3306 |
dns | Резолв имени системным или указанным резолвером | example.com или example.com@8.8.8.8:53 |
Все TLS-варианты выполняются поверх обычного TCP (без StartTLS), поэтому для шифрованных портов указывайте уже-шифрованный порт (
smtp→:465,imap→:993,pop3→:995,redis→:6380и т.п.). Для проверки самого факта работы TCP — используйтеkind: "tcp".
Как это работает
Заголовок раздела «Как это работает»каждую минуту: timer-trigger → notifly-monitor └─▶ SELECT WHERE next_check_at <= now AND status != "paused" └─▶ HTTP GET / TCP Dial с timeoutSec ├─ успех → status=up, fail_count=0 │ если был "down" и есть recoveryMessage → recovery └─ ошибка → fail_count++; если ≥ consecutiveFails и не "down": отправить alert, status=down- Хранение — таблица
monitorsв YDB Serverless, индекс поnext_check_at. - Проверка — отдельная Cloud Function
notifly-monitor, запускается таймер- триггером Yandex Cloud (cron* * * * ? *— раз в минуту). - Уведомление — обычное сообщение Notifly, приходит через выбранное при создании монитора канал и доходит до всех ваших клиентов (web, Android, desktop), как любая другая push-нотификация.
События
Заголовок раздела «События»Поскольку общение инициирует сам Notifly, есть два явных события:
| Событие | Когда отправляется | Текст |
|---|---|---|
| Потеря связи (alert) | После consecutiveFails подряд неудач, только при первом переходе в down. К сообщению добавляется техническая ошибка (например, dial tcp: connect: connection refused) | alertMessage |
| Восстановление связи (recovery) | При первой успешной проверке после состояния down, только если задан recoveryMessage | recoveryMessage |
Повторного alert-спама не будет: пока монитор в down, новых сообщений не
шлётся, проверки продолжаются с обычным интервалом и просто фиксируют статус.
Создание монитора
Заголовок раздела «Создание монитора»Через админку
Заголовок раздела «Через админку»- Откройте app.notifly.ru → Мониторы.
- Нажмите «Создать монитор», заполните:
- Название — для отображения, например «Прод-сайт» или «Postgres-реплика».
- Канал — через какой канал слать уведомление.
- Тип проверки — один из 11 поддерживаемых
kind(см. таблицу выше). - Цель — формат зависит от типа: URL,
host:portили DNS-имя. - Период (сек) — между проверками (минимум 30, максимум 86400).
- Таймаут (сек) — сколько ждать ответа в одной попытке (1–60, по умолчанию 10).
- Подряд неудач — сколько подряд неудачных проверок до alert (по умолчанию 1; типично 2–3, чтобы не реагировать на единичные сетевые джиттеры).
- Ожидаемый HTTP-код (только
http) —0означает «любой 2xx», иначе явный код (например,200). - Запас по сертификату, дней (только
tls) —0= не проверять;30= алёрт за 30 дней до expiry. - Текст alert / recovery — что прилетит в push.
Через REST API
Заголовок раздела «Через REST API»# HTTP-проверкаcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Gotify-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Прод-сайт", "kind": "http", "target": "https://example.com/health", "intervalSec": 60, "timeoutSec": 10, "expectedStatus": 0, "consecutiveFails": 2, "alertMessage": "Сайт недоступен!", "alertPriority": 9, "recoveryMessage": "Сайт снова отвечает." }'
# TCP-проверкаcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Gotify-Key: <client-token>" \ -d '{ "appid": 12345, "name": "Postgres-реплика", "kind": "tcp", "target": "db-replica.internal:5432", "intervalSec": 60, "timeoutSec": 5, "consecutiveFails": 3, "alertMessage": "Реплика не принимает соединения.", "recoveryMessage": "Реплика снова доступна." }'
# TLS — алёрт за 30 дней до истечения сертификатаcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Gotify-Key: <client-token>" \ -d '{ "appid": 12345, "name": "SSL prod", "kind": "tls", "target": "example.com:443", "intervalSec": 3600, "timeoutSec": 10, "expectedStatus": 30, "alertMessage": "Сертификат example.com истекает менее чем через 30 дней!" }'
# DNS — проверка резолва через указанный серверcurl -X POST "$NOTIFLY_URL/monitor" \ -H "Content-Type: application/json" \ -H "X-Gotify-Key: <client-token>" \ -d '{ "appid": 12345, "name": "DNS prod-зоны", "kind": "dns", "target": "example.com@8.8.8.8:53", "intervalSec": 300, "timeoutSec": 5, "alertMessage": "DNS-зона example.com не резолвится через 8.8.8.8" }'Примеры по типам
Заголовок раздела «Примеры по типам»Характерные комбинации kind + target для частых задач:
{ "kind": "smtp", "target": "mx.example.com:25" } // SMTP-MX отвечает{ "kind": "imap", "target": "imap.example.com:143" } // IMAP жив (plain){ "kind": "pop3", "target": "pop3.example.com:110" } // POP3 жив{ "kind": "ssh", "target": "jump.example.com:22" } // SSH-баннер{ "kind": "redis", "target": "redis.example.com:6379"} // Redis отвечает на PING{ "kind": "postgres", "target": "pg.example.com:5432" } // PostgreSQL принимает соединения{ "kind": "mysql", "target": "db.example.com:3306" } // MySQL шлёт handshake{ "kind": "tls", "target": "smtps.example.com:465", "expectedStatus": 14 } // SSL-сертификат жив и не истечёт в ближайшие 14 днейЧерез MCP (для AI-ассистента)
Заголовок раздела «Через MCP (для AI-ассистента)»Если у вас настроен MCP-сервер Notifly (см. MCP), просто попросите:
Создай монитор для https://api.example.com/health, проверять каждые 30 секунд, алёрт после 3 подряд неудач с текстом «API лежит», recovery «API снова работает».
Доступные MCP-инструменты: list_monitors, create_monitor, update_monitor,
delete_monitor, pause_monitor, resume_monitor.
REST endpoints
Заголовок раздела «REST endpoints»| Метод | Путь | Описание |
|---|---|---|
GET | /monitor | Список мониторов пользователя |
POST | /monitor | Создать |
PUT | /monitor/:id | Обновить настройки (нельзя сменить appid) |
DELETE | /monitor/:id | Удалить |
POST | /monitor/:id/pause | Приостановить (проверки не выполняются) |
POST | /monitor/:id/resume | Возобновить |
Все endpoints, кроме pause/resume, требуют клиентский (или MCP) токен с правом write.
Почему YDB, а не S3
Заголовок раздела «Почему YDB, а не S3»См. ту же аргументацию для heartbeat: индексированный
точечный запрос по next_check_at дешевле и быстрее, чем перечисление S3-объектов.
Ограничения
Заголовок раздела «Ограничения»- Минимальный период: 30 секунд (чтобы не перегружать YDB).
- Максимальный период: 24 часа (для редких проверок выгоднее использовать heartbeat).
- Один вызов
notifly-monitorобрабатывает не более 200 просроченных мониторов (cron срабатывает раз в минуту, проверки выполняются последовательно). - Запросы идут из Yandex Cloud, поэтому целевой ресурс должен быть доступен из публичного интернета (или из приватной сети YC, если функция в нужной VPC).
- Все протокол-специфичные проверки (
smtp/imap/pop3/…) выполняются без StartTLS — для шифрованного варианта используйте уже-шифрованный порт (:465,:993,:995,:6380) сkind: "tls"илиkind: "tcp".