Главная/Документация/Мониторинг
Контракт мониторинга
Мониторинг ставит ваше расширение под постоянное наблюдение: живой светофор на карточке в списке, базовый таб monitoring в Detail и отдельное Telegram статус-сообщение с edge-алертами. Он состоит из двух независимо включаемых компонентов: push-heartbeat (агент на стенде вашего сервиса репортит с заявленной периодичностью; молчание – само по себе сигнал) и uptime-пингов (панель сама проверяет доступность ваших публичных URL).
Важно о двух типах heartbeat. Эта страница описывает мониторинг регистрации Chrome-расширения: ваш агент отправляет отчёт в POST /api/v1/monitoring/report. Для окружений веб-проекта в панели используется отдельный POST /api/v1/heartbeat/report с другим токеном. Минимальный отчёт окружения: {"overall":"ok"}; также принимается payload кастом-метрик v2. Не меняйте один endpoint на другой при настройке агента.
1. Как это работает (два компонента, один светофор)
- Push-heartbeat: cron-скрипт на вашем хосте (например,
адаптированный
monitor.sh) POST-ит панели отчёт метрик v2 с заявленным интервалом. Каждый отчёт обязан нести зарезервированный итогoverall. Пропуски отчётов эскалируют светофор (dead-man's switch): умер хост, сеть или cron – видно именно потому, что вызовы прекратились. - Uptime-пинги: панель сама периодически дергает публичные URL, которые вы настроили (site, api, docs), и проверяет только доступность, никогда не содержимое. Агент не нужен, достаточно URL.
Расширение «стоит на мониторинге», когда мониторинг включён и настроен хотя бы один компонент. Иначе на карточке – нейтральная серая точка.
1b. Heartbeats и пул слотов
Мониторинг живёт на уровне расширения как два независимых плоских списка, делящих
один пул слотов: heartbeats (push-продюсеры, ранее «стенды») и
uptime-пинги (pull-проверки). У расширения может быть несколько
heartbeat'ов – например, главный хост и платный воркер. Каждый heartbeat шлёт отчёты
под своим токеном и сам объявляет презентацию (табы, секции, строки
Telegram) через свой label. Uptime-пинги – отдельный плоский список на
уровне расширения, не вложенный ни в какой heartbeat. Панель мержит всё в один
агрегатный светофор (worst-of), один Detail и одно сводное Telegram-сообщение.
Heartbeats и пинги делят единый на расширение пул слотов (slots):
один heartbeat = один слот, один активный пинг = один слот, сумма ≤ тарифного
max_slots (Trial 3 · Studio 10 · Fleet 25). Превышение пула →
409 slot_limit; после даунгрейда излишек приостанавливается (сначала
пинги, heartbeats – в последнюю очередь). В ответе есть slots_used и
max_slots для отображения бюджета в UI.
2. Светофор
Агрегат: worst-of по всем включённым heartbeat-компонентам и всем
активным пингам, где severity упорядочены как ok < warn < crit.
Компонент heartbeat'а – max(reported, watchdog): reported
– худшее из метрики overall и пробитых порогов (6.2)
из последнего принятого отчёта;
watchdog – floor по свежести, считается по часам приёма панели
(clock skew агента не вредит).
| Состояние | Цвет | Когда |
|---|---|---|
off | ⚪ серый | Мониторинг не включён или не настроен ни один компонент. |
paused | ⚪ серый | Включён, но заморожен (тариф-гейт или ручная пауза). Отчёты продолжают сохраняться. |
green | 🟢 | Все компоненты ok. |
yellow | 🟡 | Худший компонент warn. |
red | 🔴 | Худший компонент crit. |
Severity каноничны: ok | warn | crit.
Дружелюбные алиасы нормализуются на приёме: warning становится
warn; error и critical становятся crit.
3. Watchdog (пропуски heartbeat)
Ожидаемый интервал отчётов (от 60s до 24h) вы заявляете при включении
heartbeat. Дальше watchdog floor-ит светофор по свежести, с допуском
grace = max(60s, 25% интервала) на джиттер cron и сети:
| Возраст последнего принятого отчёта | Floor watchdog |
|---|---|
| до interval + grace | ok (green) |
| пропущен 1 отчёт (до 2 × interval + grace) | warn (yellow) |
| пропущено 2 и более отчётов | crit (red) |
Отвергнутый отчёт (401 / 413 / 422 / 429) не обновляет watchdog, поэтому сломавшийся агент честно эскалирует; причина последнего отказа видна в настройках мониторинга. Восстановление мгновенно: первый же принятый отчёт немедленно пересчитывает светофор.
4. Uptime-пинги
Пинг – именованная проверка доступности одного публичного https-URL. Панель делает GET с таймаутом 10s, следует максимум за 5 редиректами, не читает тело сверх минимума и считает успехом финальный статус класса 2xx (204 и 206 тоже засчитываются). Финальный 3xx (цикл или лимит редиректов), 4xx, 5xx, таймаут или DNS/TLS/сетевая ошибка – провал. Провалившаяся проверка подтверждается одним повтором через ~15s, прежде чем засчитается: это гасит единичные сетевые блипы.
| Подтверждённых провалов подряд | Светофор пинга |
|---|---|
| 0 | ok |
| 1 | warn |
| 2 и более | crit |
Результаты пингов появляются first-party метриками ping:<name>
в секции pings (Uptime) базового таба
monitoring и в зарезервированной Telegram-строке
pings: 🟢 api 210ms · 🟢 site 90ms · 🔴 docs (timeout).
Число пингов на расширение и минимальный интервал зависят от тарифа:
| Тариф | Uptime-пингов на расширение | Min интервал пинга |
|---|---|---|
| Trial | 3 | 5 мин |
| Indie | 3 | 5 мин |
| Studio | 10 | 1 мин |
| Fleet | 25 | 1 мин |
Доступность мониторинга и число слотов зависят от тарифа; минимальный интервал heartbeat – 60s.
5. Как поставить расширение на мониторинг
В Settings расширения, блок мониторинга:
- Включите мониторинг, если он доступен на вашем тарифе.
- Heartbeat: включите и заявите интервал отчётов; панель выдаст bearer токен мониторинга, он показывается ровно один раз (ротация доступна в любой момент; старый токен сразу получает 401). Положите токен и URL эндпоинта в окружение вашего агента.
- Пинги: добавьте именованные публичные URL (например,
site,api,docs) с per-ping интервалом, до лимита тарифа. - Telegram: включите доставку мониторинга и опционально задайте отдельную группу/чат.
6. Формат отчёта
Отчёт – тот же metadata-driven payload v2, что и в
контракте кастом-метрик (табы, секции,
строки Telegram, метрики), пушится в
POST /api/v1/monitoring/report с заголовком
Authorization: Bearer <токен мониторинга>. Мониторинг
добавляет зарезервированные id:
| Зарезервированный id | Статус | Смысл |
|---|---|---|
overall | обязателен | Метрика kind status: итог тика, severity ok | warn | crit. Кормит агрегат. Отчёт без валидной overall отвергается (422). |
issues | рекомендуем | Метрика kind list: текущие проблемы, items на верхнем уровне метрики. До 5 пунктов цитируются в тексте алертов. |
ping:* | запрещён | Namespace метрик-id наших собственных пингов; в push отвергается (422). |
pings | запрещён | Id Telegram-строки нашей строки пингов; в push отвергается (422). |
monitoring | таб панели | Id базового таба. Метрики могут адресоваться в него (dashboard.tab: "monitoring") без объявления в tabs; объявление игнорируется. |
base | таб панели | Id вкладки Basic, зарезервирован так же: объявление игнорируется. |
Лимиты: payload не более 64 KB, не более 200 метрик, не более 2 отчётов в минуту на источник (излишки получают 429 и не засчитываются как heartbeat).
Тело больше 64 KB получает 413 payload_too_large и никогда не обрезается и не
читается как отчёт покороче. Отчёт, нарушающий правила выше, получает 422 invalid_report
со списком всех проблем. Обе причины сохраняются как последняя ошибка heartbeat:
HTTP/1.1 413 Payload Too Large
{ "code": "payload_too_large", "message": "report is over 64 KB; send fewer metrics or split them across heartbeats",
"limit_bytes": 65536, "size_bytes": 71680 }
HTTP/1.1 422 Unprocessable Entity
{ "code": "invalid_report", "message": "report rejected",
"errors": [ "metric \"overall\" must have kind \"status\" (got \"text\")",
"metric id \"ping:x\" uses the reserved \"ping:\" namespace" ] }6.1. Пример отчёта
{
"schema_version": "2.0",
"generated_at": "2026-07-12T10:19:58Z",
"tabs": [ { "id": "stand", "title": "Stand", "order": 5, "icon": "server" } ],
"sections": [ { "tab": "stand", "id": "docker", "title": "Docker", "order": 0 },
{ "tab": "monitoring", "id": "host", "title": "Host", "order": 10 } ],
"telegram": { "header": "{sev} {name} monitoring",
"lines": [ { "id": "host", "order": 0, "prefix": "🖥 " },
{ "id": "docker", "order": 1, "prefix": "📦 " } ] },
"metrics": [
{ "id": "overall", "kind": "status", "state": "ok", "severity": "ok" },
{ "id": "issues", "kind": "list",
"items": [ { "text": "RAM 91% (7.1/7.8G)", "severity": "warn" } ],
"dashboard": { "show": true, "tab": "monitoring", "section": "host", "order": 0,
"render": "list", "name": "Issues" },
"telegram": { "show": false } },
{ "id": "ram", "kind": "percent", "label": "RAM", "value": 91, "severity": "warn",
"dashboard": { "show": true, "tab": "monitoring", "section": "host", "order": 1,
"render": "kpi" },
"telegram": { "show": true, "line": "host", "pos": 10,
"format": "RAM {value}%", "sep": " · " } }
]
}Успешный ответ:
{ "accepted": true, "effective": "green", "next_expected_by": "2026-07-12T10:26:13Z" }6.2. Пороги на метриках отчёта
Любая числовая метрика отчёта, кроме overall, может нести
thresholds (блок контракта кастом-метрик,
раздел 5.4). Severity такой метрики панель считает на приёме, а свет heartbeat равен худшему из
overall и пробитых порогов: метрика выше crit делает heartbeat
красным даже при overall = ok. recover сравнивается с
прошлым принятым отчётом того же heartbeat. Кривой блок даёт 422 invalid_report с
причиной в списке. Отчёт без порогов ведёт себя как раньше.
{ "id": "queue", "kind": "number", "label": "Mail queue", "value": 41,
"thresholds": { "direction": "above", "warn": 20, "crit": 100, "unit": "msgs", "recover": 15 },
"dashboard": { "show": true, "tab": "monitoring", "section": "host", "order": 2, "render": "kpi" },
"telegram": { "show": true, "line": "host", "pos": 20, "format": "queue {value}" } }Панель рисует её как 41 (порог 20/100 msgs) на жёлтой плитке, heartbeat жёлтый.
7. Интеграция монитор-скрипта (в стиле monitor.sh)
Если у вас уже крутится cron-скрипт health-check'а, добавьте один best-effort POST в конец его тика. Сбой доставки не должен ронять тик: затянувшееся молчание всё равно поймает watchdog.
# monitor.env
EXTOPS_REPORT_URL="https://extops.dev/api/v1/monitoring/report"
EXTOPS_REPORT_TOKEN="<токен мониторинга из Settings>"
# конец тика: собираем payload через jq из уже посчитанных значений
# и шлём best-effort (доставка никогда не роняет сам тик)
payload="$(jq -n --arg sev "$SEVERITY" '{
schema_version: "2.0",
generated_at: (now | todate),
metrics: [ { id: "overall", kind: "status", state: $sev, severity: $sev } ]
}')"
code="$(curl -sS -m 10 -o /tmp/extops-report.json -w '%{http_code}' -X POST "$EXTOPS_REPORT_URL" \
-H "Authorization: Bearer $EXTOPS_REPORT_TOKEN" \
-H "Content-Type: application/json" \
-d "$payload" || echo 000)"
# 413 payload_too_large: over 64 KB; 422 invalid_report: .errors lists every problem
case "$code" in 413|422) logger -t monitor "panel: $code $(jq -c . /tmp/extops-report.json)" ;; esac
Смаппьте severity вашего скрипта на канонический набор (critical
принимается и нормализуется в crit) и отдайте существующий список
проблем в метрику issues. Заявленный интервал держите равным
периоду cron.
8. Telegram: отдельное статус-сообщение и алерты
- Данные мониторинга уходят в Telegram отдельным редактируемым
статус-сообщением, не смешиваясь со статусом кастом-метрик: header +
зарезервированная строка
pings+ строки, объявленные вашим отчётом. - Опционально мониторинг маршрутизируется в отдельную группу/чат; если не задана, используется чат канала расширения. Бот-транспорт общий с каналом расширения.
- Edge-алерты срабатывают на каждую смену агрегатного цвета, в обе стороны, включая recovery обратно в green (с длительностью инцидента). Пока цвет стабилен – тишина; правки конфига (пауза, редактирование пингов) не алертятся.
8b. Heartbeat веб-проекта
У веб-проекта свои heartbeat. Каждый принадлежит среде (например, Production) и имеет свой
токен hb_. Правила отчёта те же, что в разделе 6; ниже только отличия.
POST /api/v1/heartbeat/report
Authorization: Bearer hb_<64 hex>
Content-Type: application/json
{"overall":"ok"}- Тело: отчёт v2 с обязательной метрикой
overallвида status или тонкое{"overall":"ok"}со значениемok,warnилиcrit. Тонкое тело панель превращает в отчёт v2 и хранит нормализованное тело. - Лимиты: не более 64 KB на отчёт, не более 4 отчётов в минуту на токен и не более 200 метрик. Отчёт больше 200 метрик получает 422, как у расширения.
- Ответы:
200 {"accepted":true,"light":"green"},401на неизвестный токен,413 payload_too_large,422 invalid_report,429сRetry-After: 60. Причины 413 и 422 видны как Last error в Setup, Monitoring. - Covers: heartbeat покрывает ноль или больше поверхностей своей среды. Его свет красит каждую покрытую поверхность; heartbeat без покрытия красит среду. Covers задаётся в панели, не в отчёте.
- Свет: зелёный до interval + grace после последнего принятого отчёта,
жёлтый до 2 × interval + grace, дальше красный, где
grace = max(60s, 25% of the interval). Интервал от 60 с до 24 ч. - Waiting for first report: новый heartbeat серый до первого принятого отчёта. Через 24 часа без отчёта он жёлтый и присылает одно уведомление; красным до первого отчёта он не бывает.
- Пороги: как в разделе 6.2. Свет в ответе 200 и в
панели равен худшему из свежести,
overallи пробитых порогов и через Covers доходит до покрытых поверхностей. - Вкладки: метрики с
tab:"monitoring"рисуются на первой вкладке раздела Monitoring проекта,baseтоже зарезервирован. Объявленные вами вкладки получают свои вкладки.
8c. Кто и как подключается к вашим сервисам
Веб-проект может добавить проверки портов к Service, адрес которого задан хостом, например к почтовому серверу. Эти проверки делает сама Ext Ops Panel. Здесь сказано, кто подключается, что отправляется, как часто и как хост может отказаться. Контракт агента выше не меняется.
- Откуда: один адрес,
89.117.144.124, с именемprobe.extops.dev. Имя резолвится в этот адрес, а адрес обратно в имя. Других точек наблюдения нет. - Только подтверждённые хосты: проверка идёт только на хост под доменом, который владелец проекта подтвердил записью DNS TXT или файлом well-known. Когда подтверждение пропадает, проверки встают на паузу.
- Порты: TCP 25, 110, 143, 465, 587, 993, 995; TLS 443, 465, 993, 995; SMTP 25 и 587; SMTPS 465; IMAP 143; IMAPS 993. Никакие другие порты не проверяются.
- TCP и TLS: подключиться и прочитать приветствие, которое отправит сервер, или пройти TLS-рукопожатие и прочитать сертификат. Ничего не отправляется.
- SMTP: дождаться приветствия
220, отправитьEHLO probe.extops.dev, отправитьSTARTTLS, если сервер его предлагает, и пройти рукопожатие, затем отправитьQUIT. SMTPS на порту 465 делает то же внутри TLS, без STARTTLS. - IMAP: дождаться
* OK, отправитьa1 CAPABILITY, на порту 143 отправитьSTARTTLS, если он предложен, отправитьID ("name" "ExtOpsPanel-Probe" "support-url" "https://extops.dev/docs/monitoring#probes")только если сервер объявил ID, затем отправитьLOGOUT. IMAPS на порту 993 делает то же внутри TLS. - Никогда не отправляется:
AUTH,LOGIN,AUTHENTICATE,MAIL FROM,RCPT TO,DATA,VRFY,EXPN,SELECT. Проба никогда не входит, не отправляет писем и не открывает почтовый ящик. Каждая строка до записи в сокет проходит закрытый список разрешённых команд, а тест падает, если любая другая команда дойдёт до сервера. - Как часто: почтовая проверка идёт не чаще раза в 5 минут на любом тарифе, с разбросом 10% в обе стороны. На один хост не больше одного соединения одновременно и не больше 40 соединений в час для всех проектов вместе. Сверх этого хост не трогаем до следующего часа.
- Когда сервер отказывает: SMTP
421останавливает все проверки этого хоста на час. SMTP554или IMAP* BYEзаписывается как отказ, и следующая попытка будет только в следующий интервал. - Пределы одной проверки: 5 секунд на подключение, 10 секунд на весь диалог, чтение не больше 4 КБ.
- Что хранится: результат, код ответа, задержка, первая строка приветствия не длиннее 120 символов без адресов e-mail, короткий список возможностей вроде STARTTLS и IMAP4rev1 и даты сертификата. Не хранится приветствие целиком, ответы на EHLO и ID и любые адреса.
- Как отказаться: если вы обслуживаете хост и не хотите этих проверок,
напишите на support@extops.dev с именем хоста. Мы
исключим хост или весь его домен, и после этого к нему ничего не подключается. Можно также
отвечать
421или закрыть доступ для89.117.144.124. Владелец проекта может в любой момент поставить проверку на паузу или удалить её в Setup, Monitoring.
9. Машиночитаемый контракт
Формальное описание эндпоинта отчётов, схемы payload, зарезервированных id и семантики светофора – файл OpenAPI 3.1. Он несёт ту же версию контракта (2.1.0).