fix(tradein/devops): логи в journald — переживают пересоздание контейнера (#2741) #2758

Merged
bot-backend merged 1 commit from fix/2741-log-retention into main 2026-08-06 21:24:58 +00:00

View file

@ -23,13 +23,47 @@
# ПЕРЕСОЗДАСТ ВСЕ tradein-контейнеры, включая scraper — прервёт бегущий sweep
# (stop_grace_period 120s даёт unit'у до-checkpoint'иться). Допустимо, разово.
#
# logging: json-file с ротацией (20m × 3 = ≤60M на сервис). До этого драйвер по
# умолчанию рос без границ. Общий anchor ниже.
# logging: journald (#2741). Было json-file 20m × 3 — оно решало только размер,
# и ценой того, что лог ЖИВЁТ В КОНТЕЙНЕРЕ: `docker rm` уносит его целиком.
# Деплоев ~20/сутки, скрейперы работают ночью, разбор идёт утром → окно жизни
# лога почти никогда не покрывает интересное (#2695, #2698, #2676 — три разбора
# подряд уперлись в «логов уже нет»).
#
# journald: демон отдаёт stdout/stderr в /var/log/journal (persistent, на хосте),
# запись переживает пересоздание контейнера и читается ПО ВРЕМЕНИ, а не «сколько
# осталось от последнего рестарта».
#
# КАК ЧИТАТЬ (проверено на проде 2026-08-06):
# docker logs tradein-scraper # как и раньше: только текущий контейнер
# # история через пересоздания — журнал принадлежит root, а deploy-юзер
# # gendesign состоит в docker, но НЕ в adm/systemd-journal, и sudo просит пароль,
# # поэтому голый `journalctl` у него выдаёт «No entries». Рабочий однострочник:
# docker run --rm -v /:/host:ro alpine chroot /host \
# journalctl -t tradein-scraper --utc --since "2026-08-07 00:30" --until "01:30"
# # то же по метке контейнера: CONTAINER_NAME=tradein-scraper (-o cat -f для tail -f)
# Владельцу стоит разово выдать `sudo usermod -aG adm gendesign` — после этого
# journalctl работает напрямую, без docker-обёртки (host-config, не этот файл).
#
# Ротация: журнал общий на хост, режется самим journald по размеру (SystemMaxUse)
# и НЕ обнуляется пересозданием контейнера — то есть глубина истории меряется
# сутками, а не «сколько прошло с последнего деплоя» (это и был баг #2741/#2715:
# 60 МБ json-file при флуде прокручивались за минуты, а деплой обнулял и их).
# Жёсткий потолок по возрасту (MaxRetentionSec) — при желании host drop-in.
# Замер 2026-08-06: /var/log/journal =
# 2.3G за 103 дня (~22 МБ/сутки системных) при дефолтном потолке SystemMaxUse=4G;
# tradein добавляет единицы-десятки МБ/сутки (5.8k карточек за сутки по
# scrape_runs, ~153 Б/строку) → до вытеснения старого ещё недели, требуемые
# «сутки-двое» покрыты с запасом. Дисковый риск нулевой: 4G — это ПОТОЛОК, при
# его достижении journald сам удаляет старейшее.
# Ceiling: journald рейт-лимитит (дефолт 10000 сообщений / 30s на сервис) — при
# превышении в журнал попадёт «Suppressed N messages». Июльский флуд postgres
# (40 МБ за 6 часов ≈ 12 строк/с) от лимита в ~25 раз ниже, но если такое
# появится — это host-config (drop-in journald.conf.d), не этот файл.
# tag: имя контейнера вместо ID — SYSLOG_IDENTIFIER стабилен между пересозданиями.
x-logging: &default-logging
driver: json-file
driver: journald
options:
max-size: "20m"
max-file: "3"
tag: "{{.Name}}"
services:
browser: