docs: документация переведена на канон av-dev-pm

- беклог и план переехали в docs/tasks (38 задач, 11 целей), слаги
  переименованы с транслита на английские, 85 ссылок поправлены
- conventions.md разобран в docs/conventions/, local-research.md — в
  docs/research/, review-journal.md — в docs/review.md с разделом настройки
  конвейера; заведены security.md, adr/ и .pm.json
- шаг docs.py check добавлен в task gate; поведение в architecture.md помечено
  девятью маркерами долга, database.md получил настройки с числовым значением
This commit is contained in:
av
2026-08-03 17:14:53 +03:00
parent de7b15d48c
commit d79189be18
94 changed files with 1234 additions and 566 deletions
+59
View File
@@ -0,0 +1,59 @@
# Наблюдаемость: /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`: механизм условного запроса может
перестать окупаться под плотным потоком, и снаружи это неотличимо от нормы.