- рядом с воркером свёртки живёт горутина, раз в минуту разбирающая журнал пассивным чекпойнтом; «журнал не разбирается» видно строкой владельцу, а не только по `df`. Признак — пара чисел, а не флаг занятости: тот молчит под удерживаемым читателем (`busy=0` при 6256 страницах и пяти перенесённых), а при занятой блокировке отдаёт `-1` вместо ответа, и `-1 >= -1` читалось бы как «разобрано целиком» - каталог отвечает `304` на `If-None-Match`, не открывая снимок витрины. Метка собрана из всего, от чего зависит ответ: версии витрины (`data_version` с закреплённого соединения плюс поколение — значение локально для соединения и не переживает переоткрытия), горизонта измерения и области действия ресурса. Версия снимается до и после сборки: снятая после пометила бы устаревший снимок свежим номером - предел и дедлайн ответа отложены в задачу Read API точек вместе с измеренной ценой первого запроса; попутно починен флаки-тест чужой задачи, искавший значение точки в сыром буфере записи лога
60 lines
5.6 KiB
Markdown
60 lines
5.6 KiB
Markdown
# Наблюдаемость: /stats
|
||
|
||
**Приоритет:** средний
|
||
|
||
Тихо сломавшаяся автоматизация — главный эксплуатационный риск коллектора:
|
||
данные просто перестают приходить, и заметить это можно только по молчанию.
|
||
Расписание 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`: механизм условного запроса может
|
||
перестать окупаться под плотным потоком, и снаружи это неотличимо от нормы.
|