中文翻译暂不可用,显示俄语原文。

Настроить RED metrics для LLM

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить RED metrics для LLM

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

Освоить практику мониторинга production-сервисов на LLM по методологии RED (Rate, Errors, Duration) для каждого эндпоинта. Реализовать инструментирование LLM-приложения, сбор метрик в Prometheus и визуализацию в Grafana с дашбордом, позволяющим быстро оценить здоровье сервиса.

Ключевой результат Рабочий дашборд Grafana с панелями Rate, Error Rate и Latency (p50, p95, p99) для двух эндпоинтов LLM сервиса, с настроенными оповещениями (alerts) при превышении порогов.

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

Что нужноОткуда взять
LLM сервис (минимальный – два эндпоинта, например, /v1/chat и /v1/embed)Реальный или смоделированный
Docker и Docker ComposeУстановить или проверить версию
Python 3.10+ с библиотекамиpip install flask prometheus_client
PrometheusОбраз prom/prometheus (docker)
GrafanaОбраз grafana/grafana (docker)

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

  1. Создать файл llm_sim.py с Flask-приложением, которое эмулирует два эндпоинта:
    • /v1/chat – случайная задержка от 0.1 до 2.0 сек, с вероятностью 5% ошибки (HTTP 500).
    • /v1/embed – случайная задержка от 0.05 до 0.5 сек, без ошибок.
  2. Инструментировать эндпоинты метриками RED с помощью библиотеки prometheus_client.
  3. Добавить генератор трафика (например, отдельный скрипт или Apache Bench) для постоянной нагрузки.
# llm_sim.py (фрагмент)
from flask import Flask, jsonify
from prometheus_client import Counter, Histogram, generate_latest
import random, time

app = Flask(__name__)

# Метрики RED
REQUEST_COUNT = Counter('llm_requests_total', 'Total request count', ['endpoint', 'status'])
REQUEST_LATENCY = Histogram('llm_request_duration_seconds', 'Request latency', ['endpoint'],
                            buckets=(0.1, 0.5, 1.0, 2.0, 5.0, 10.0))

@app.route('/v1/chat', methods=['POST'])
def chat():
    start = time.time()
    if random.random() < 0.05:  # 5% ошибок
        REQUEST_COUNT.labels(endpoint='/v1/chat', status='error').inc()
        return jsonify({'error': 'simulated failure'}), 500
    time.sleep(random.uniform(0.1, 2.0))
    REQUEST_COUNT.labels(endpoint='/v1/chat', status='success').inc()
    REQUEST_LATENCY.labels(endpoint='/v1/chat').observe(time.time() - start)
    return jsonify({'response': 'ok'})

@app.route('/v1/embed', methods=['POST'])
def embed():
    start = time.time()
    time.sleep(random.uniform(0.05, 0.5))
    REQUEST_COUNT.labels(endpoint='/v1/embed', status='success').inc()
    REQUEST_LATENCY.labels(endpoint='/v1/embed').observe(time.time() - start)
    return jsonify({'response': 'ok'})

@app.route('/metrics')
def metrics():
    return generate_latest()

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

КомпонентИнструментыНазначение
LLM сервис (симуляция)Python Flask / FastAPI + prometheus_clientЭмуляция API, экспорт метрик
Система метрикPrometheus (pull-based)Сбор и хранение метрик
ВизуализацияGrafanaДашборд, алертинг
КонтейнеризацияDocker, Docker ComposeОркестрация компонентов
Генерация нагрузкиPython-скрипт (requests) или Apache BenchСоздание трафика для теста

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

Этап 1: Настройка локальной инфраструктуры (30-45 минут)

Действия

  1. Создать структуру проекта

    • docker-compose.yml
    • prometheus/prometheus.yml
    • llm_sim.py (код из п.2)
    • generator.py (простой скрипт для имитации пользователей)
    • grafana/datasources.yml (добавить Prometheus как datasource)
  2. Docker Compose конфигурация (основные сервисы):

  3. prometheus.yml – конфигурация scrape:

    global:
      scrape_interval: 5s
    scrape_configs:
      - job_name: 'llm_service'
        static_configs:
          - targets: ['llm_sim:8000']
    
  4. Сделать docker-compose up -d, проверить логи, что все сервисы запущены.

Ожидаемый результат этапа Все три контейнера (llm_sim, prometheus, grafana) работают. Grafana доступна на порту 3000, Prometheus на 9090, API llm_sim на 8000.

Этап 2: Инструментирование метрик RED (1-1.5 часа)

Действия

  1. Добавить в код сервиса три типа метрик для каждого эндпоинта:

    • RateCounter с метками endpoint и status (success/error).
    • Errors – та же Counter, но фильтровать только status='error'.
    • Duration – Histogram с меткой endpoint и подходящими бакетами (например, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0).
  2. Обернуть каждый эндпоинт в middleware (или декоратор), который:

    • Замеряет время выполнения.
    • Увеличивает счётчик с успешным/ошибочным статусом.
    • Записывает latency в Histogram.
  3. Экспортировать метрики на /metrics с помощью prometheus_client.generate_latest().

  4. Проверить метрики через curl localhost:8000/metrics. Убедиться, что присутствуют llm_requests_total и llm_request_duration_seconds.

  5. Написать скрипт-генератор generator.py, который в цикле отправляет POST-запросы на оба эндпоинта (по 50% трафика) с паузой 0.1-0.5 сек.

Ожидаемый результат этапа При запущенном генераторе метрики обновляются; в Prometheus (UI) можно увидеть target UP и получаемые метрики.

Этап 3: Создание дашборда Grafana с RED панелями (1.5-2 часа)

Действия

  1. Создать дашборд в Grafana (UI или provisioning).

    • Рекомендуется provisioning через YAML (папка grafana/dashboards), чтобы дашборд воспроизводился.
  2. Добавить панели (Panels) для каждого измерения RED:

    • Rate – запросов в секунду (за минуту). Graph с линиями для каждого эндпоинта (сумма success+error). Использовать запрос: rate(llm_requests_total[1m]) с legend {{endpoint}}.

    • Error Rate – процент ошибок. Использовать две линии: ошибки/сек и общий rate, а также можно вывести процент через формулу: rate(llm_requests_total{status="error"}[1m]) / rate(llm_requests_total[1m]) * 100. Легенда: Error % {{endpoint}}.

    • Duration – p50/p95/p99 latency. Для каждого эндпоинта отдельная панель (или одна с несколькими линиями). Использовать histogram_quantile: histogram_quantile(0.5, sum(rate(llm_request_duration_seconds_bucket{endpoint="/v1/chat"}[5m])) by (le)) и т.д.

  3. Настроить оповещения (alerts): (опционально, но желательно)

    • Если error rate > 10% в течение 2 минут → отправка (пока только Grafana-уведомление, без реального канала).
    • Если p95 latency > 3 сек → предупреждение.
  4. Добавить Time picker и описания панелей.

  5. Экспортировать дашборд в JSON и сохранить в grafana/dashboards/red_dashboard.json.

Ожидаемый результат этапа Дашборд с 3-4 панелями, обновляющимися в реальном времени. Видны динамика rate, латенси и ошибок.

Этап 4: Тестирование, анализ и документирование (30-45 минут)

Действия

  1. Провести стресс-тест – увеличить нагрузку генератором (уменьшить паузу до 0.01 сек), проверить, как меняются метрики на дашборде.
  2. Симулировать сбой – временно ввести time.sleep(10) на эндпоинте, убедиться, что latency взлетает, графики показывают аномалию.
  3. Проверить работу alerting при превышении порога должно появиться оповещение в Grafana (раздел Alerting).
  4. Написать короткий README с описанием архитектуры, как запустить, где смотреть дашборд.

Ожидаемый результат этапа Дашборд корректно отражает изменения нагрузки и сбои. Настроены alerts.

Этап 5: (Опционально) Интеграция с существующим LLM сервисом (1-2 часа)

