Dashboards de Grafana para Observabilidad con Prometheus
Construye dashboards de Grafana que visualizan métricas de Prometheus. Usá paneles, variables de template, provisioning y alertas para observabilidad del equipo.
Descripción General
Los dashboards de Grafana transforman métricas crudas de Prometheus en una vista en vivo de la salud de los servicios. Esta receta muestra cómo conectar un data source, construir un dashboard con paneles y variables, provisionarlo desde disco y agregar alertas. Los ejemplos usan snippets de YAML, JSON, PromQL y Terraform que podés adaptar a tu propio stack. Recomiendo este enfoque porque lo usé en producción durante años.
Si ya estás recolectando métricas con Prometheus, Grafana es la capa de visualización que se pone encima. No almacena métricas por sí mismo; consulta a Prometheus (o a Loki para logs) y las renderiza como paneles, gráficos y tiles de stat. Pensalo como el front-end de tu stack de observabilidad. Lo uso hace años y me resulta la forma más rápida de dar visibilidad a un equipo.
Cuándo Usar Esto
Usá este enfoque cuando tu equipo necesite un único lugar para ver request rate, latencia y error rate a través de los servicios. Ayuda a los ingenieros on-call a identificar rápido servicios que fallan y da visibilidad de uptime a stakeholders sin técnicos sin que escriban PromQL. También sirve cuando querés que los dashboards estén versionados como código para poder revisarlos en Git y desplegarlos automáticamente.
Lo usé en equipos donde el rotate de on-call incluía gente que no conocía PromQL. Un dashboard bien armado con variables de template les permitía filtrar por servicio y ver qué estaba fallando sin tocar una query. Ese es el valor real: escribís el PromQL una vez y todos los demás tienen un botón. Lo vi funcionar con equipos de 5 personas y con equipos de 50; la dinámica es la misma.
Solución
El flujo es directo: Prometheus scrapea métricas de tus servicios, Grafana consulta a Prometheus a través de un data source provisionado, y los dashboards renderizan esas queries como paneles. Las alertas evalúan expresiones de PromQL y enrutan notificaciones a través de Grafana o Alertmanager.
1. Provisionar el data source de Prometheus
# provisioning/datasources/prometheus.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
2. Construir el JSON del dashboard
{
"dashboard": {
"title": "API Service Overview",
"tags": ["api", "production"],
"timezone": "utc",
"panels": [
{
"title": "Request Rate",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m])) by (route)",
"legendFormat": "{{ route }}"
}
],
"fieldConfig": {
"defaults": {
"unit": "reqps",
"min": 0
}
},
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }
},
{
"title": "P95 Latency",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, route))",
"legendFormat": "{{ route }}"
}
],
"fieldConfig": {
"defaults": {
"unit": "s",
"custom": {
"drawStyle": "line",
"lineWidth": 2
}
}
},
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }
},
{
"title": "Error Rate",
"type": "stat",
"targets": [
{
"expr": "sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m])) * 100",
"legendFormat": "Error %"
}
],
"fieldConfig": {
"defaults": {
"unit": "percent",
"thresholds": {
"steps": [
{ "color": "green", "value": 0 },
{ "color": "yellow", "value": 1 },
{ "color": "red", "value": 5 }
]
}
}
},
"gridPos": { "h": 4, "w": 6, "x": 0, "y": 8 }
}
]
}
}
3. Agregar variables de template
{
"templating": {
"list": [
{
"name": "service",
"type": "query",
"query": "label_values(http_requests_total, job)",
"multi": true,
"includeAll": true
},
{
"name": "route",
"type": "query",
"query": "label_values(http_requests_total{job=~\"$service\"}, route)",
"multi": true,
"includeAll": true
},
{
"name": "interval",
"type": "interval",
"options": [
{ "text": "1m", "value": "1m" },
{ "text": "5m", "value": "5m" },
{ "text": "1h", "value": "1h" }
],
"current": { "text": "5m", "value": "5m" }
}
]
}
}
4. Provisionar dashboards desde disco
# provisioning/dashboards/dashboards.yml
apiVersion: 1
providers:
- name: default
orgId: 1
folder: Services
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
5. Manejar dashboards como código con Terraform
# terraform/grafana.tf
resource "grafana_dashboard" "api" {
config_json = jsonencode({
title = "API Overview"
panels = [
{
title = "Request Rate"
type = "timeseries"
targets = [{
expr = "sum(rate(http_requests_total[5m]))"
}]
}
]
})
}
6. Agregar alertas de Grafana
# provisioning/alerting/alerts.yml
apiVersion: 1
groups:
- orgId: 1
name: API Health
interval: 30s
rules:
- uid: api-error-rate
title: API Error Rate > 5%
condition: A
data:
- refId: A
relativeTimeRange:
from: 300
datasourceUid: prometheus
model:
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
instant: true
noDataState: NoData
execErrState: Error
for: 5m
annotations:
summary: "Error rate above 5%"
labels:
severity: critical
notification_settings:
group_by: ['alertname']
group_wait: 10s
7. Incluir paneles de logs con Loki
# provisioning/datasources/loki.yml
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
url: http://loki:3100
isDefault: false
jsonData:
maxLines: 500
# Logs de error para un servicio específico
{service="api"} |= "error" | json | line_format "{{.msg}}"
# Requests lentos (>1s)
{service="api"} |= "duration" | json | duration > 1000
Explicación
Cada pieza del dashboard tiene un trabajo específico. Los paneles renderizan queries de PromQL como tablas, gráficos, gauges o tiles de stat. Las variables permiten filtrar por servicio, ruta o intervalo sin editar el query. Las rows agrupan paneles en secciones colapsables.
El provisioning carga dashboards desde disco cuando Grafana arranca, así viven en Git. Terraform convierte al dashboard en infraestructura real, como el resto del stack. Las alertas evalúan expresiones de PromQL y enrutan notificaciones a través de Grafana o Alertmanager. Loki agrega contexto de logs junto a las métricas, así podés saltar de un pico a las líneas que lo causaron.
Una cosa que aprendí por las malas: no mezcles métodos de provisioning. Si provisionás dashboards desde disco Y los manejás con Terraform, vas a tener conflictos en cada reinicio. Elegí uno y quedate con él. Prefiero provisioning basado en archivos para dashboards (más simple, nativo de Git) y Terraform para data sources y reglas de alerta (el lifecycle management importa más ahí).
También me topé con un issue sutil con las carpetas de dashboards. Cuando
provisionás dashboards desde disco, el flag foldersFromFilesStructure espera
que el layout de carpetas coincida con la estructura de archivos en disco. Si
alguien crea una carpeta en la UI con el mismo nombre, Grafana las mergea
silenciosamente, y el dashboard provisionado puede sobreescribir el manual. Me
pasé una tarde entera debuggeando eso. La solución es namespacar los nombres de
carpetas o deshabilitar allowUiUpdates por completo.
La documentación de provisioning de Grafana cubre el esquema YAML completo. La documentación de queries de Prometheus es esencial para escribir PromQL que performe bien, especialmente con rate functions y histogram quantiles, que confunden a mucha gente. Todavía la consulto cada pocas semanas cuando estoy tuneando un panel lento.
Variantes
Dashboard de sistema con Node Exporter
# CPU usage
100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Memory usage
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes
# Disk I/O
rate(node_disk_io_time_seconds_total[5m])
Recording rules para queries caros
- record: job:http_p99:5m
expr: histogram_quantile(0.99, sum by(job, le)(rate(http_request_duration_seconds_bucket[5m])))
Mejores Prácticas
- Guardá los dashboards en Git y provisionarlos al inicio. Esto te da revisiones por pull request y rollback. Yo empecé con dashboards en la UI y cuando perdimos uno, migré todo a Git.
- Seteá intervalos de refresh según el caso de uso: 5s para troubleshooting en vivo, 30s–1m para dashboards de overview.
- Limitá variables y cardinalidad de labels. Una variable que lista cada pod en un cluster grande puede volver lentas las queries. Me pasó con un cluster de 200 pods; el dashboard tardaba 30 segundos en cargar.
- Usá recording rules para PromQL caro que aparece en muchos dashboards.
- Preferí
$__rate_intervalen lugar de un rango hardcodeado para que el query se adapte cuando el usuario hace zoom. - Limitá
maxLinesde Loki a unos pocos cientos para evitar traer grandes volúmenes de logs al navegador.
También te recomiendo convenciones de nombres. Prefixá los títulos de dashboards
con el nombre del servicio (API: Request Rate, API: Error Budget) para que
se ordenen juntos en el selector. Tagueá los dashboards consistentemente
(production, staging, on-call) para que la gente pueda filtrar. Parecen
cosas triviales, pero en un equipo con 50+ dashboards, te ahorran tiempo real.
Yo me volví loco buscando dashboards antes de adoptar esta convención; ahora
encuentro cualquier dashboard en segundos.
Para distributed tracing, considerá agregar un data source de Tempo junto con Loki. Podés linkear desde un panel de Grafana directamente a un trace, lo que cierra el loop entre métricas, logs y traces. Lo usé en un incidente donde la métrica mostraba latencia alta pero no decía por qué; el link al trace me llevó directo al servicio que estaba fallando.
Errores Comunes
- Sobrecargar un solo dashboard con 50+ paneles. Se vuelve lento y difícil de leer. Yo cometí este error en mi primer dashboard; tardaba 40 segundos en cargar.
- Copiar un dashboard por servicio en lugar de usar variables. La mantenibilidad explota.
- Olvidar thresholds en paneles stat y gauge. Sin ellos, valores sanos y fallidos se ven iguales.
- Consultar meses de datos en un dashboard de overview. Seteá un rango de tiempo razonable por defecto.
- Dejar dashboards editables en la UI después de provisionarlos. Los cambios se pierden en el próximo reinicio.
Otro error que veo seguido: los equipos se olvidan de setear editable: false
en los data sources provisionados. Alguien cambia la URL en la UI, funciona
hasta el próximo reinicio, y después se rompe silenciosamente. Bloquealo. Me
pasó en un incidente donde perdimos 20 minutos buscando el problema hasta que
descubrimos que alguien había cambiado la URL del data source en la UI.
No pongas lógica de negocio en las alertas del dashboard. Si una regla de alerta necesita una expresión PromQL de 20 líneas con subqueries anidadas, mové ese cómputo a un recording rule primero. La alerta se convierte en un chequeo simple de umbral sobre la métrica grabada, que es más fácil de leer, testear y debuggear. Aprendí esto después de tener una alerta que nadie entendía cómo funcionaba; cuando la simplifiqué con un recording rule, el equipo entero pudo razonar sobre ella.
Resumen
Los dashboards de Grafana convierten métricas de Prometheus en vistas accionables. Conectá un data source, construí paneles con variables de template, provisioná desde disco para que los dashboards vivan en Git, y agregá alertas para las métricas que importan. Mantené los dashboards enfocados (menos de 20 paneles), usá recording rules para queries caros, y bloqueá los recursos provisionados para que los cambios en la UI no sobrevivan un reinicio. Combiná con Loki para logs y tenés un stack de observabilidad completo.
Ver También
- Monitoreo y Alertas con Prometheus: configurá reglas de alerta en Prometheus antes de wirear alertas de Grafana
- Recolección de Métricas: instrumentá tus servicios para exponer métricas de Prometheus en primer lugar
- Logging Estructurado: combiná Grafana con Loki para contexto de logs junto a las métricas
- Documentación de Grafana: referencia oficial para provisioning, paneles y alertas
- Bases de Queries de Prometheus: fundamentos de PromQL para escribir queries de dashboards
Preguntas frecuentes
¿Cómo se compara Grafana con la UI built-in de Prometheus?
Grafana es una plataforma dedicada de visualización con ricos tipos de paneles, variables y layouts. La UI de Prometheus sirve para queries ad-hoc, pero no compone dashboards.
¿Puedo usar Grafana con otros data sources?
Sí. Grafana soporta nativamente Elasticsearch, InfluxDB, CloudWatch, Loki, Jaeger y muchos otros.
¿Debería usar alertas de Grafana o Prometheus Alertmanager?
Ambas funcionan. Las alertas de Grafana mantienen la configuración de notificaciones junto al dashboard. Alertmanager la mantiene junto al pipeline de métricas. Elegí según dónde tu equipo ya gestione el enrutamiento de alertas.
¿Cómo mantengo los dashboards rápidos?
Usá recording rules, seteá rangos de tiempo por defecto, limitá variables y
limitá maxLines de Loki. Evitá agrupar por labels de alta cardinalidad en
paneles de overview.
¿Cuál es la diferencia entre provisioning y Terraform?
El provisioning basado en archivos lee JSON de dashboards desde disco al arrancar, simple y nativo de Git. Terraform maneja los dashboards como infraestructura con comandos de lifecycle (plan, apply, destroy). Usá provisioning para dashboards que querés en Git, Terraform para recursos que necesitan lifecycle management.
Recursos Relacionados
Métricas y Alertas con Prometheus
Instrumenta aplicaciones e infraestructura con métricas de Prometheus, configura reglas de alertas y recording rules para monitoreo eficiente.
RecipeRecoleccion de metricas
Recolecta, agrega y expone métricas de aplicación e infraestructura con Prometheus, StatsD y OpenTelemetry para monitoreo y alertado.
RecipeMonitoreo de APIs con Prometheus
Monitorea rendimiento y salud de APIs con métricas Prometheus, collectors personalizados y reglas de alertamiento.
RecipeAgregación de Logs
Centraliza logs de servicios distribuidos con ELK, Fluentd y Loki para búsqueda, alertado y troubleshooting en producción.
RecipeLogging Estructurado
Implementa logging estructurado con salida JSON, correlation IDs y agregación de logs para observabilidad en producción.
RecipeTracing Distribuido
Tracea requests a través de microservicios distribuidos con OpenTelemetry, Jaeger y Zipkin para debuguear latencia y optimizar performance.