Пара 20: Prometheus: сбор метрик и PromQL

90 минут · 3 курс, ML.

Содержание и результат

Поднять Prometheus, проверить target и построить rate и p95 из метрик StudyPulse.

План занятия

0–10: контекст и исходная задача. 10–40: устройство и механизмы. 40–55: демонстрация команд. 55–80: лабораторная работа. 80–90: разбор результата и фиксация исправлений.

Практика выполняется в своей учебной папке и на localhost. Подготовка окружения описана в lab/README.md.

Pull и временные ряды

Prometheus периодически читает endpoint метрик.

Приложение предоставляет /metrics в формате экспозиции. Prometheus по расписанию делает scrape и сохраняет samples с именем метрики, labels и временем. up показывает успешность scrape, но up=1 ещё не означает правильный predict. Targets помогают отличить ошибку сбора от отсутствия пользовательского трафика. В учебном compose target app:8000 доступен по внутренней сети; Prometheus UI публикуется только на localhost:9090. Интервал 5 секунд удобен для демонстрации, а не универсальная настройка production. Первые rate-запросы требуют нескольких наблюдений.

Аналогия: дежурный регулярно переписывает показания счётчика.

Counter, gauge, histogram

Тип метрики определяет корректную операцию.

Counter накапливает события и сбрасывается при рестарте; rate считает скорость с учётом сбросов. Gauge показывает текущее значение, например активные запросы. Histogram распределяет длительности по накопительным bucket и хранит count/sum. Для средней длительности делим rate(sum) на rate(count); для p95 используем histogram_quantile с rate bucket. p95 — оценка границы, ниже которой находится около 95% наблюдений, а не максимальное время. При малом числе событий оценка нестабильна. Наш текстовый histogram учебный и потокобезопасный, в рабочем проекте обычно берут официальный client.

Аналогия: одометр, спидометр и распределение длительностей поездок.

Labels и кардинальность

Каждая уникальная комбинация labels создаёт отдельный ряд.

route=/predict и status=200 имеют ограниченное множество значений. request_id, email и произвольный URL в label создают огромное число рядов и могут раскрыть данные. В учебном приложении неизвестные пути нормализуются в route=other. Request ID оставляем в логе, не в метриках. Это не косметическое правило: число рядов влияет на память, хранение и скорость запросов. Не добавляйте label только потому, что поле существует в запросе.

Аналогия: отдельная папка на каждую категорию удобна, на каждую песчинку — нет.

Команды и наблюдения

Окружение: Ubuntu / Bash, lab; PromQL в UI :9090.

docker compose -f compose.yaml -f compose.monitoring.yaml up -d
python3 scripts/load.py --requests 60 --concurrency 3
# PromQL expressions
up{job="studypulse"}
sum(rate(studypulse_http_requests_total{route="/predict"}[1m]))
histogram_quantile(0.95, sum by (le) (rate(studypulse_request_duration_seconds_bucket{route="/predict"}[1m])))

Команды PromQL вводятся в интерфейсе Prometheus, не в Bash. Трафик ограничен своим localhost.

Ожидаемый результат: Target UP; rate появляется после нескольких scrape; p95 возвращается при наличии достаточных наблюдений.

Вариант для macOS

Prometheus и PromQL одинаковы в контейнерном варианте. Если нужный учебный image не поддерживает архитектуру, проверьте manifest и используйте согласованную платформу/VM, а не случайную подмену версии.

docker compose -f compose.yaml -f compose.monitoring.yaml up -d
python3 scripts/load.py --requests 60 --concurrency 3

Практика: Из счётчика в график

  1. Откройте Targets и проверьте app:8000.
  2. Выполните ограниченную нагрузку; подождите 15–30 секунд.
  3. Сравните значение counter, rate и p95 в PromQL.
  4. Перезапустите app и объясните сброс счётчика без объявления отрицательной скорости.

Результат: Три запроса PromQL с интерпретацией, а не только скриншоты.

Проверка: Единицы подписаны; request_id отсутствует в labels; up не подменяет smoke-test.

Неисправность для разбора: Выражение rate без данных воспринимают как ошибку приложения.

Решение и диагностика

Проверьте target, затем сырой /metrics, затем окно времени. После рестарта rate учитывает reset, но короткое окно и редкий трафик дадут нестабильный график. Для p95 сохраняется label le: sum by (le)(rate(...bucket[1m])). Ошибки сервера: sum(rate(studypulse_http_requests_total{route="/predict",status=~"5.."}[1m])) / sum(rate(studypulse_http_requests_total{route="/predict"}[1m])). При нулевом трафике отношение не имеет информативного значения.

Основные выводы

Самостоятельная работа

Подготовить два PromQL-запроса и объяснить их единицы и условия интерпретации.

Источники