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

HTTP-мониторы (расширенные)

«Лёгкий» тип http в активных мониторах делает только GET <url> и сверяет статус-код с 2xx (или expectedStatus). Этого достаточно для простого health-check-а, но не покрывает случаи вроде «дёрни POST /api/login с JSON-телом и заголовком Authorization, а потом проверь, что в ответе пришёл "status":"ok" и код 200».

HTTP-монитор — это отдельная сущность со своим REST API, которая умеет:

  • произвольный метод — GET, POST, PUT, PATCH, DELETE, HEAD;
  • произвольные заголовки (headers) — JSON-объект {"Header": "Value"};
  • тело запроса (body) — для POST/PUT/PATCH;
  • фильтрацию ответа — по статус-коду, диапазону кодов, подстроке/regex в body, значению по JSONPath и максимальному времени ответа;
  • два режима реакции — алёртить «на совпадение» или «на несовпадение» фильтров.

Период, таймаут, число неудач подряд, тексты alert/recovery и пауза работают так же, как у обычных мониторов.

ПолеТипОбязательноОписание
appidnumberдаID канала, в который слать уведомления
namestringдаНазвание монитора, 1–200 символов
methodstringдаGET, POST, PUT, PATCH, DELETE, HEAD (регистр не важен)
urlstringдаВалидный http(s) URL на публичный адрес
headersstringнетJSON-объект заголовков: {"Authorization": "Bearer ..."}
bodystringнетТело запроса (для POST/PUT/PATCH)
intervalSecnumberдаПериод между проверками, 30–86400 секунд
timeoutSecnumberнетТаймаут одной попытки, по умолчанию 10, максимум 30
filterModestringдаalert_on_match или alert_on_mismatch (см. ниже)
filtersstringдаJSON-массив фильтров (см. Фильтры ответа); может быть []
consecutiveFailsnumberнетСколько подряд неудач до alert, по умолчанию 1, максимум 20
alertMessagestringдаТекст уведомления при срабатывании, 1–2000 символов
alertTitlestringнетЗаголовок уведомления
alertPrioritynumberнетПриоритет уведомления, 0–10 (им же уходит recovery)
recoveryTitlestringнетЗаголовок recovery-сообщения
recoveryMessagestringнетТекст при возврате в норму (если пусто — recovery не шлётся)

URL на приватные, loopback- и link-local-адреса отвергается (400) — и при сохранении, и в тестовом запросе; редиректы на такие адреса тоже не проходят. Редиректы на публичные адреса выполняются, фильтры применяются к финальному ответу.

filters — это JSON-массив объектов. Каждый объект — одно условие; внутри объекта все заданные поля должны выполняться одновременно (И), а массив в целом считается совпавшим, если выполнился хотя бы один объект (ИЛИ). Доступные поля фильтра:

Поле фильтраТипЧто проверяет
statusCodenumberТочный HTTP-код (0 = не проверять)
statusCodeMin / statusCodeMaxnumberДиапазон кодов [min, max] включительно (0,0 = не проверять; без max — до 999)
bodyContainsstringПодстрока, которую должен содержать body
bodyRegexstringРегулярное выражение (синтаксис Go) для body
jsonPathstringПуть в JSON-ответе: $.status, data.0.id; без jsonPathValue — достаточно наличия значения
jsonPathValuestringОжидаемое значение по jsonPath (сравнение строковое: 200, true, ok)
maxDurationMsnumberМаксимально допустимое время ответа в мс (0 = не проверять)

Body для bodyContains, bodyRegex и jsonPath читается до 64 КБ. JSONPath — простой обход $.a.b с числовыми индексами массивов $.a.0.b. Некорректный bodyRegex при сохранении не отвергается — такой фильтр просто никогда не совпадает.

  • alert_on_mismatch — описываете, как выглядит нормальный ответ. Если фактический ответ не совпал с фильтрами — проверка неудачна. Это «whitelist»-логика и самый частый сценарий.
  • alert_on_match — описываете проблемный ответ. Если фактический ответ совпал с фильтром — проверка неудачна. Удобно ловить конкретные ошибки.

Сетевая ошибка или таймаут — неудача в любом режиме.

// filterMode = "alert_on_mismatch":
// норма — код 200 и в JSON {"status":"ok"}; иначе алёрт.
[
{ "statusCode": 200, "jsonPath": "$.status", "jsonPathValue": "ok" }
]
// filterMode = "alert_on_match":
// алёртим, если в body встретилось слово maintenance ИЛИ код в 5xx.
[
{ "bodyContains": "maintenance" },
{ "statusCodeMin": 500, "statusCodeMax": 599 }
]
// норма — отвечает быстрее 800 мс и код 2xx (filterMode = "alert_on_mismatch"):
[
{ "statusCodeMin": 200, "statusCodeMax": 299, "maxDurationMs": 800 }
]

HTTP-монитор использует те же статусы, что и обычные мониторы: pending (создан или возобновлён, проверок ещё не было), up, degraded (есть неудачи, но порог consecutiveFails ещё не достигнут), down и paused.

