Настройка tail latency amplification мониторинга (p99/p50)

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настройка tail latency amplification мониторинга (p99/p50)

1. Цель задачи

Научиться выявлять и алертить аномалии хвостовой задержки (tail latency amplification) в распределённой системе. Ключевой результат — алерт при отношении p99 к p50 (ratio) > 5, который сигнализирует о деградации качества обслуживания, когда небольшое число запросов испытывает существенно большую задержку, чем медианные. Вы настроите сбор метрик, вычисление ratio в Prometheus, запись правила алерта и визуализацию в Grafana.

2. Исходные данные

Что нужноОткуда взять
Система, генерирующая метрики latency (гистограммы)Создать эмулятор микросервиса с Python и prometheus_client
Prometheus (latest)prometheus.io/download
Grafana (latest)grafana.com/oss/grafana
Alertmanager (опционально)prometheus.io/download/#alertmanager
Docker (рекомендуется)docker.com, docker-compose

Если нет реального инструмента — симулируем:

  1. Напишите Python-скрипт latency_emulator.py, который каждые 5 секунд эмулирует 1000 запросов с нормальным распределением loc=0.1, scale=0.02 (сек) и с вероятностью 1% добавляет "хвостовые" задержки из Triangular(0.5, 0.5, 2.0). Это создаёт подъём p99 без изменения p50.
  2. Используйте prometheus_client для создания гистограммы request_duration_seconds с бакетами [0.01, 0.05, 0.1, 0.2, 0.5, 1.0, 2.0, 5.0].
  3. Экспортируйте метрики на порту 8000.
  4. Для проверки ratio вручную можно запустить скрипт и через curl localhost:8000/metrics посмотреть _bucket счётчики.

3. Технологический стек

КомпонентИнструментыНазначение
Эмулятор сервисаPython 3.10+, prometheus-client==0.19.0Генерация гистограмм latency
Сбор метрикPrometheus (2.50+)Хранение и вычисление ratio
АлертингPrometheus Alertmanager / встроенные правилаОтправка уведомлений при ratio > 5
ВизуализацияGrafana (10+)Дашборд с p50, p99, ratio
ОркестрацияDocker, docker-compose (опционально)Быстрый запуск инфраструктуры
ЗапросыPromQLВычисление p50, p99, ratio

4. Этапы выполнения

Этап 1: Подготовка окружения (30 мин)

Действия

  1. Установить Docker и docker-compose (если не установлены).
  2. Создать директорию tail-latency-lab/.
  3. Внутри создать docker-compose.yml с сервисами:
  4. Создать Dockerfile для эмулятора и requirements.txt с prometheus-client.
  5. Написать prometheus.yml:
    global:
      scrape_interval: 15s
      evaluation_interval: 15s
    scrape_configs:
      - job_name: 'latency-emulator'
        static_configs:
          - targets: ['latency-emulator:8000']
    rule_files:
      - 'rules.yml'
    
  6. Создать пустой rules.yml (заполним позже).
  7. Запустить docker-compose up -d и убедиться, что все сервисы запущены.

Ожидаемый результат этапа
Контейнеры запущены, Prometheus доступен на localhost:9090, Grafana на localhost:3000, эмулятор экспортирует метрики.


Этап 2: Создание эмулятора с гистограммами (1 час)

Действия

  1. В latency_emulator.py реализовать:
    • Гистограмму request_duration_seconds с указанными бакетами.
    • Каждые 5 секунд генерировать 1000 случайных задержек:
      • Основной поток: numpy.random.normal(0.1, 0.02).
      • 1% хвостовых: numpy.random.triangular(0.5, 0.5, 2.0).
    • Для каждой задержки вызывать histogram.observe(delay).
    • Запустить HTTP-сервер на порту 8000 с start_http_server.
    • Выводить в лог текущие p50, p99 (приблизительно через бакеты) для самоконтроля.
  2. Создать requirements.txt:
    prometheus-client==0.19.0
    numpy==1.26.0
    
  3. В Dockerfile:
    FROM python:3.10-slim
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY latency_emulator.py .
    CMD ["python", "latency_emulator.py"]
    
  4. Проверить локально без Docker: python latency_emulator.py, открыть http://localhost:8000/metrics — должны быть метрики request_duration_seconds_bucket.
  5. Собрать и запустить в compose.

Ожидаемый результат этапа
Эмулятор стабильно генерирует гистограмму с чётко различающимися p50 (~0.1 с) и p99 (~0.5-1.0 с). Ratio p99/p50 > 5.


Этап 3: Настройка Prometheus — вычисление ratio и правила алертинга (1 час)

Действия

  1. В rules.yml (Prometheus recording rules) добавить:
    groups:
      - name: latency_ratio
        interval: 15s
        rules:
          - record: job:request_duration_seconds:p50
            expr: histogram_quantile(0.50, sum(rate(request_duration_seconds_bucket[5m])) by (le))
          - record: job:request_duration_seconds:p99
            expr: histogram_quantile(0.99, sum(rate(request_duration_seconds_bucket[5m])) by (le))
          - record: job:request_duration_seconds:p99_p50_ratio
            expr: |
              (histogram_quantile(0.99, sum(rate(request_duration_seconds_bucket[5m])) by (le))
               /
               histogram_quantile(0.50, sum(rate(request_duration_seconds_bucket[5m])) by (le)))
              or vector(0)
    
  2. Добавить правило алерта:
    groups:
      - name: latency_alert
        rules:
          - alert: TailLatencyAmplification
            expr: job:request_duration_seconds:p99_p50_ratio > 5
            for: 1m
            labels:
              severity: warning
            annotations:
              summary: "Tail latency amplification detected (ratio {{ $value }})"
              description: "p99/p50 ratio > 5 (current {{ $value }}). Check system for stragglers."
    
  3. Перезапустить Prometheus (или reload через SIGHUP или /-/reload).
  4. В интерфейсе Prometheus (/rules) проверить, что правила активны.
  5. В Alerts проверить статус алерта (должен быть Pending, затем Firing через 1 минуту).

Ожидаемый результат этапа
В Prometheus доступны метрики job:request_duration_seconds:p50, :p99, :p99_p50_ratio. Алерт переходит в состояние Firing, когда ratio > 5.


Этап 4: Визуализация в Grafana (40 мин)

Действия

  1. Подключиться к Grafana (admin/admin).
  2. Добавить data source «Prometheus» с URL http://prometheus:9090.
  3. Создать дашборд «Tail Latency Amplification».
  4. Добавить панели:
    • p50 и p99 (Time series): запросы job:request_duration_seconds:p50 и :p99, легенда для каждой.
    • Ratio p99/p50 (Time series): job:request_duration_seconds:p99_p50_ratio, цвет красный при значении >5 (через thresholds).
    • Гистограмма (heatmap) на основе request_duration_seconds_bucket для визуализации хвоста.
  5. Настроить alerts в Grafana (опционально) или импортировать из Prometheus.
  6. Добавить оповещение в Telegram/email через Alertmanager (по желанию).
  7. Настроить автообновление каждые 30 секунд.

Ожидаемый результат этапа
Дашборд в Grafana отображает p50, p99, ratio. При ratio >5 панель ratio краснеет, алерт виден в Grafana.


Этап 5: Тестирование и проверка алерта (30 мин)

Действия

  1. Убедиться, что эмулятор стабильно выдаёт ratio >5.
  2. Временно изменить эмулятор, убрав хвостовые задержки (установить tail_prob = 0.0). Перезапустить контейнер.
  3. Наблюдать за ratio: он должен упасть ниже 5, алерт должен перейти в Pending, затем Resolved.
  4. Вернуть хвостовые задержки, убедиться, что алерт снова срабатывает.
  5. Проверить логи Prometheus и Alertmanager (если используется) на наличие уведомлений.

Ожидаемый результат этапа
Алерт корректно переходит между состояниями Firing и Resolved. Ratio отображается на дашборде правильно.

