Files
jellybit/docs/backlog/oshibki-klassifikaciya-i-konvencii-logirovaniya.md
T
avandClaude Opus 4.8 7d8a455e47 Логирование: классификация доменных ошибок (500→409/400) + конвенции
Штатные конфликты и промахи ввода возвращались голым fmt.Errorf, поэтому
classifyErr отправлял их в 500 «внутренняя ошибка» вместо 409/400 (и logCmd
писал ERROR вместо DEBUG). Продолжение f8fb4fa (Tier A), по итогам ревью Fable.

Классификация ошибок:
- новый sentinel worker.ErrInvalidInput → 400 для валидации ввода команд
  (refine/set type/ignore/add source/set provider/choose candidate);
- обёртки %w ErrConflict в Cancel/Retry/Defer/Undo (штатный конфликт состояния);
- classifyErr: ErrInvalidInput→400, layout.ErrCollision→409 (коллизия цели
  штатно уводит в review); ветка ErrCollision в tgbot (сообщение + refreshCard);
- logCmd относит ErrInvalidInput и ErrCollision в DEBUG «command rejected».

Конвенции (docs/conventions):
- logging.md: публичные команды воркера = доменная граница (лог один раз,
  logCmd); таблица уровней доменных отказов (граница команды vs асинхронная
  стадия); правило про *url.Error/секреты в URL; канон категории
  state transition; уровень повторяющихся сбоев фоновых циклов;
- errors.md: таблица маппинга ошибка→статус; развилка «транзиентный ответ vs
  персистентная диагностика» решена как (а) — error_msg/reasons на review-экране
  и tg-карточке = операторская поверхность владельца (сырой текст ок, секреты
  запрещены; аудит подтвердил, что секреты туда не текут).

Унификация категории лога state transition: cancel/retry/relink/recovery
переведены с семантических msg на общий state transition (from/to) — весь
жизненный цикл собирается одним jq-фильтром.

Мелочи: reason-коды linkPlan в const-блок; httpapi лог-поля id→download_id и
msg «… failed»; комментарий «почему» у parseIgnored; preview build failure в
ReviewData DEBUG→WARN.

Беклог: задача сведена к остатку (ext.* ERROR-шторм при недоступном qBittorrent
+ эскалация устойчивого сбоя тика), понижена в приоритете.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 14:57:12 +03:00

4.1 KiB
Raw Blame History

Шум ERROR фоновых циклов при недоступной зависимости

Приоритет: низкий · Теги: review-fable, logging, reliability

Остаток от задачи «классификация доменных ошибок + конвенции логирования» (основное реализовано, см. ниже). Здесь — два смежных пункта про уровень повторяющихся сбоев фоновых циклов, каждый требует небольшого решения, а не только правки.

Что уже сделано (не переоткрывать)

Коммит f8fb4fa (Tier A) + коммит этой задачи закрыли:

  • Классификация доменных ошибок: sentinel worker.ErrInvalidInput→400; обёртки ErrConflict в Cancel/Retry/Defer/Undo; layout.ErrCollision→409 в classifyErr и ветка в tgbot; logCmd относит новые классы в DEBUG.
  • Конвенции: logging.md — команды воркера = доменная граница, таблица уровней доменных отказов (граница команды vs асинхронная стадия), правило про *url.Error/секреты в URL, канон категории state transition (унифицированы cancel/retry/relink/recovery). errors.md — таблица маппинга ошибка→статус, развилка «транзиентный ответ vs персистентная диагностика» решена как (а): error_msg/reasons — операторская поверхность владельца (сырой текст ок, секреты запрещены; аудит показал, что секреты туда не текут).
  • Мелочи: reason-коды const-блок; лог-поля iddownload_id; preview WARN; комментарий у parseIgnored.

Остаток

ERROR-шторм при недоступном qBittorrent

Клиент qbt логирует ext.* FailureERROR на каждом тике поллинга (torrents/info, internal/qbt/qbt.go), пока qBittorrent недоступен (рестарт демона, сеть). Домен уже пишет poll failed = WARN (по новой конвенции), но транспортная ext.*-запись остаётся ERROR по правилу ext-конвенции («сервис недоступен → ERROR»). При частом поллинге это шумит.

Развилка (решить до правки):

  • (а) Ввести у logging.ExtCall вариант с пониженным уровнем для рутинно-частых вызовов (симметрично SuccessDebug) — поллинг-вызовы (torrents/info) на транзиентном сбое пишут WARN, не ERROR;
  • (б) Дедуп/circuit-breaker: первый ERROR, дальше тишина до восстановления;
  • (в) Оставить как есть, признав ext.* ERROR легитимным сигналом «зависимость лежит» (тогда шум гасить уровнем сбора, а не кодом).

Эскалация устойчивого сбоя тика

Сейчас транзиентный сбой тика = WARN всегда. Договорённость на будущее (logging.md): устойчивый сбой N тиков подряд эскалировать в ERROR (реальная деградация, а не разовый промах). Не реализовано — нужен счётчик подряд-сбоев по циклу и порог в конфиге.

Вердикт: мелкая надёжностная полировка, не блокер. Делать вместе (обе про уровень сбоев фоновых циклов) или отдельной строкой.