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

Как работают наблюдаемость и алертинг

Проблема: автономная ночная платформа падает двумя очень разными способами — громко (исключение) и тихо (всё выходит с кодом 0 и не производит ничего). Классический мониторинг ловит первый род. Второй однажды бежал здесь два дня подряд: нули по всему флоту, ни одного алерта. Тот инцидент и сформировал этот дизайн.

Слой 1 — три примитива, делающие тишину структурно трудной

Заголовок раздела «Слой 1 — три примитива, делающие тишину структурно трудной»

Вся обработка ошибок стекается в три маленьких примитива:

ПримитивДля чегоГарантия
capture_exceptionЛюбая пойманная ошибкаНикогда не бросает; лог + метрика + долговечная строка error_event (секреты вычищены) одним вызовом
guarded(...)Одноразовые батч-операцииЛовит всё, захватывает, возвращает None — батч-шаг не может уронить процесс
supervise(...)Долгоживущие фоновые циклыНа краше: захват + рестарт с бэкоффом — цикл не может умереть молча

Третий — главный урок: проектор, вачдоги, health-монитор и автоскейлер бегут под супервизией, потому что тихо умерший фоновый цикл превращается в «платформа выглядит нормально и не делает ничего» — худший класс отказа автономной системы.

restart with backoffcrashSupervised background loopsprojectorwatchdoghealth monitorautoscalerAny caught errorcapture_exceptionstructured logerror countererror_eventdurable sink

Сток queryable (GET /api/v1/errors — см. Как читать ошибки); запись — best-effort по дизайну, поэтому структурная строка лога остаётся записью последней надежды для краша раньше event-loop.

Слой 2 — доктрина алертов «ноль — это провал»

Заголовок раздела «Слой 2 — доктрина алертов «ноль — это провал»»

Ночной прогон заканчивается самооценкой, различающей три плохих финала — и третий и есть доктрина:

half of collects failedgenerated 0, published 0all green but zero qualifiednormalNightly run endsAssesscollapse:exit 1 alertpublish_fail:exit 1 alertall_zero:exit 0, still alarmedvia dead-man's switchreport + success ping

all_zero — самый интересный: ничего не упало, все коды выхода чистые — но платформа, чья целая ночь произвела ноль полезного выхода, проваливает свою работу. Инфраструктурный мониторинг этого не видит; видит только проверка исхода.

Доставка алертов сама умеет умирать (хост, сеть, месседжинг-креды — или тот же облачный аккаунт, на котором прод). Поэтому финальный ярус инвертирован: ночная джоба пингует внешний сервис и на успехе, и на провале, а тревогу поднимает отсутствие любого пинга — из инфраструктуры, намеренно независимой от собственного аккаунта платформы. Kill-switch уровня провайдера, снёсший прод, не может снести то, что за продом смотрит.

Полный пайплайн типизированных алертов (уровни severity, ключи дедупа, rules-driven диспетчер, распределённый трейсинг) спроектирован и принят, но запаркован — сегодня бежит Phase-0 пояс выше: три режима исхода, error-сток и dead-man’s switch. Страница изменится, когда доедет остальное; до тех пор это честный инвентарь. Эндпоинта метрик-скрейпа тоже пока нет — счётчики есть, дашбордов нет.

GET /api/v1/errors?limit=5 показывает сток вживую; ночной отчёт (домен cycles) несёт оценку исхода последнего прогона.

Спеки: SPEC-060 (error-сток + примитивы), SPEC-091 (доктрина алертинга; полный диспетчер спроектирован, Phase-0 в проде).