Ext Ops Panel
Открыть панель

Главная/Документация/Мониторинг

Контракт мониторинга

Версия контракта 2.1.0 · schema_version payload 2.0

Мониторинг ставит ваше расширение под постоянное наблюдение: живой светофор на карточке в списке, базовый таб 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 на другой при настройке агента.

↓ Скачать OpenAPI 3.1 (YAML) /monitoring-openapi.yaml · info.version 2.1.0

1. Как это работает (два компонента, один светофор)

Расширение «стоит на мониторинге», когда мониторинг включён и настроен хотя бы один компонент. Иначе на карточке – нейтральная серая точка.

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 + graceok (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, прежде чем засчитается: это гасит единичные сетевые блипы.

Подтверждённых провалов подрядСветофор пинга
0ok
1warn
2 и болееcrit

Результаты пингов появляются first-party метриками ping:<name> в секции pings (Uptime) базового таба monitoring и в зарезервированной Telegram-строке pings: 🟢 api 210ms · 🟢 site 90ms · 🔴 docs (timeout). Число пингов на расширение и минимальный интервал зависят от тарифа:

ТарифUptime-пингов на расширениеMin интервал пинга
Trial35 мин
Indie35 мин
Studio101 мин
Fleet251 мин

Доступность мониторинга и число слотов зависят от тарифа; минимальный интервал heartbeat – 60s.

5. Как поставить расширение на мониторинг

В Settings расширения, блок мониторинга:

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: отдельное статус-сообщение и алерты

8b. Heartbeat веб-проекта

У веб-проекта свои heartbeat. Каждый принадлежит среде (например, Production) и имеет свой токен hb_. Правила отчёта те же, что в разделе 6; ниже только отличия.

POST /api/v1/heartbeat/report
Authorization: Bearer hb_<64 hex>
Content-Type: application/json

{"overall":"ok"}

8c. Кто и как подключается к вашим сервисам

Веб-проект может добавить проверки портов к Service, адрес которого задан хостом, например к почтовому серверу. Эти проверки делает сама Ext Ops Panel. Здесь сказано, кто подключается, что отправляется, как часто и как хост может отказаться. Контракт агента выше не меняется.

9. Машиночитаемый контракт

Формальное описание эндпоинта отчётов, схемы payload, зарезервированных id и семантики светофора – файл OpenAPI 3.1. Он несёт ту же версию контракта (2.1.0).

↓ Скачать OpenAPI 3.1 (YAML) /monitoring-openapi.yaml