Access-логи Caddy доезжают в Loki: статусы и латентность прокси наконец видны #3478

Merged
lekss361 merged 1 commit from feat/3471-caddy-access-logs into main 2026-09-12 11:05:47 +00:00
Owner

Пункт из #3471, раздел «Слепые зоны мониторинга».

Чего не было

За три часа наблюдения в контейнере gendesign-caddy-1 не нашлось ни одной строки http.log.access — только ACME, TLS и предупреждения от reverse_proxy. Фронтовый прокси стоит перед всем продуктом, а его статусы, латентность и RPS в Loki не видны вообще: пятисотки приходится искать в логе uvicorn, доля отказов по прокси не измеряется.

Что сделано

В боевых site-блоках gendsgn.ru и meraocenka.ru добавлена вторая копия access-лога — JSON на stdout, рядом с уже существующим файловым логгером. Alloy на продуктовом хосте забирает stdout контейнеров через journald, поэтому ни нового бинд-монта, ни правки конфигурации Alloy не потребовалось.

Заодно подтвердилась ловушка, из-за которой правку легко было внести не туда: корневой Caddyfile — заготовка с import caddy/sites/{$CADDY_SITES}.caddy, а боевой конфиг собирается из caddy/sites/apps.caddy для Selectel и caddy/sites/infra.caddy для Beget плюс сниппеты. Вне git ничего из этого не живёт.

Объём

Замерено на проде по текущим файловым логам, а не прикинуто: около 4.5 тысяч запросов в сутки на gendsgn.ru и 4.2 тысячи на meraocenka.ru. После исключения шумных путей прирост в Loki составит 6-7 МБ в сутки при нынешних 39 МБ — то есть от 15 до 20 процентов.

Шумные пути вынесены в log_skip: /health на gendsgn.ru (32 процента строк в измеренном сегменте, аптайм-монитор раз в минуту) и статика Next.

Побочный эффект, о котором нужно знать: log_skip в Caddy — общий флаг на запрос, выборочно скипать только stdout-копию нельзя. Поэтому эти же пути исчезли и из файловых логов. Для /health и статики это осознанный размен: диагностической ценности в них нет, а файловый лог они гнали через ротацию впустую.

Секреты

Отдельный скраб в Caddy не заводился намеренно: loki.process.scrub_credentials в конфигурации Alloy, добавленный после инцидента #3154, стоит на пути любого journal-лога и режет ?secret=, ?token= и прочее до записи в Loki. Новый источник он покрывает автоматически, второй слой был бы дублированием с риском разъехаться.

Проверка

caddy adapt на полном дереве с CADDY_SITES=apps проходит без ошибок, логгер access_stdout зарегистрирован для обоих доменов.

caddy/sites/infra.caddy на Beget по-прежнему пишет только в файл. Это не продуктовый трафик, отдельная задача при необходимости.

Пункт из #3471, раздел «Слепые зоны мониторинга». ## Чего не было За три часа наблюдения в контейнере `gendesign-caddy-1` не нашлось ни одной строки `http.log.access` — только ACME, TLS и предупреждения от reverse_proxy. Фронтовый прокси стоит перед всем продуктом, а его статусы, латентность и RPS в Loki не видны вообще: пятисотки приходится искать в логе uvicorn, доля отказов по прокси не измеряется. ## Что сделано В боевых site-блоках `gendsgn.ru` и `meraocenka.ru` добавлена вторая копия access-лога — JSON на stdout, рядом с уже существующим файловым логгером. Alloy на продуктовом хосте забирает stdout контейнеров через journald, поэтому ни нового бинд-монта, ни правки конфигурации Alloy не потребовалось. Заодно подтвердилась ловушка, из-за которой правку легко было внести не туда: корневой `Caddyfile` — заготовка с `import caddy/sites/{$CADDY_SITES}.caddy`, а боевой конфиг собирается из `caddy/sites/apps.caddy` для Selectel и `caddy/sites/infra.caddy` для Beget плюс сниппеты. Вне git ничего из этого не живёт. ## Объём Замерено на проде по текущим файловым логам, а не прикинуто: около 4.5 тысяч запросов в сутки на `gendsgn.ru` и 4.2 тысячи на `meraocenka.ru`. После исключения шумных путей прирост в Loki составит 6-7 МБ в сутки при нынешних 39 МБ — то есть от 15 до 20 процентов. Шумные пути вынесены в `log_skip`: `/health` на `gendsgn.ru` (32 процента строк в измеренном сегменте, аптайм-монитор раз в минуту) и статика Next. **Побочный эффект, о котором нужно знать:** `log_skip` в Caddy — общий флаг на запрос, выборочно скипать только stdout-копию нельзя. Поэтому эти же пути исчезли и из файловых логов. Для `/health` и статики это осознанный размен: диагностической ценности в них нет, а файловый лог они гнали через ротацию впустую. ## Секреты Отдельный скраб в Caddy не заводился намеренно: `loki.process.scrub_credentials` в конфигурации Alloy, добавленный после инцидента #3154, стоит на пути любого journal-лога и режет `?secret=`, `?token=` и прочее до записи в Loki. Новый источник он покрывает автоматически, второй слой был бы дублированием с риском разъехаться. ## Проверка `caddy adapt` на полном дереве с `CADDY_SITES=apps` проходит без ошибок, логгер `access_stdout` зарегистрирован для обоих доменов. `caddy/sites/infra.caddy` на Beget по-прежнему пишет только в файл. Это не продуктовый трафик, отдельная задача при необходимости.
lekss361 added 1 commit 2026-09-12 11:00:18 +00:00
feat(ops): access-логи Caddy на stdout для боевых доменов — Alloy теперь видит их в Loki
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 13s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
25c938a833
За 3 часа в gendesign-caddy-1 не было ни одной строки http.log.access — только
ACME/TLS/warn от reverse_proxy. Статусы, латентность и RPS фронтового прокси
были не видны в Loki, 5xx приходилось искать в логе uvicorn.

