# Наблюдаемость: /stats **Секция:** инфра · **Хук:** Тихо сломавшаяся автоматизация — главный эксплуатационный риск, а сейчас факт виден только в логах · **Теги:** goal:observability Тихо сломавшаяся автоматизация — главный эксплуатационный риск коллектора: данные просто перестают приходить, и заметить это можно только по молчанию. Расписание HAE — пожелание, а не гарантия (находка 28), так что молчание случается штатно. `/stats` отвечает на «жив ли поток» без чтения логов: последняя доставка по каждой автоматизации, счётчики за сутки, тишина в часах, доля доставок с ошибкой разбора, строки без кода в словаре категориальных значений. Готово, когда по одному запросу видно, какая из автоматизаций замолчала и когда. Отдельной строкой — **отставание фоновой свёртки**: длина очереди (`parse_status = 'pending'`) и возраст самой старой неразобранной доставки. Сегодня об этом говорят только две метки в логе (`WARN` «доставка ждала свёртки дольше пяти минут» и `INFO` о размере задолженности при старте), а `/healthz` статичен и здорового сервиса от сервиса с сотней несвёрнутых тел не отличает. Пришло из задачи «Разнести ответ приёма и свёртку доставки»: там числа намеренно не заводились, чтобы не предрешать форму счётчиков этой задачи. Длина очереди обязана быть видна **и без `WARN`**. После миграции, переводящей доставки в `pending`, весь исторический бэклог встаёт в очередь перед свежими доставками, а `warnLag` на это время намеренно подавлен (`startupDone`) — то есть отставание по конструкции не WARN-ится ровно тогда, когда оно максимально, и бэклог идёт молча при зелёном `/healthz`. Пришло из дозакрытия находок ревью по слиянию сущностей (проход `ops`, находка O1); оракула нет — он потребовал бы десятков тысяч доставок. Активное уведомление — отдельная задача, здесь только факт. **Что добавил каталог рода агрегации.** Реальный сценарий поломки измерения — не противоречие свидетельств (его на корпусе не бывает), а их исчезновение: владелец переставил автоматизацию HAE, минутный слой перестал приходить, метрики одна за другой уезжают в `unknown`, Read API перестаёт агрегировать — и в логах ноль событий. Сюда же вторая половина: пять разных причин непригодности часа (две точки у часового объекта, невыровненная метка, нет числа, мало минутных, неразличимость) схлопнуты в одну разность `hours − compared`, поэтому «HAE переименовал поле точки» неотличимо от «данных мало». Оба сигнала естественно живут в `/stats`: число метрик по родам и число метрик с `compared == 0` при непустом окне. **Корреляция у контура чтения.** В записи `http request` нет ни идентификатора запроса, ни адреса клиента: жалобу потребителя не сопоставить с записью, а выгрузку каталога посторонним — не отличить от планового опроса агента. У приёма корреляция есть (`delivery_id`), у чтения аналога нет. **Обслуживание журнала WAL тоже спрашивается здесь.** Признак «журнал не разбирается» (чекпойнт по таймеру, change `cena-chitayushchego-marshruta`) живёт одной строкой `WARN` в ротируемом docker-логе: состояние держится днями, а сказано о нём один раз. Вопрос «журнал сейчас разбирается?» сегодня не имеет ответа нигде, кроме `df`. В `/stats` просятся последний исход чекпойнта (когда, сколько страниц лежит и сколько перенесено) и — тем же полем — доля ответов чтения, которые удалось подписать `ETag`: механизм условного запроса может перестать окупаться под плотным потоком, и снаружи это неотличимо от нормы.