# Юнит-тесты правил `promtool test rules` (#3493). Исполняются деплоем метрик # перед reload Prometheus (.forgejo/workflows/deploy-metrics.yml): упавший тест # оставляет работающий Prometheus на прежних правилах. # # Каждый случай — ровно тот, что уже случился на проде, а не придуманный. rule_files: - ../rules/infra.yml evaluation_interval: 1m tests: # tradein-postgres, ночь 17.09: рабочий набор 98 % от лимита, но почти весь — # кэш страниц; анонимная память ~1 %. OOM не грозит — тревоги быть не должно. - interval: 1m input_series: - series: 'container_memory_working_set_bytes{host="apps",name="tradein-postgres"}' values: '2940x40' - series: 'container_memory_rss{host="apps",name="tradein-postgres"}' values: '40x40' - series: 'container_spec_memory_limit_bytes{host="apps",name="tradein-postgres"}' values: '3000x40' alert_rule_test: - eval_time: 30m alertname: ContainerNearMemoryLimit exp_alerts: [] # tradein-browser, 12.09: у потолка, и это анонимная память незакрытых # инстансов браузера. Тревога обязана прийти, и в тексте — доля, а не байты. - interval: 1m input_series: - series: 'container_memory_working_set_bytes{host="apps",name="tradein-browser"}' values: '1960x40' - series: 'container_memory_rss{host="apps",name="tradein-browser"}' values: '1900x40' - series: 'container_spec_memory_limit_bytes{host="apps",name="tradein-browser"}' values: '2000x40' alert_rule_test: - eval_time: 30m alertname: ContainerNearMemoryLimit exp_alerts: - exp_labels: severity: warning host: apps name: tradein-browser exp_annotations: summary: "Контейнер у своего потолка памяти" description: "apps / tradein-browser: 98% от mem_limit, и больше половины лимита — анонимная память процессов, которую ядро не вытеснит как кэш. Дальше OOM-kill." # 12.09–17.09: экспортёр Celery не поднят, серий нет вовсе, воркер при этом жив. # Должна гореть QueueExporterDown про celery — и НЕ должна NoActiveCeleryWorkers. - interval: 1m input_series: - series: 'up{job="redis",host="apps"}' values: '1x40' alert_rule_test: - eval_time: 30m alertname: NoActiveCeleryWorkers exp_alerts: [] - eval_time: 30m alertname: QueueExporterDown exp_alerts: - exp_labels: severity: warning job: celery exp_annotations: summary: "Метрики очереди не собираются" description: "celery-экспортёр на Poincare не отдаёт метрики (up=0 или серии нет вовсе). Это авария наблюдаемости, а не продукта: Redis и воркеры могут быть живы — проверь `docker ps`. Пока она горит, RedisDown и NoActiveCeleryWorkers молчат по построению." # Нормальная работа: экспортёр жив, воркер шлёт heartbeat — тишина. - interval: 1m input_series: - series: 'up{job="celery",host="apps"}' values: '1x40' - series: 'up{job="redis",host="apps"}' values: '1x40' - series: 'celery_worker_up{hostname="celery@worker",host="apps"}' values: '1x40' alert_rule_test: - eval_time: 30m alertname: NoActiveCeleryWorkers exp_alerts: [] - eval_time: 30m alertname: QueueExporterDown exp_alerts: [] # Воркер умер: экспортёр жив, серия воркера в 0. Прежнее правило # (`count(x == 1) == 0`) этот случай пропускало — count() от пустого вектора пуст. - interval: 1m input_series: - series: 'up{job="celery",host="apps"}' values: '1x40' - series: 'celery_worker_up{hostname="celery@worker",host="apps"}' values: '0x40' alert_rule_test: - eval_time: 30m alertname: NoActiveCeleryWorkers exp_alerts: - exp_labels: severity: critical exp_annotations: summary: "Ни одного живого воркера Celery" description: "celery-exporter работает, но не видит ни одного heartbeat от воркера Site Finder. Все periodic-таски (парсинг, аналитика, синк слоёв) встали." # Воркер умер давно: экспортёр вычистил его серию, осталось только `up`. - interval: 1m input_series: - series: 'up{job="celery",host="apps"}' values: '1x40' alert_rule_test: - eval_time: 30m alertname: NoActiveCeleryWorkers exp_alerts: - exp_labels: severity: critical exp_annotations: summary: "Ни одного живого воркера Celery" description: "celery-exporter работает, но не видит ни одного heartbeat от воркера Site Finder. Все periodic-таски (парсинг, аналитика, синк слоёв) встали." # #2214: tradein-backend умер, хост и агент живы — агент шлёт up=0. # До MeraBackendDown этот случай не давал ни одного сигнала вне Poincare. - interval: 30s input_series: - series: 'up{job="app",app="mera",instance="tradein-backend:8000",host="apps"}' values: '1x9 0x40' alert_rule_test: - eval_time: 15m alertname: MeraBackendDown exp_alerts: - exp_labels: severity: critical host: apps job: app app: mera instance: tradein-backend:8000 exp_annotations: summary: "Бэкенд «Меры» не отвечает" description: "Агент на Poincare 5 минут не может снять /metrics с tradein-backend (up=0), либо цель пропала из скрейпа. Проверь `docker ps` и /health изнутри сети. Лэндинг meraocenka.ru может открываться из кэша и при мёртвом бэкенде — это не признак жизни." # Окно деплоя: самый длинный провал за 26.08–17.09 — 4 нулевые точки подряд # (~2 минуты). Тревоги быть не должно. Заодно упавший бэкенд «Птицы» не должен # поднимать тревогу про «Меру». - interval: 30s input_series: - series: 'up{job="app",app="mera",instance="tradein-backend:8000",host="apps"}' values: '1x19 0 0 0 0 1x40' - series: 'up{job="app",app="sitefinder",instance="gendesign-backend-1:8000",host="apps"}' values: '0x64' alert_rule_test: - eval_time: 11m alertname: MeraBackendDown exp_alerts: [] - eval_time: 30m alertname: MeraBackendDown exp_alerts: [] # Цель пропала из скрейпа (агент жив, «Птица» снимается), серии «Меры» нет. - interval: 30s input_series: - series: 'up{job="app",app="sitefinder",instance="gendesign-backend-1:8000",host="apps"}' values: '1x40' alert_rule_test: - eval_time: 10m alertname: MeraBackendDown exp_alerts: - exp_labels: severity: critical host: apps job: app app: mera exp_annotations: summary: "Бэкенд «Меры» не отвечает" description: "Агент на Poincare 5 минут не может снять /metrics с tradein-backend (up=0), либо цель пропала из скрейпа. Проверь `docker ps` и /health изнутри сети. Лэндинг meraocenka.ru может открываться из кэша и при мёртвом бэкенде — это не признак жизни."