Боевой конфиг собирается из caddy/sites/apps.caddy (импортируется корневым
Caddyfile через `import caddy/sites/{$CADDY_SITES:*}.caddy`, CADDY_SITES=apps
на Selectel/Poincare) — правка внесена туда, не в плоский Caddyfile в корне
(93 строки в git — это только заготовка, реальный конфиг на проде собирается
из caddy/sites/* + сниппетов, ~20КБ через admin API). caddy/sites/infra.caddy
(Beget: obsidian/errors/git.gendsgn.ru) не трогал — не боевой трафик, вне
скоупа issue.

Для gendsgn.ru и meraocenka.ru добавлен второй логгер (access_stdout, JSON)
рядом с существующим файловым — Alloy на этом хосте уже собирает stdout
контейнеров через journald (loki.source.journal в
ops/metrics/alloy/alloy-apps.alloy), второй bind-монт не нужен.

Объём: по измерению на проде 12.09.2026 (docker exec, wc -l + первый/последний
ts в текущих файловых логах) — gendsgn.ru ~4.5k запросов/сутки, meraocenka.ru
~4.2k запросов/сутки. После исключения шумных путей (см. ниже) новая копия
на stdout — это дополнительно ~6-7 МБ/сутки в Loki, то есть около +15-20% к
текущим ~39 МБ/сутки при ретенции 30 дней (после сжатия Loki фактический
прирост диска меньше).

Шумные пути исключены через log_skip: /health на gendsgn.ru — 32% строк
файлового лога в измеренном сегменте (аптайм-монитор раз в минуту, без
диагностической ценности), статика Next (_next/static, trade-in/_next/static)
на обоих доменах — 5.1% строк на meraocenka.ru. Важный нюанс: log_skip в
Caddy — общий флаг на запрос для ВСЕХ логгеров сайта, скипать выборочно
только stdout-копию нельзя, поэтому эти пути пропадают и из существующих
файловых логов тоже (gendsgn.ru.log, meraocenka.ru.log) — осознанный побочный
эффект, а не только экономия трафика в Loki.

Секреты в query-параметрах (?secret=, ?token= и т.п. — инцидент #3154) второй
раз не чистим: уже работающий loki.process.scrub_credentials в
ops/metrics/alloy/alloy-apps.alloy (#3354, тот же список имён, что в
app/core/log_scrub.py) стоит на пути ЛЮБОГО journal-лога и вырежет их до
записи в Loki. Alloy-конфиг не менял — существующий пайплайн уже покрывает
новый источник.

Осталось за скобками (не входит в этот PR): caddy/sites/infra.caddy на Beget
логирует access тем же способом (файл, не stdout) — если нужна наблюдаемость
git.gendsgn.ru/errors.gendsgn.ru/metrics.gendsgn.ru, это отдельная задача с
тем же паттерном.

Refs #3471
lekss361 merged commit 2d87f70711 into main 2026-09-12 11:05:47 +00:00
lekss361 deleted branch feat/3471-caddy-access-logs 2026-09-12 11:05:48 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3478
No description provided.