Настройка кастомных дашбордов мониторинга инфраструктуры (Grafana)
Grafana-дашборды — это визуальный язык состояния инфраструктуры. Дефолтные дашборды из community часто перегружены ненужными панелями и не отвечают на конкретные вопросы вашего сервиса. Кастомный дашборд строится от вопросов, которые задаёт команда, а не от доступных метрик.
Принципы построения эффективного дашборда
Иерархия информации. Верхняя строка — самое важное: сервис работает или нет. Детализация — ниже. Не заставлять глаза искать статус.
Actionable метрики. Каждая панель отвечает на вопрос, который влияет на решение. «CPU 67%» — не actionable. «CPU 67%, target 60%, trending up, 3 инстанса масштабируются» — actionable.
Временные переменные. $__timeRange и $__interval позволяют менять период просмотра и сохранять разрешение графиков.
Структура дашборда для веб-приложения
Row 1: Service Health (большие stat panels)
[Error Rate %] [P95 Latency ms] [Uptime %] [Active Users]
Row 2: Traffic & Performance
[RPS - время] [Response time P50/P95/P99 - время] [HTTP status breakdown]
Row 3: Infrastructure
[CPU % per host] [Memory % per host] [Disk I/O] [Network I/O]
Row 4: Database
[DB Connections active/max] [Query latency P95] [Slow queries count]
Row 5: Cache
[Redis hit rate %] [Redis memory usage] [Evictions per sec]
Prometheus запросы для ключевых панелей
Error Rate:
sum(rate(http_requests_total{status=~"5..", job="app"}[5m]))
/
sum(rate(http_requests_total{job="app"}[5m]))
* 100
P95 Latency:
histogram_quantile(0.95,
sum(rate(http_request_duration_seconds_bucket{job="app"}[5m])) by (le)
)
Active DB Connections:
pg_stat_activity_count{datname="mydb", state="active"}
Redis Hit Rate:
rate(redis_keyspace_hits_total[5m])
/
(rate(redis_keyspace_hits_total[5m]) + rate(redis_keyspace_misses_total[5m]))
* 100
Переменные дашборда
Переменные делают дашборд универсальным:
{
"templating": {
"list": [
{
"name": "environment",
"type": "custom",
"options": [
{"text": "production", "value": "production"},
{"text": "staging", "value": "staging"}
]
},
{
"name": "instance",
"type": "query",
"query": "label_values(up{job='app', env='$environment'}, instance)"
}
]
}
}
Использование в запросах: {job="app", env="$environment", instance="$instance"}.
Аннотации деплоев
Вертикальная линия на графиках при каждом деплое — быстро видно корреляцию между деплоем и деградацией:
# CI/CD: отправить аннотацию после деплоя
import requests
def create_grafana_annotation(grafana_url: str, api_key: str, text: str, tags: list):
requests.post(
f"{grafana_url}/api/annotations",
headers={"Authorization": f"Bearer {api_key}"},
json={
"text": text,
"tags": tags,
"time": int(time.time() * 1000) # milliseconds
}
)
# В CI/CD pipeline после успешного деплоя:
create_grafana_annotation(
GRAFANA_URL, API_KEY,
text=f"Deploy v{VERSION} to production",
tags=["deploy", "production"]
)
Dashboard as Code (Grafonnet / Terraform)
Хранить дашборды в git, а не только в UI:
// Grafonnet: dashboard as code
local grafana = import 'grafonnet/grafana.libsonnet';
local dashboard = grafana.dashboard;
local graphPanel = grafana.graphPanel;
dashboard.new(
'Application Overview',
time_from='now-1h',
refresh='30s',
)
.addPanel(
graphPanel.new(
'Error Rate',
datasource='Prometheus',
)
.addTarget(
grafana.prometheus.target(
'sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) * 100',
legendFormat='Error Rate %'
)
),
gridPos={ x: 0, y: 0, w: 12, h: 8 }
)
Или через Terraform Grafana provider: resource "grafana_dashboard" "app".
Sharing и доступ
- Read-only публичный URL — для статус-панели в офисе
- Snapshot — поделиться текущим состоянием с кем-то без доступа к Grafana
- Embedded панели — встроить в внутренний портал команды
Сроки создания
- Базовые панели (error rate, latency, traffic) — 1-2 дня
- Полный дашборд приложения (все слои) — 3-5 дней
- Dashboard as code + git workflow — 1-2 дня
- Аннотации деплоев — 1 день







