From 25c938a833b4747d759ecb3e0de7cce85df65e4d Mon Sep 17 00:00:00 2001 From: bot-backend Date: Sat, 12 Sep 2026 13:58:48 +0300 Subject: [PATCH] =?UTF-8?q?feat(ops):=20access-=D0=BB=D0=BE=D0=B3=D0=B8=20?= =?UTF-8?q?Caddy=20=D0=BD=D0=B0=20stdout=20=D0=B4=D0=BB=D1=8F=20=D0=B1?= =?UTF-8?q?=D0=BE=D0=B5=D0=B2=D1=8B=D1=85=20=D0=B4=D0=BE=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=D0=B2=20=E2=80=94=20Alloy=20=D1=82=D0=B5=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D1=8C=20=D0=B2=D0=B8=D0=B4=D0=B8=D1=82=20=D0=B8=D1=85=20?= =?UTF-8?q?=D0=B2=20Loki?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit За 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 --- caddy/sites/apps.caddy | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/caddy/sites/apps.caddy b/caddy/sites/apps.caddy index 5a47e1bd..1bc227e7 100644 --- a/caddy/sites/apps.caddy +++ b/caddy/sites/apps.caddy @@ -133,6 +133,35 @@ gendsgn.ru { format json } + # #3471: копия access-лога на stdout. За 3 часа наблюдения в + # gendesign-caddy-1 не было НИ ОДНОЙ строки http.log.access — только ACME/ + # TLS/warn от reverse_proxy, статусы/латентность/RPS прокси не видны в + # Loki вообще. Alloy на этом хосте уже собирает stdout контейнеров через + # journald (`loki.source.journal "host"`, + # ops/metrics/alloy/alloy-apps.alloy) — второй bind-монт не нужен. + # + # Секреты в query (`?secret=`, `?token=` и т.п., см. инцидент #3154) режет + # УЖЕ РАБОТАЮЩИЙ `loki.process.scrub_credentials` (#3354, тот же список + # имён параметров, что в app/core/log_scrub.py) — он стоит на пути ЛЮБОГО + # journal-лога, включая этот, поэтому второй слой скраба здесь не заводим. + # + # `log_skip` — общий для ВСЕХ логгеров сайта флаг на запрос (Caddy не даёт + # скипать выборочно по конкретному логгеру), поэтому /health и статика + # Next пропадают заодно и из файлового gendsgn.ru.log выше, не только из + # копии на stdout. Это осознанный побочный эффект, не только экономия: + # /health — 32% строк gendsgn.ru.log в измеренном сегменте (12.09.2026, + # 240 из 742 строк за ~4ч, аптайм-монитор раз в минуту) без диагностической + # ценности, и именно он гонит файловый лог через 50MiB roll_size так часто. + log access_stdout { + output stdout + format json + } + + @noisy_access_log { + path /health /_next/static/* + } + log_skip @noisy_access_log + route { # `/metrics` наружу не отдаётся — ни бэкендом, ни фронтом (#3078). # Сегодня он и так недостижим: бэкенду «Птицы» ниже уходят только @@ -375,6 +404,24 @@ meraocenka.ru { output file /var/log/caddy/meraocenka.ru.log } + # #3471: та же копия access-лога на stdout, что у gendsgn.ru — см. + # развёрнутый комментарий там (Alloy/journald, scrub_credentials #3354, + # log_skip общий на все логгеры сайта). `/trade-in/_next/static/*` — 5.1% + # строк meraocenka.ru.log в измерении 12.09.2026 (3782 из 73810 за + # ~17.6 суток без ротации, roll_size здесь вообще не настроен) — статика + # Next не может быть источником 5xx бэкенда. `/health` на этом домене не + # проксируется (allowlist ниже отдаёт по нему 404), но матчер добавлен для + # единообразия с gendsgn.ru — вреда от него ноль. + log access_stdout { + output stdout + format json + } + + @noisy_access_log { + path /health /trade-in/_next/static/* + } + log_skip @noisy_access_log + # `/metrics` наружу не отдаётся (#3078). Здесь действует белый список и # финальный `handle { respond 404 }`, так что путь и без этой строки не # проходит, — но у бэкенда «Меры» он ОТКРЫТ без авторизации ради агента