fix(metrics): дисковые тревоги в абсолютных ГБ + алерт на скорость утечки #3542

Merged
lekss361 merged 1 commit from fix/disk-alerts-absolute-thresholds into main 2026-09-17 12:49:43 +00:00
Owner

Summary

Инцидент 16.09: кэш архивов Forgejo ел 2 ГБ/ч, диск на Beget (host=infra) — 145 ГБ. Проценты давали слишком короткое окно реакции ночью: DiskSpaceLow (85%, for=15m) = 21 ГБ запаса ≈ 10 ч до нуля, DiskSpaceCritical (93%, for=5m) = 10 ГБ ≈ 5 ч.

  • DiskSpaceLow / DiskSpaceCritical: пороги переведены с процентов на абсолютные ГБ свободного места (30 ГБ / 15 ГБ). Проценты на разных дисках значат разное: host=apps держит /-раздел ~910 ГБ, те же 85% там — ещё ~135 ГБ запаса; на host=infra (145 ГБ) это почти ничего. Абсолютный порог одинаково осмыслен на любом диске.
  • Оба правила сужены до mountpoint="/" — на /boot//boot/efi (меньше 1 ГБ целиком на обоих хостах) абсолютный порог горел бы постоянно.
  • Новое правило DiskSpaceDepletingFast: deriv() по 15-минутному окну, свободное место убывает быстрее ~1 ГБ/ч устойчиво 30 минут. Ловит именно быструю течь независимо от текущего уровня — пока Low/Critical ещё молчат, потому что места пока много.
  • DiskWillFillIn24h не тронут по логике, только добавлен фильтр mountpoint="/" для консистентности и annotation с человеко-читаемым дефицитом в ГБ вместо сырых байт predict_linear.

Как разделены роли (чтобы не было 3 писем об одном)

  • DiskSpaceDepletingFast — сигнал по СКОРОСТИ (>1 ГБ/ч), не зависит от уровня. Короткое окно (15m) → срабатывает быстро (~45 мин–1 ч).
  • DiskWillFillIn24h — подтверждённый ТРЕНД на 6h, ловит более медленные утечки, которые короткое окно не поймает, но которые всё равно упрутся в ноль за сутки. Срабатывает позже (окно сглаживания).
  • DiskSpaceLow/Critical — сигнал по АБСОЛЮТНОМУ уровню, независимо от того, есть ли активная утечка (например органический рост без резкого скачка).

На одной и той же быстрой утечке DiskSpaceDepletingFast и DiskWillFillIn24h МОГУТ сработать оба — это намеренная эскалация двумя разными сигналами в разное время (не дубль: разный текст, разное время срабатывания). Подробности — в комментариях ops/metrics/prometheus/rules/infra.yml.

Verification

promtool check rules (prom/prometheus:v3.1.0, entrypoint /bin/promtool):

Checking /rules/infra.yml
  SUCCESS: 24 rules found

Живые запросы к Prometheus на Beget (docker exec gendesign-prometheus wget -qO- ...), сейчас (свободно 104.8 ГБ на host=infra, диск 145 ГБ):

  • DiskSpaceLow raw expr (avail/1073741824 < 30) → пустой result (не горит)
  • Формула скорости (без >1) → host=infra: -3.18 (растёт на ~3.2 ГБ/ч — недавно почистили кэш архивов), host=apps: 0.21 ГБ/ч (ниже порога) — DiskSpaceDepletingFast не горит
  • Формула прогноза (без >0) → host=infra: -360.7, host=apps: -699.9 (глубоко отрицательные = запас профицитный) — DiskWillFillIn24h не горит

Не сделано (в рамках бюджета)

  • Не проверял вживую сработает ли DiskSpaceDepletingFast на синтетической утечке (нет безопасного способа сымитировать без риска для прод-диска).
  • Alertmanager/маршрутизация не трогал (явный запрет в задаче).

🤖 Generated with Claude Code

https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG

## Summary Инцидент 16.09: кэш архивов Forgejo ел 2 ГБ/ч, диск на Beget (host=infra) — 145 ГБ. Проценты давали слишком короткое окно реакции ночью: `DiskSpaceLow` (85%, for=15m) = 21 ГБ запаса ≈ 10 ч до нуля, `DiskSpaceCritical` (93%, for=5m) = 10 ГБ ≈ 5 ч. - `DiskSpaceLow` / `DiskSpaceCritical`: пороги переведены с процентов на абсолютные ГБ свободного места (30 ГБ / 15 ГБ). Проценты на разных дисках значат разное: host=apps держит `/`-раздел ~910 ГБ, те же 85% там — ещё ~135 ГБ запаса; на host=infra (145 ГБ) это почти ничего. Абсолютный порог одинаково осмыслен на любом диске. - Оба правила сужены до `mountpoint="/"` — на `/boot`/`/boot/efi` (меньше 1 ГБ целиком на обоих хостах) абсолютный порог горел бы постоянно. - Новое правило `DiskSpaceDepletingFast`: `deriv()` по 15-минутному окну, свободное место убывает быстрее ~1 ГБ/ч устойчиво 30 минут. Ловит именно быструю течь независимо от текущего уровня — пока Low/Critical ещё молчат, потому что места пока много. - `DiskWillFillIn24h` не тронут по логике, только добавлен фильтр `mountpoint="/"` для консистентности и annotation с человеко-читаемым дефицитом в ГБ вместо сырых байт predict_linear. ## Как разделены роли (чтобы не было 3 писем об одном) - `DiskSpaceDepletingFast` — сигнал по СКОРОСТИ (>1 ГБ/ч), не зависит от уровня. Короткое окно (15m) → срабатывает быстро (~45 мин–1 ч). - `DiskWillFillIn24h` — подтверждённый ТРЕНД на 6h, ловит более медленные утечки, которые короткое окно не поймает, но которые всё равно упрутся в ноль за сутки. Срабатывает позже (окно сглаживания). - `DiskSpaceLow`/`Critical` — сигнал по АБСОЛЮТНОМУ уровню, независимо от того, есть ли активная утечка (например органический рост без резкого скачка). На одной и той же быстрой утечке `DiskSpaceDepletingFast` и `DiskWillFillIn24h` МОГУТ сработать оба — это намеренная эскалация двумя разными сигналами в разное время (не дубль: разный текст, разное время срабатывания). Подробности — в комментариях `ops/metrics/prometheus/rules/infra.yml`. ## Verification `promtool check rules` (prom/prometheus:v3.1.0, entrypoint `/bin/promtool`): ``` Checking /rules/infra.yml SUCCESS: 24 rules found ``` Живые запросы к Prometheus на Beget (`docker exec gendesign-prometheus wget -qO- ...`), сейчас (свободно 104.8 ГБ на host=infra, диск 145 ГБ): - `DiskSpaceLow` raw expr (`avail/1073741824 < 30`) → пустой result (не горит) - Формула скорости (без `>1`) → host=infra: **-3.18** (растёт на ~3.2 ГБ/ч — недавно почистили кэш архивов), host=apps: **0.21** ГБ/ч (ниже порога) — `DiskSpaceDepletingFast` не горит - Формула прогноза (без `>0`) → host=infra: **-360.7**, host=apps: **-699.9** (глубоко отрицательные = запас профицитный) — `DiskWillFillIn24h` не горит ## Не сделано (в рамках бюджета) - Не проверял вживую сработает ли DiskSpaceDepletingFast на синтетической утечке (нет безопасного способа сымитировать без риска для прод-диска). - Alertmanager/маршрутизация не трогал (явный запрет в задаче). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG
lekss361 added 1 commit 2026-09-16 19:25:50 +00:00
fix(metrics): дисковые тревоги в абсолютных ГБ + алерт на скорость утечки
All checks were successful
CI Trade-In / changes (pull_request) Successful in 16s
CI / changes (pull_request) Successful in 19s
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 / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m34s
CI / backend-tests (pull_request) Successful in 6m40s
a8d3499bdc
Инцидент 16.09: кэш архивов Forgejo ел 2 ГБ/ч, а проценты на диске 145 ГБ
(host=infra) давали слишком короткое окно реакции (85% = 21 ГБ запаса,
93% = 10 ГБ). На диске host=apps (~910 ГБ) те же проценты значат совсем
другой запас в ГБ — переведено на абсолютные пороги (30/15 ГБ свободного
места), одинаково осмысленные независимо от размера диска. Сужено до
mountpoint="/" — на /boot и /boot/efi (меньше 1 ГБ целиком) абсолютный
порог горел бы постоянно.

Добавлен DiskSpaceDepletingFast: deriv() по 15-минутному окну, >1 ГБ/ч
устойчиво 30 минут — ловит именно быструю течь независимо от текущего
уровня заполнения, пока DiskSpaceLow/Critical ещё молчат (места много,
но утечка есть). DiskWillFillIn24h остаётся отдельным сигналом для более
медленных, но устойчивых трендов (предупреждает позже за счёт 6h окна
сглаживания шума) — роли не дублируют друг друга, разделение описано
комментариями в файле.

Проверено promtool check rules (24 rules found) и живыми запросами к
Prometheus на Beget — ни одно из трёх правил сейчас не горит.
lekss361 merged commit da5fd24435 into main 2026-09-17 12:49:43 +00:00
lekss361 deleted branch fix/disk-alerts-absolute-thresholds 2026-09-17 12:49:44 +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#3542
No description provided.