Если есть доступ к реальному LLM сервису (например, на базе vLLM, Triton Inference Server), необходимо инструментировать его аналогично. Для production решений часто используют OpenTelemetryPrometheus. В рамках задачи можно показать, как заменить симуляцию на реальный сервер.

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

  • Дашборд Grafana содержит минимум три панели: Request Rate (запросов/сек), Error Rate (% или absolute), Latency (p50, p95, p99).
  • Метрики собираются для каждого из двух эндпоинтов раздельно.
  • Дашборд автообновляется (refresh interval ≤ 15 сек).
  • Источник данных Prometheus настроен и подключён без ошибок.
  • При запуске генератора метрики визуально растут, при остановке – падают до 0.
  • Настроено как минимум одно alert-правило (например, на высокий error rate).
  • Весь код и конфигурация находятся в репозитории (или папке) с README, воспроизводимы через docker-compose up.
  • Скрипт генератора запускается отдельно и даёт стабильную нагрузку.

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

Файлы/артефакты в корне проекта:

АртефактСодержание
docker-compose.ymlТри сервиса: llm_sim, prometheus, grafana
llm_sim.pyFlask-приложение с RED метриками, порт 8000
prometheus/prometheus.ymlКонфиг Prometheus, scrape job на llm_sim:8000
grafana/datasources/datasource.ymlProvisioning datasource Prometheus
grafana/dashboards/red_dashboard.jsonЭкспортированный дашборд RED (3-4 панели)
generator.pyСкрипт постоянной нагрузки
README.mdИнструкция по запуску, описание метрик и панелей

Дополнительные результаты (опционально):

  • Скриншот дашборда с пиками нагрузки и ошибками.
  • Документация по алертингу (какие пороги установлены и почему).

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

СложностьРешение
Metrica latency не появляется в PrometheusУбедиться, что при вызове эндпоинта Histogram.observe() вызывается. Проверить, что метрики доступны по /metrics.
Дашборд не отображает данныеПроверить datasource в Grafana (название должно совпадать с provisioning). Проверить Prometheus target UP.
Generator слишком быстро сжирает ресурсыУменьшить количество потоков, добавить time.sleep(0.1)
Docker контейнеры не общаютсяИспользовать сеть -net bridge в docker-compose; обращаться по имени сервиса (llm_sim, prometheus, grafana).
Alert rule не срабатываетПроверить таймфрейм (for: 2m), правильный PromQL. Убедиться, что алерт active и настроен evaluation interval.
Histogram buckets не соответствуют распределениюВ production выбирать buckets в 4-5 раз выше ожидаемой медианной задержки. Для симуляции оставить дефолтные.

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

ЭтапВремя (часов)
Этап 1: Настройка инфраструктуры0.5 – 0.75
Этап 2: Инструментирование метрик1.0 – 1.5
Этап 3: Создание дашборда Grafana1.5 – 2.0
Этап 4: Тестирование и документирование0.5 – 0.75
Этап 5 (опционально): Реальный сервис+1.0 – 2.0
Итого (основные 4 этапа)3.5 – 5.0 часов

Примечание для первого раза Если не знакомы с Prometheus и Grafana, добавьте 1-2 часа на ознакомление. Симуляция упрощает работу, поэтому реальный сервис может потребовать дополнительного времени.

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

ВопросТема
10Основы Prometheus: метрики, label, экспортеры
42Написание PromQL запросов для rate и histogram_quantile
105Конфигурация docker-compose для multi-service приложения
203Инструментирование Python-сервиса prometheus_client
311Создание дашборда в Grafana через provisioning
428Настройка alert rules в Grafana
550Наблюдаемость LLM сервисов: метрики, логи, трейсинг
612RED методология: Rate, Errors, Duration
707Использование histogram_quantile для перцентилей
834Best practices по buckets для latency метрик

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

  • Я проверил, что метрики /metrics отдают правильные данные для обоих эндпоинтов.
  • Prometheus успешно забирает метрики (target state = UP).
  • В дашборде отображаются графики для Rate, Error Rate и Latency.
  • Alert правила настроены и переходят в состояние Firing при создании искусственных ошибок.
  • README содержит команды для быстрого развертывания (docker-compose up --build).
  • Код не содержит закомментированных блоков или токенов.
  • Я протестировал остановку генератора: метрики должны вернуться к нулю через ~2 scrape интервала.
  • Все конфигурационные файлы (prometheus.yml, datasource, dashboard) лежат в соответствующих папках проекта.