Python dataclasses vs attrs vs Pydantic: когда какой инструмент выбрать
Дашборд в Grafana — это не набор красивых графиков, а инструмент для быстрого ответа на вопрос «что сломалось и где». В микросервисной архитектуре с десятками сервисов правильная структура дашбордов критична: без неё вы утонете в метриках. Разберём принципы проектирования, PromQL-паттерны и построим дашборд для HTTP-сервиса.
Принципы: USE, RED и golden signals
Два фреймворка для выбора метрик:
RED (для сервисов — request-driven):
- Rate — количество запросов в секунду.
- Errors — процент ошибок (5xx).
- Duration — latency (p50, p95, p99).
USE (для ресурсов — CPU, память, диск):
- Utilization — процент использования.
- Saturation — очередь/перегрузка.
- Errors — ошибки ресурса.
Для каждого микросервиса на overview-дашборде показываем RED-метрики. Для инфраструктуры (ноды, БД, очереди) — USE. Это даёт мгновенный ответ: «сервис X отвечает медленно» или «нода Y перегружена по CPU».
Структура: overview → service → instance
Трёхуровневая иерархия дашбордов:
- Overview — все сервисы на одном экране: RPS, error rate, p99 latency. Цель — за 5 секунд найти проблемный сервис.
- Service — детали одного сервиса: разбивка по эндпоинтам, коды ответов, ресурсы подов.
- Instance — конкретный pod/инстанс: CPU, memory, GC, connections.
Переход между уровнями — через data links в Grafana: клик на сервис в overview открывает service-дашборд с предзаполненными переменными.
PromQL паттерны
Request rate (RPS):
sum(rate(http_requests_total{namespace="$namespace", service="$service"}[5m])) by (service)
Error rate (%):
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/
sum(rate(http_requests_total[5m])) by (service)
* 100
Latency percentiles (histogram):
# p99 latency
histogram_quantile(0.99,
sum(rate(http_request_duration_seconds_bucket{service="$service"}[5m])) by (le)
)
# p95 latency
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{service="$service"}[5m])) by (le)
)
Saturation (CPU throttling):
sum(rate(container_cpu_cfs_throttled_periods_total{pod=~"$service.*"}[5m]))
/
sum(rate(container_cpu_cfs_periods_total{pod=~"$service.*"}[5m]))
Memory usage vs limit:
container_memory_working_set_bytes{pod=~"$service.*"}
/
container_spec_memory_limit_bytes{pod=~"$service.*"}
* 100
Важно: всегда используйте rate() для counters и [5m] как минимальное окно (2× scrape interval). Для мгновенных значений (gauges) — без rate.
Переменные: интерактивность дашборда
Переменные превращают статичный дашборд в интерактивный инструмент:
# Переменная $namespace — список namespace из метрик
label_values(http_requests_total, namespace)
# Переменная $service — сервисы в выбранном namespace
label_values(http_requests_total{namespace="$namespace"}, service)
# Переменная $instance — поды выбранного сервиса
label_values(http_requests_total{namespace="$namespace", service="$service"}, pod)
Настройки переменных в JSON-модели дашборда:
{
"templating": {
"list": [
{
"name": "namespace",
"type": "query",
"query": "label_values(http_requests_total, namespace)",
"refresh": 2,
"multi": false
},
{
"name": "service",
"type": "query",
"query": "label_values(http_requests_total{namespace=\"$namespace\"}, service)",
"refresh": 2,
"multi": true,
"includeAll": true
}
]
}
}
Рекомендации: refresh: 2 (on time range change), multi: true для service (сравнение нескольких сервисов на одном графике), каскадная зависимость namespace → service → instance.
Алерты: Grafana alerting vs Alertmanager
Grafana Alerting (unified alerting с v9+) — алерты прямо в дашборде:
- Правила на основе PromQL-запросов.
- Routing через contact points (Slack, PagerDuty, email).
- Silence и mute timings из UI.
Alertmanager (отдельный компонент Prometheus-стека):
- Правила в PrometheusRule CRD.
- Группировка, дедупликация, routing tree.
- Лучше для больших команд с разными on-call ротациями.
Практический совет: для команды до 10 человек Grafana Alerting проще. Для enterprise с десятками команд и сложным routing — Alertmanager.
Пример алерта на высокий error rate:
# PrometheusRule для Alertmanager
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: api-alerts
spec:
groups:
- name: api.rules
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m])) by (service)
/ sum(rate(http_requests_total[5m])) by (service)
> 0.05
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.service }}"
description: "Error rate is {{ $value | humanizePercentage }}"
Практика: дашборд для HTTP-сервиса
Минимальный набор панелей для service-level дашборда:
┌─────────────────────────────────────────────────────────┐
│ Row 1: Overview (stat panels) │
│ [RPS: 1.2k] [Error%: 0.3%] [p99: 45ms] [Pods: 5/5] │
├─────────────────────────────────────────────────────────┤
│ Row 2: Traffic │
│ [RPS by endpoint - timeseries] [Status codes - stacked]│
├─────────────────────────────────────────────────────────┤
│ Row 3: Latency │
│ [p50/p95/p99 - timeseries] [Latency heatmap] │
├─────────────────────────────────────────────────────────┤
│ Row 4: Resources │
│ [CPU usage vs limit] [Memory usage vs limit] │
├─────────────────────────────────────────────────────────┤
│ Row 5: Saturation │
│ [CPU throttling %] [Connection pool usage] │
└─────────────────────────────────────────────────────────┘
Stat-панели сверху дают мгновенный ответ: всё ли в норме. Timeseries ниже — для анализа трендов. Heatmap для latency показывает распределение, а не только percentiles.
Вывод
Хороший дашборд отвечает на вопрос за 5 секунд, а не создаёт новые. Используйте RED для сервисов, USE для ресурсов. Стройте трёхуровневую иерархию с drill-down через переменные. Не перегружайте overview — максимум 3–4 метрики на сервис. И помните: дашборд без алертов — это картинка, на которую никто не смотрит, пока не станет поздно.