# Правила алертинга Prometheus. Подключены через
# `rule_files` в prometheus.yml. Метрики — из `backend/api/metrics.py`
# (см. комментарий в prometheus.yml про контракт имён).
#
# Проверка: алерт на искусственно заваленном пайплайне — остановить `llm`
# при активном `summarize_session` (см. `docs/deploy/monitoring.md`).
groups:
  - name: vidconf-pipeline
    rules:
      # Растёт число сеансов, застрявших в статусе `failed`
      # (`conference_sessions.pipeline_status`).
      # `delta()` — корректная функция PromQL именно для gauge (не
      # `increase()`, которая рассчитана на монотонные counter'ы).
      - alert: PipelineFailed
        expr: delta(vidconf_pipeline_sessions{status="failed"}[15m]) > 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Растёт число упавших сеансов пайплайна пост-обработки"
          description: >-
            За последние 15 минут число сеансов в статусе failed выросло
            на {{ $value }}. Смотреть логи worker/worker-transcriber и
            таблицу conference_sessions (pipeline_status).

      # Глубина хотя бы одной из очередей Celery устойчиво растёт 15 минут
      # подряд — воркеры не успевают за потоком задач (см.
      # docs/deploy/scaling.md — вынос очереди в отдельную реплику).
      - alert: QueueGrowing
        expr: delta(vidconf_celery_queue_depth[15m]) > 0 and vidconf_celery_queue_depth > 10
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Очередь Celery «{{ $labels.queue }}» растёт 15 минут подряд"
          description: >-
            Текущая глубина очереди {{ $labels.queue }}: {{ $value }} задач,
            рост не прекращается 15 минут — см. docs/deploy/scaling.md
            (вынос очереди в отдельную реплику/масштабирование).

      # LLM-сервер (llama.cpp, job `llm` — см. комментарий в prometheus.yml
      # про сетевой алиас `llm`/`llm-gpu`) недоступен. Актуально ТОЛЬКО на
      # инсталляциях с включённым профилем `llm`/`llm-gpu` (пресеты 3–5,
      # `install.sh`) — целевой набор профилей по умолчанию (`media,monitoring`,
      # см. .env.example) их не включает, поэтому правило закомментировано
      # вместе с job `llm` в prometheus.yml (иначе `up{job="llm"}` не находит
      # ни одной серии — сам по себе закомментированный job уже не даёт этому
      # алерту сработать, но держать активное правило на несуществующую
      # метрику вводит в заблуждение). Раскомментируйте оба вместе на
      # инсталляциях с профилем `llm`/`llm-gpu`.
      # - alert: LlmDown
      #   expr: up{job="llm"} == 0
      #   for: 2m
      #   labels:
      #     severity: critical
      #   annotations:
      #     summary: "LLM-сервер (llama.cpp) недоступен"
      #     description: >-
      #       Prometheus не может достучаться до llm:8080 дольше 2 минут —
      #       суммаризация встанет (задачи будут копиться в очереди summarize,
      #       см. также алерт QueueGrowing). Проверить
      #       `docker compose ps llm` / `llm-gpu` и `docker compose logs llm`.

  # Железо хоста (job `node` — node-exporter). Пороги подобраны под
  # конкретный сервер 1gb: 8 ГБ RAM, 4 CPU, 50 ГБ диска — если сервер
  # сменится, пересчитать.
  - name: vidconf-host
    rules:
      # MemAvailable — уже честная оценка Linux с учётом того, что легко
      # освобождаемый page cache/buffers не в счёт (в отличие от naive
      # used = total - free). 10% от 8 ГБ ≈ 800 МБ — `for: 10m`, чтобы не
      # дёргать на кратковременный всплеск (например, разовый всплеск
      # transcribe/summarize), но успеть среагировать до OOM killer.
      - alert: HostMemoryLow
        expr: (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 < 10
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "Мало свободной памяти на хосте"
          description: >-
            Свободно {{ $value | printf "%.1f" }}% RAM дольше 10 минут
            (порог 10% ≈ 800 МБ из 8 ГБ). Смотреть, какой контейнер ест
            память — дашборд «Хост и контейнеры», топ по памяти
            (container-exporter, см. deploy/monitoring/container-exporter/).

      # 50 ГБ диска — 10% ≈ 5 ГБ. `for: 15m` (не мгновенно): диск не растёт
      # так же резко, как память, ложные срабатывания на всплеск не грозят,
      # но и разовая проверка на границе некритична — 15 минут отсекает шум.
      - alert: HostDiskLow
        expr: (node_filesystem_avail_bytes{mountpoint="/",fstype!="tmpfs"} / node_filesystem_size_bytes{mountpoint="/",fstype!="tmpfs"}) * 100 < 10
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Мало места на диске хоста"
          description: >-
            Свободно {{ $value | printf "%.1f" }}% диска дольше 15 минут
            (порог 10% ≈ 5 ГБ из 50 ГБ). Частые причины на этом проекте —
            записи транскрибации (`recordings`), логи docker, образы/слои
            после пересборки — проверить `docker system df`.

      # 4 CPU. Порог 90% и `for: 15m` — сознательно строже по времени, чем
      # у памяти/диска: кратковременные пики от пайплайна пост-обработки
      # (транскрибация/суммаризация) — это ожидаемая, не аварийная нагрузка,
      # алерт должен ловить именно устойчивую перегрузку, а не обычный всплеск.
      - alert: HostCpuHigh
        expr: 100 - (avg(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
        for: 15m
        labels:
          severity: warning
        annotations:
          summary: "Устойчиво высокая загрузка CPU хоста"
          description: >-
            Загрузка CPU {{ $value | printf "%.1f" }}% дольше 15 минут
            подряд (порог 90% из 4 ядер). Смотреть топ контейнеров по CPU
            (дашборд «Хост и контейнеры») и латентность API — возможно,
            не хватает уровня AI/ресурсов под нагрузку.
