中文翻译暂不可用,显示俄语原文。
Настроить дашборд в Grafana для LLM
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настроить дашборд в Grafana для LLM
1. Цель задачи
Научиться проектировать и разворачивать production-ready дашборд мониторинга для LLM-сервиса (или RAG-системы). Вы научитесь собирать метрики latency, error rate и throughput из LLM-приложения, загружать их в Prometheus и визуализировать в Grafana с использованием перцентилей (p50/p95/p99), агрегированных панелей и временных фильтров.
Ключевой результат Рабочий дашборд Grafana, который отражает p50/p95/p99 latency, error rate (доля ошибок 4xx/5xx) и throughput в разрезе эндпоинтов / моделей / временных окон, готовый к демонстрации и экспорту как JSON.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| LLM-сервис (или симуляция) | Пет-проект / учебный проект / Python-скрипт, эмулирующий запросы к LLM |
| Метрики latency, ошибок, количества запросов | Prometheus exporter внутри приложения или OpenTelemetry Collector |
| Prometheus | локальный Docker-контейнер (prometheus.yml) |
| Grafana | локальный Docker-контейнер или облачная инстанция |
| Базовые знания PromQL | Документация Prometheus / шпаргалка |
| Инструмент для нагрузки (опционально) | locust, vegeta или простой time + curl |
Если нет реального LLM-сервиса — симулируем:
- Напишите простой FastAPI-сервер на Python с одним эндпоинтом
/v1/chat/completions, который:- принимает POST-запрос с JSON
{"prompt": "..."} - имитирует работу LLM (задержка от 200 до 2000 мс через
time.sleep(random.uniform(0.2, 2.0))) - генерирует ответ
{"response": "...", "model": "gpt-4o-mini"} - случайно возвращает ошибки 500 с вероятностью 1-5%
- принимает POST-запрос с JSON
- Встройте в приложение Prometheus-клиент (
prometheus_client) и экспортируйте метрики: - Запустите нагрузочный тест (например, 10 параллельных запросов в течение 3 минут) с помощью Python-скрипта или
ab.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| LLM-приложение (цель мониторинга) | FastAPI / Flask + prometheus_client | Генерация метрик |
| Сбор метрик | Prometheus (pull-модель) | Хранение временных рядов |
| Визуализация | Grafana (v10+) | Дашборды и алерты |
| Нагрузочное тестирование | Python-скрипт / locust / vegeta | Генерация трафика |
| Контейнеризация (опционально) | Docker + docker-compose | Упрощение развёртывания |
| Метрики latency | Histogram метрики Prometheus | p50/p95/p99 |
| Метрики ошибок | Counter или Gauge по статусам | Error rate |
| Throughput | Rate от Counter | Requests per second |
4. Этапы выполнения
Этап 1: Подготовка окружения и симуляция LLM-сервиса (оценка времени: 1 час)
Действия
-
Создайте файл
llm_service.pyс FastAPI-приложением, экспортирующим Prometheus-метрики:from fastapi import FastAPI from prometheus_client import Histogram, Counter, generate_latest from starlette.responses import Response import random, time, asyncio app = FastAPI() REQUEST_DURATION = Histogram( 'llm_request_duration_seconds', 'Duration of LLM requests', buckets=(0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 10.0) ) REQUESTS_TOTAL = Counter( 'llm_requests_total', 'Total LLM requests', ['status', 'model'] ) @app.get('/metrics') async def metrics(): return Response(content=generate_latest(), media_type='text/plain') @app.post('/v1/chat/completions') async def chat(body: dict): model = body.get('model', 'default') delay = random.uniform(0.2, 2.0) await asyncio.sleep(delay) status = 'success' if random.random() > 0.03 else 'error' if status == 'error': REQUESTS_TOTAL.labels(status='500', model=model).inc() return Response(status_code=500, content='{"error":"internal"}') REQUESTS_TOTAL.labels(status='200', model=model).inc() REQUEST_DURATION.observe(delay) return {"response": f"Simulated response for: {body.get('prompt','')}", "model": model} -
Настройте
prometheus.ymlдля сбора метрик каждые 5 секунд:global: scrape_interval: 5s scrape_configs: - job_name: 'llm_service' static_configs: - targets: ['host.docker.internal:8000'] -
Соберите
docker-compose.ymlс сервисами:llm_service(сборка из Dockerfile или прямо из образа Python)prometheus(image: prom/prometheus, монтирование prometheus.yml)grafana(image: grafana/grafana, порт 3000)
-
Запустите окружение:
docker-compose up -d
Ожидаемый результат этапа
Приложение отвечает на POST-запросы, метрики доступны по http://localhost:8000/metrics, Prometheus видит цель (Status UP).
Этап 2: Генерация нагрузки и накопление данных (оценка времени: 30 минут)
Действия
-
Напишите скрипт
load_test.py, который в течение 5-10 минут отправляет запросы к LLM-сервису с разными промптами и моделями (model1, model2):import requests, time, threading, random def worker(): while True: try: model = random.choice(['gpt-4o-mini', 'claude-3-haiku']) resp = requests.post('http://localhost:8000/v1/chat/completions', json={'prompt':'hello', 'model':model}, timeout=10) except Exception: pass time.sleep(random.uniform(0.1, 0.5)) threads = [threading.Thread(target=worker) for _ in range(10)] for t in threads: t.start() time.sleep(600) # 10 минут нагрузки -
Запустите нагрузку:
python load_test.py -
Проверьте, что Prometheus накопил данные:
- Откройте
http://localhost:9090→ выполните запрос:rate(llm_requests_total[1m]) - Должен появиться график.
- Откройте
Ожидаемый результат этапа
В Prometheus есть временные ряды llm_request_duration_seconds_bucket, llm_requests_total с минимум 100 точками.
Этап 3: Создание дашборда в Grafana (оценка времени: 1.5 часа)
Действия
-
Подключите Prometheus как источник данных в Grafana:
- URL:
http://prometheus:9090 - Тип: Prometheus
- Название:
Prometheus
- URL:
-
Создайте новый дашборд с названием «LLM Service Monitoring».
-
Добавьте панель «Latency (p50 / p95 / p99)» (Time series, Query A/B/C):
- p50:
histogram_quantile(0.50, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le)) - p95:
histogram_quantile(0.95, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le)) - p99:
histogram_quantile(0.99, sum(rate(llm_request_duration_seconds_bucket[5m])) by (le)) - Настройте оси: Unit = seconds, Decimals = 3, Legend =
p50,p95,p99. - Добавьте threshold: красная линия на 2 секунды как warning.
- p50:
-
Добавьте панель «Error Rate» (Stat или Time series):
- Query:
sum(rate(llm_requests_total{status="500"}[5m])) / sum(rate(llm_requests_total[5m])) * 100 - Unit = percent (0-100), Decimals = 2.
- Color: green if < 1, yellow if < 5, red otherwise.
- Query:
-
Добавьте панель «Throughput (RPS)» (Time series):
-
Добавьте панель «Requests by Model» (Bar gauge или Pie chart):
- Query:
sum by (model) (rate(llm_requests_total[5m])) - Legend:
{{model}}.
- Query:
-
Настройте переменные дашборда (Dashboard variables):
$model:label_values(llm_requests_total, model)→ позволяет фильтровать по модели.$interval: интервал сглаживания (например,$__auto_interval_2m).
-
Примените фильтры к панелям – добавьте
model=~"$model"в запросы. -
Сохраните дашборд и экспортируйте как JSON (меню Share → Export → Save to file).
Ожидаемый результат этапа
Дашборд отображает четыре панели, данные обновляются каждые 5 секунд, фильтр по модели работает.
Этап 4: Настройка алертов (опционально, оценка времени: 30 минут)
Действия
Ожидаемый результат этапа
Алерты активны, при превышении порога меняется цвет панели и отправляется уведомление (если настроено).
Этап 5: Документирование дашборда (оценка времени: 30 минут)
Действия
-
Создайте файл
README.mdс описанием дашборда:- Цель мониторинга.
- Перечень панелей и PromQL-запросов.
- Как обновить переменные.
- Инструкция по развёртыванию.
-
Приложите экспортированный JSON дашборда (например,
llm_dashboard.json).
Ожидаемый результат этапа
Git-репозиторий (или папка) содержит код симуляции, дашборд и документацию.
5. Критерии приемки (Definition of Done)
- Дашборд содержит минимум 4 панели: latency (p50/p95/p99), error rate, throughput, распределение по моделям.
- Все панели работают с реальными данными из Prometheus (не пустые графики).
- Настроена хотя бы одна переменная дашборда (например, фильтр по модели).
- Latency отображается в секундах с точностью до миллисекунд.
- Error rate отображается в процентах с порогами раскраски.
- Дашборд экспортирован как JSON-файл и включён в репозиторий.
- Написана краткая документация (README) с описанием панелей и способом запуска.
- (бонус) Настроен хотя бы один алерт на p99 latency > 2s.
6. Ожидаемый результат
Основной артефакт
Файл llm_dashboard.json (экспорт дашборда Grafana) и файл README.md с инструкциями.
Содержание дашборда
- Latency Panel (time series): три линии p50, p95, p99.
- Error Rate Panel (stat): одно число с окраской.
- Throughput Panel (time series): RPS.
- Requests by Model Panel (bar gauge или table): распределение запросов.
- Переменная
$modelсо значениями из метрик.
Дополнительно (опционально):
- Docker-compose файл для воспроизведения окружения.
- Скрипт нагрузки
load_test.py. - Алерты в JSON (если настроены).
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Prometheus не видит цель (target down) | Проверьте docker-compose networking: используйте host.docker.internal или общую сеть, убедитесь, что порт 8000 открыт. |
| Histogram метрики не показывают перцентили | Убедитесь, что _bucket создаются (buckets заданы). Используйте histogram_quantile с правильным le. |
| Графики пустые из-за отсутствия нагрузки | Запустите нагрузочный скрипт дольше (минимум 5 минут), убедитесь, что rate[5m] не слишком большой. |
| Grafana не подключается к Prometheus | Проверьте URL источника данных – внутри Docker используйте имя сервиса http://prometheus:9090. |
Переменная $model не подхватывается | Используйте label_values(llm_requests_total, model) и убедитесь, что метрики имеют лейбл model. |
| Медленное обновление дашборда | Уменьшите scrape_interval в Prometheus до 5-10 секунд. |
8. Бюджет времени (оценка)
| Этап | Время |
|---|---|
| Этап 1: Подготовка окружения и симуляция | 1 ч |
| Этап 2: Генерация нагрузки | 30 мин (активно), 10 мин ожидания |
| Этап 3: Создание дашборда | 1.5 ч |
| Этап 4: Настройка алертов (опционально) | 30 мин |
| Этап 5: Документирование | 30 мин |
| Итого | ~4-5 часов |
Примечание Для первого выполнения увеличьте бюджет на 1–2 часа из-за возможных затруднений с Docker и PromQL.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 42 | Как настроить Prometheus для сбора метрик из Python-приложения? |
| 87 | Как рассчитать p95 latency с использованием Histogram в Prometheus? |
| 131 | Какие панели Grafana лучше всего подходят для мониторинга производительности API? |
| 205 | Как вычислить error rate (SLO/SLI) с помощью PromQL? |
| 244 | Как настроить переменные дашборда Grafana с фильтрацией по лейблам? |
| 310 | Как симулировать нагрузку на LLM-сервис для тестирования мониторинга? |
| 412 | Как экспортировать и импортировать дашборды Grafana через JSON? |
| 527 | Как настроить алерты на основе p99 latency в Grafana? |
| 638 | В чём разница между rate и irate в PromQL при расчёте throughput? |
| 789 | Как интерпретировать heatmap latency в Grafana? |
10. Чек-лист самопроверки
- Я запустил docker-compose, и сервис LLM отвечает на запросы.
- Я убедился, что метрики доступны в Prometheus (
/targets→ UP). - Я сгенерировал нагрузку и дождался накопления данных (минимум 5 минут).
- Я создал дашборд с нужными панелями (latency, error rate, throughput).
- Я проверил, что фильтр по модели работает и меняет данные на панелях.
- Я экспортировал дашборд как JSON и положил в репозиторий.
- Я написал README с описанием дашборда и инструкцией по развёртыванию.
- (опционально) Я настроил алерт и проверил его срабатывание при превышении порога.