# Юнит-тесты правил `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-таски (парсинг, аналитика, синк слоёв) встали."