Files
healthlog/docs/tasks/items/stats-endpoint.md
T
avandClaude Opus 5 a53d0f0f2f задачи: мета переехала в блок, поле «Хук» стало «Зачем»
49 файлов, миграция сделана командой tasks.py check --fix — той самой, ради
которой в скрипте оставлена читаемость старой формы. Побочно тот же прогон
проставил тег decomposed целям, у которых есть задачи: это его штатная работа.

check после миграции зелёный, индексы согласованы.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 17:31:29 +03:00

5.8 KiB
Raw Blame History

Наблюдаемость: /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: механизм условного запроса может перестать окупаться под плотным потоком, и снаружи это неотличимо от нормы.