Тревоги печатали не ту величину, которую называли: «2.684e+11% от mem_limit» и «доля HOT 75.21%» при пороге 20% #3464
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3464
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/alert-value-is-not-the-ratio"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Найдено по боевым сообщениям в Telegram 12.09.2026 (скриншот от владельца).
Что приходило человеку
Причина — форма выражения, а не условие
В PromQL
A and Bвозвращает значения ЛЕВОЙ части, отфильтрованные правой. Значит в$valueпопадаетA, а не то отношение, ради которого правило написано.ContainerNearMemoryLimitcontainer_spec_memory_limit_byteshumanizePercentage→2.684e+11%PostgresLowHotUpdateRatiorate(tup_upd[6h])75.21%Условия срабатывания были верны — врал только текст. Поэтому дефект и прожил незамеченным: у памяти число абсурдно и его списывали на «глюк экспортёра», а у HOT — правдоподобно и притом противоречило собственному порогу правила.
Замеры на живом Prometheus (только чтение, 12.09)
container_spec_memory_limit_bytes{name="tradein-browser"}= 2 684 354 560 →humanizePercentageдаёт ровно2.684e+11 %, то самое число из сообщения. Настоящая доля в тот момент — 1.2 %.rate(pg_table_write_amplification_tup_upd{table="listings"}[6h])= 0.0411 → сообщение сказало бы «4.11 %». Настоящая доля HOT по listings = 0.00 %.Правка
Отношение вынесено влево, побочное условие — внутрь знаменателя, где оно и фильтрует серии, и защищает от деления на ноль:
Проверено на живом Prometheus: новое выражение памяти отдаёт доли 0.35–0.71 (топ —
gendesign-infra-postgres70.8 %), новое выражение HOT — доли 0.00–1.00.promtool check rules→ SUCCESS, 16 rules.Третье правило того же семейства,
PostgresDeadTuplesHigh, верно — но верно случайно: печатаемая величина совпала с левым операндом. Помечено комментарием, чтобы его не «причесали» по образцу двух других.Гейт
backend/tests/ops/test_alert_value_is_the_described_quantity.py— инвариант: если описание рендерит$valueкак долю (humanizePercentage), левая часть выражения (до первогоand/unless) обязана содержать деление. Плюс две именные проверки для правил, которые уже соврали.Фальсификация: вернул файл правил с
origin/main→ красныеtest_percentage_annotations_come_from_a_ratioиtest_known_two_rules_are_fixed; с правкой —3 passed.Чего этот PR НЕ делает
promtoolв CI: сейчас правила не валидируются вообще ничем, но это отдельная задача (здесьpromtool checkпрогнан руками на боевом контейнере).Приёмка
Следующая сработка любого из двух правил приходит с числом в диапазоне 0–100 %, согласованным с порогом правила.
Боевые сообщения в Telegram 12.09: «apps / tradein-browser: 2.684e+11% от mem_limit. Дальше OOM-kill.» «apps / listings: доля HOT 75.21%.» — при пороге срабатывания «доля < 20%» Причина общая и она про ФОРМУ выражения, а не про условие: в PromQL `A and B` возвращает ЗНАЧЕНИЯ ЛЕВОЙ части, отфильтрованные правой. В `$value` попадало A: - ContainerNearMemoryLimit: слева стоял `container_spec_memory_limit_bytes` — в сообщение уходил лимит в байтах (2 684 354 560), отрендеренный как процент. Замер 12.09: настоящее потребление того контейнера — 1.2 % лимита. - PostgresLowHotUpdateRatio: слева стоял `rate(tup_upd[6h])` — апдейтов в секунду. Это опаснее: 0.7521 превращалось в «75.21%», попадало в правдоподобный диапазон и противоречило собственному порогу, но выглядело настоящим числом. Замер 12.09 по listings: rate(tup_upd[6h]) = 0.0411 → сообщение сказало бы «4.11%», настоящая доля HOT = 0.00%. Условия срабатывания в обоих случаях были ВЕРНЫ — врал только текст, поэтому дефект и прожил незамеченным. Правка: отношение вынесено влево, а побочное условие — внутрь знаменателя (`X / (Y > 0)`), где оно и фильтрует серии, и защищает от деления на ноль. Проверено на живом Prometheus (только чтение): новое выражение памяти отдаёт доли 0.35–0.71 (топ — gendesign-infra-postgres 70.8 %), новое выражение HOT — доли 0.00–1.00. `promtool check rules` — SUCCESS, 16 rules. Третье правило того же семейства (PostgresDeadTuplesHigh) верно, но верно случайно: печатаемая величина совпала с левым операндом. Помечено комментарием, чтобы его не «причесали» по образцу двух других. Гейт: backend/tests/ops/test_alert_value_is_the_described_quantity.py — если описание рендерит `$value` как долю (`humanizePercentage`), левая часть выражения обязана содержать деление. Фальсификация: вернул файл правил с origin/main → красные test_percentage_annotations_come_from_a_ratio и test_known_two_rules_are_fixed; с правкой — 3 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>