СобытиеКогдаТекст
AlertПосле consecutiveFails неудачных проверок подряд, один раз на падение. К тексту в скобках добавляется причина: response mismatch: status=… duration=…ms, alert condition matched: … или текст сетевой ошибкиalertTitle + alertMessage
RecoveryПри первой успешной проверке после down — только если задан recoveryMessage и о падении действительно был отправлен alertrecoveryTitle + recoveryMessage

Повторного alert-спама не будет: отправив alert, монитор запоминает момент в поле alertedAt и, пока остаётся в down, новых сообщений не шлёт — проверки продолжаются и просто фиксируют статус. Исключение — re-arm: если через PUT /http-monitor/:id изменить параметры проверки (метод, URL, заголовки, тело, период, таймаут, filterMode, filters, consecutiveFails), отметка alertedAt сбрасывается и монитор проверяется сразу; если ответ всё ещё плохой, придёт свежий alert. Правка названия, текстов и приоритета расписание не сдвигает и re-arm не делает.

Что ещё влияет на уведомления — так же, как у обычных мониторов:

  • Окна обслуживания: в окне проверки идут и пишутся в историю, но alert откладывается — если после окна ответ всё ещё плохой, его отправит первая же проверка. Упал и поднялся внутри окна — не придёт ни alert, ни recovery.
  • Тихие часы подавляют эскалацию во внешние каналы для сообщений с приоритетом ниже breakthroughPriority (по умолчанию 8).
  • Статус-страница канала: переход в down открывает авто-инцидент, восстановление — закрывает.
  • Каждая проверка — одно событие дневной квоты; при исчерпании проверки откладываются до следующих суток.

В записи монитора, кроме настроек, хранятся status, failCount, lastCheckAt, lastError, lastStatusCode, lastBodyPreview (первые 512 байт ответа), nextCheckAt и alertedAt. История проверок — GET /monitor-history/http_monitor/:id (см. Активные мониторы).

Перед созданием монитора можно выполнить разовый запрос и посмотреть ответ — ничего не сохраняя. POST /http-monitor/test принимает method, url, headers, body, timeoutSec (по умолчанию 10, до 60) и возвращает statusCode, bodyPreview (первые 2048 байт), headers (JSON заголовков ответа), durationMs и error (если запрос упал). Фильтры тестовый запрос не применяет.

Окно терминала
curl -X POST "$NOTIFLY_URL/http-monitor/test" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <api-token>" \
-d '{
"method": "POST",
"url": "https://api.example.com/login",
"headers": "{\"Content-Type\": \"application/json\"}",
"body": "{\"user\":\"probe\",\"pass\":\"...\"}",
"timeoutSec": 10
}'
# → {"statusCode":200,"bodyPreview":"{\"status\":\"ok\"}","headers":"{...}","durationMs":134}
  1. Откройте app.notifly.ru → Мониторы → Создать → «Сайт или API доступен» (или вкладка HTTP-запросы → «Создать HTTP-монитор»).
  2. Укажите название, канал, метод, URL, при необходимости — заголовки и тело. Кнопкой «Тест запроса» проверьте, что приходит в ответ.
  3. Настройте период, таймаут и число неудач подряд.
  4. Опишите фильтры ответа и выберите режим фильтрации.
Окно терминала
curl -X POST "$NOTIFLY_URL/http-monitor" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <api-token>" \
-d '{
"appid": 12345,
"name": "API login health",
"method": "POST",
"url": "https://api.example.com/login",
"headers": "{\"Content-Type\": \"application/json\"}",
"body": "{\"user\":\"probe\",\"pass\":\"...\"}",
"intervalSec": 60,
"timeoutSec": 10,
"filterMode": "alert_on_mismatch",
"filters": "[{\"statusCode\":200,\"jsonPath\":\"$.status\",\"jsonPathValue\":\"ok\"}]",
"consecutiveFails": 2,
"alertMessage": "Логин-эндпоинт не отвечает как надо!",
"alertPriority": 9,
"recoveryMessage": "Логин снова работает."
}'

Поля headers, body и filters передаются строками (JSON внутри JSON), поэтому в curl-примерах их содержимое экранируется. PUT /http-monitor/:id принимает тот же набор полей целиком (кроме appid — канал сменить нельзя).

Если настроен MCP-сервер Notifly (см. MCP), достаточно описать задачу словами:

Заведи HTTP-монитор: POST на https://api.example.com/login с JSON-телом, проверяй каждую минуту, что код 200 и в ответе status=ok, алёрт после 2 неудач подряд.

МетодПутьОписание
GET/http-monitorСписок HTTP-мониторов пользователя
POST/http-monitorСоздать
POST/http-monitor/testРазовый тестовый запрос (без сохранения)
PUT/http-monitor/:idОбновить настройки (нельзя сменить appid)
DELETE/http-monitor/:idУдалить
POST/http-monitor/:id/pauseПриостановить проверки
POST/http-monitor/:id/resumeВозобновить: статус pending, проверка — сразу

Авторизация — заголовок X-Notifly-Key с API-токеном (или токеном устройства). Создание, изменение, удаление, пауза и возобновление требуют у API-токена доступа write; для списка и POST /http-monitor/test достаточно read. Токен, ограниченный каналами, видит и меняет только мониторы этих каналов. Share-токены каналов к этим ручкам не допускаются (403). Канал монитора должен быть вашим или расшаренным вам с правом отправки.