5. Критерии приемки (Definition of Done)

  • Эмулятор экспортирует гистограмму request_duration_seconds с корректными бакетами.
  • Prometheus успешно собирает метрики с эмулятора (нет ошибок scrape).
  • Recording rules вычисляют p50, p99, ratio (метрики присутствуют в /metrics).
  • Alert rule TailLatencyAmplification срабатывает при ratio > 5 в течение 1 минуты.
  • В Grafana настроен дашборд с тремя основными панелями.
  • При изменении поведения эмулятора (убирание хвоста) алерт разрешается в течение 2-х минут.
  • Все конфигурационные файлы (docker-compose.yml, prometheus.yml, rules.yml, latency_emulator.py) версионированы и пригодны к повторному развёртыванию.

6. Ожидаемый результат

Основной артефакт Zip-архив с файлами:

  • latency_emulator.py — эмулятор сервиса с гистограммой.
  • requirements.txt — зависимости Python.
  • Dockerfile — сборка эмулятора.
  • docker-compose.yml — оркестрация всего стека.
  • prometheus.yml — конфигурация Prometheus.
  • rules.ymlrecording и alerting правила.
  • README.md — краткое описание, команды запуска.

Содержимое README.md

  • Цель задачи.
  • Инструкция по запуску docker-compose up -d.
  • Скриншот дашборда Grafana (опционально).
  • Пример curl для проверки ratio вручную.

Дополнительные результаты

  • Понимание, как вычислять квантили из гистограмм с помощью histogram_quantile.
  • Готовый дашборд Grafana (JSON-экспорт можно приложить).

7. Возможные сложности и их решение

СложностьРешение
Гистограмма не даёт точных p50/p99 из-за малого числа бакетовДобавить больше бакетов в зоне 0.5–2.0. Использовать histogram_quantile с достаточным количеством запросов (rate по 5m).
Ratio = 0 при отсутствии данных (деление на ноль)Использовать or vector(0) в recording rule.
Правила алерта не вычисляютсяПроверить evaluation_interval и наличие ошибок в Prometheus status page.
Эмулятор не экспортирует метрики в DockerУбедиться, что порт проброшен (- "8000:8000") и target в Prometheus правильный (имя сервиса).
Алерт не переходит в FiringУвеличить for до 2m, проверить, что ratio действительно >5 непрерывно.

8. Бюджет времени (оценка)

ЭтапВремя
Этап 1: Подготовка окружения30 мин
Этап 2: Создание эмулятора1 час
Этап 3: Настройка Prometheus и алертов1 час
Этап 4: Визуализация в Grafana40 мин
Этап 5: Тестирование30 мин
Итого~4 часа

При первом выполнении возможно потребуется дополнительно 1 час на отладку и изучение инструментов. Рекомендуется закладывать 5 часов.

9. Связанные вопросы из базы знаний

ВопросТема
12PromQL: агрегация и фильтрация
45Prometheus Alertmanager: отправка уведомлений
78Grafana: создание дашбордов и панелей
123Гистограммы и квантили в Prometheus
234Измерение latency (p50, p95, p99)
345SLO/SLI на основе квантилей
456Observability: мониторинг распределённых систем
567Distributed tracing для поиска stragglers
678Tail latency amplification — причины и устранение
789Recording rules и best practices

10. Чек-лист самопроверки

  • Я написал эмулятор, который генерирует гистограмму с явным хвостом (p99 > 5 * p50).
  • Я убедился, что Prometheus собирает метрики без ошибок (/targets все UP).
  • Я проверил, что recording rule job:request_duration_seconds:p99_p50_ratio возвращает корректное значение > 5.
  • Я настроил алерт, который переходит в состояние Firing при ratio > 5 в течение 1 минуты.
  • Я добавил дашборд Grafana, на котором видно ratio, p50 и p99, и thresholds настроены.
  • Я протестировал отключение хвоста — алерт разрешается.
  • Я сохранил все конфиги в репозиторий/архив.