From ec85ea1861222300c8116041fadf57cbc0868255 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Thu, 17 Sep 2026 12:43:48 +0500 Subject: [PATCH] =?UTF-8?q?fix(metrics):=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BA?= =?UTF-8?q?=D0=B0=20queries.yml=20=D0=B4=D0=BE=D0=B5=D0=B7=D0=B6=D0=B0?= =?UTF-8?q?=D0=B5=D1=82=20=D0=B4=D0=BE=20postgres-=D1=8D=D0=BA=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D1=91=D1=80=D0=BE=D0=B2=20(#3486)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit queries.yml смонтирован трём экспортёрам одним файлом и читается только при старте, а агентские джобы деплоя пересоздавали лишь alloy: правка ложилась на диск новым инодом, экспортёры продолжали отдавать старые запросы при зелёном деплое. Разрыв латентный — 17.09 иноды хоста и контейнеров совпадают (Poincare 5112170, Beget 569352). agent-apps и agent-infra после подъёма сверяют инод queries.yml у своих экспортёров через ops/metrics/recreate-stale-mount.sh и пересоздают только при расхождении, под гейтом профиля. Гейт пофайловых маунтов теперь читает и docker-compose.metrics-agent.yml (сервис → джоба по профилю), а ci.yml запускает backend-тесты на правку этого файла. Co-Authored-By: Claude Opus 5 --- .forgejo/workflows/ci.yml | 4 ++++ .forgejo/workflows/deploy-metrics.yml | 22 +++++++++++++++++++ .../ops/test_metrics_single_file_mounts.py | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 178e1246..b599c368 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -233,6 +233,10 @@ jobs: # уезжает в main зелёной. Ровно то, что осуждает комментарий выше. - '.forgejo/workflows/deploy-metrics.yml' - 'docker-compose.metrics.yml' + # #3486: гейт test_metrics_single_file_mounts.py читает и + # compose агентов — правка ТОЛЬКО его (новый пофайловый маунт у + # экспортёра) без этой строки прошла бы мимо гейта. + - 'docker-compose.metrics-agent.yml' # #3443: тот же класс, третий раз. Гейт # backend/tests/ops/test_3443_caddy_reload_not_recreate.py не читает # ops/caddy-apply.sh, а ИСПОЛНЯЕТ его с подставным `docker` — то есть diff --git a/.forgejo/workflows/deploy-metrics.yml b/.forgejo/workflows/deploy-metrics.yml index 5b77f2ad..01407644 100644 --- a/.forgejo/workflows/deploy-metrics.yml +++ b/.forgejo/workflows/deploy-metrics.yml @@ -599,6 +599,21 @@ jobs: [ "$(stat -c %i ops/metrics/alloy/alloy-apps.alloy)" = "$(docker exec gendesign-alloy stat -c %i /etc/alloy/config.alloy)" ] \ || { echo "::error::alloy читает старый инод конфига"; exit 1; } + # ── postgres-экспортёры: queries.yml — бинд-маунт ОДНОГО файла (#3486) ── + # PG_EXPORTER_EXTEND_QUERY_PATH читается только при старте, а + # `git reset --hard` пишет правку новым инодом: без пересоздания + # экспортёр продолжает отдавать старые запросы при зелёном деплое. + # Пересоздаём только при расхождении инода. Под гейтом профиля: + # `up` с явным именем сервиса включает его профиль сам. + if [ -n "$EXPORTER_PROFILE" ]; then + METRICS_ROLE=apps METRICS_ALLOY_CONFIG=alloy-apps.alloy COMPOSE_PROFILES="$EXPORTER_PROFILE" \ + sh ops/metrics/recreate-stale-mount.sh gendesign-metrics-agent docker-compose.metrics-agent.yml \ + postgres-exporter-gendesign ops/metrics/postgres/queries.yml /etc/pg-queries.yml + METRICS_ROLE=apps METRICS_ALLOY_CONFIG=alloy-apps.alloy COMPOSE_PROFILES="$EXPORTER_PROFILE" \ + sh ops/metrics/recreate-stale-mount.sh gendesign-metrics-agent docker-compose.metrics-agent.yml \ + postgres-exporter-tradein ops/metrics/postgres/queries.yml /etc/pg-queries.yml + fi + agent-infra: runs-on: ubuntu-latest needs: server @@ -668,3 +683,10 @@ jobs: [ "$(stat -c %i ops/metrics/alloy/alloy-infra.alloy)" = "$(docker exec gendesign-alloy stat -c %i /etc/alloy/config.alloy)" ] \ || { echo "::error::alloy читает старый инод конфига"; exit 1; } + + # queries.yml экспортёра инфраструктурной БД — см. agent-apps (#3486). + if [ -n "$EXPORTER_PROFILE" ]; then + METRICS_ROLE=infra METRICS_ALLOY_CONFIG=alloy-infra.alloy COMPOSE_PROFILES="$EXPORTER_PROFILE" \ + sh ops/metrics/recreate-stale-mount.sh gendesign-metrics-agent docker-compose.metrics-agent.yml \ + postgres-exporter-infra ops/metrics/postgres/queries.yml /etc/pg-queries.yml + fi diff --git a/backend/tests/ops/test_metrics_single_file_mounts.py b/backend/tests/ops/test_metrics_single_file_mounts.py index 0cd8fb3f..91511daf 100644 --- a/backend/tests/ops/test_metrics_single_file_mounts.py +++ b/backend/tests/ops/test_metrics_single_file_mounts.py @@ -226,6 +226,7 @@ RENDERED = { MOUNT = re.compile(r"^\./(?P(?:\$\{[^}]*\}|[^:])+):(?P/[^:]+)") COMPOSE_FILES = { "docker-compose.metrics.yml": "gendesign-metrics", + "docker-compose.metrics-agent.yml": "gendesign-metrics-agent", } @@ -296,6 +297,9 @@ def test_gate_sees_the_known_mounts() -> None: server = {(s, src) for s, src, _d, _p in _file_mounts("docker-compose.metrics.yml")} assert ("prometheus", "ops/metrics/prometheus/prometheus.yml") in server, server assert ("loki", "ops/metrics/loki/loki-config.yml") in server, server + agent = {(s, src) for s, src, _d, _p in _file_mounts("docker-compose.metrics-agent.yml")} + for exporter in ("gendesign", "tradein", "infra"): + assert (f"postgres-exporter-{exporter}", "ops/metrics/postgres/queries.yml") in agent, agent def test_gate_would_notice_a_mount_without_arrival() -> None: