Grafana¶
Grafana visualiza métricas, logs y trazas de la plataforma en dashboards unificados. Integra Prometheus (métricas), Loki (logs) y Tempo (trazas) en una sola interfaz, permitiendo correlacionar datos de observabilidad para diagnóstico rápido.
Instalación con Docker Compose¶
# compose.observability.yml
services:
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
GF_USERS_ALLOW_SIGN_UP: "false"
GF_SERVER_ROOT_URL: https://monitoring.example.com
GF_AUTH_ANONYMOUS_ENABLED: "false"
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
networks:
- frontend
volumes:
grafana_data:
Configurar datasources (provisioning)¶
# grafana/provisioning/datasources/datasources.yml
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
access: proxy
isDefault: true
jsonData:
timeInterval: "15s"
- name: Loki
type: loki
url: http://loki:3100
access: proxy
jsonData:
derivedFields:
- datasourceUid: tempo
matcherRegex: '"traceId":"(\w+)"'
name: TraceID
url: '$${__value.raw}'
- name: Tempo
type: tempo
url: http://tempo:3200
access: proxy
jsonData:
tracesToLogs:
datasourceUid: loki
filterByTraceID: true
spanStartTimeShift: -1h
spanEndTimeShift: 1h
Dashboard de Keycloak¶
Importar el dashboard community de Keycloak (ID: 19659 en grafana.com) o crear uno personalizado:
Panels recomendados¶
Panel 1 — Tasa de logins por realm
Query: rate(keycloak_logins_total[5m])
Tipo: Time series
Leyenda: {{realm}}
Panel 2 — Errores de login
Query: rate(keycloak_login_errors_total[5m])
Tipo: Time series, color rojo
Alerta: > 0.1 req/s durante 5 min
Panel 3 — Sesiones activas
Query: keycloak_sessions_active_total
Tipo: Stat (número actual)
Panel 4 — Uso de memoria JVM de Keycloak
Query: jvm_memory_used_bytes{job="keycloak", area="heap"}
/ jvm_memory_max_bytes{job="keycloak", area="heap"} * 100
Tipo: Gauge (0-100%)
Umbral rojo: > 85%
Panel 5 — Top clientes por tokens emitidos
Query: topk(5, sum by (clientId) (rate(keycloak_client_logins_total[1h])))
Tipo: Bar chart
Importar dashboard via API¶
# Descargar dashboard de Keycloak de la comunidad
curl -s https://grafana.com/api/dashboards/19659/revisions/latest/download > keycloak-dashboard.json
# Importar via API de Grafana
curl -s -X POST \
-H "Content-Type: application/json" \
-u "admin:${GRAFANA_PASSWORD}" \
-d "{\"dashboard\": $(cat keycloak-dashboard.json), \"overwrite\": true}" \
http://localhost:3000/api/dashboards/import
Dashboard de Spring WebFlux APIs¶
Panel 1 — Latencia p95 por endpoint
Query: histogram_quantile(0.95, rate(http_server_requests_seconds_bucket{job="identity-api"}[5m]))
Tipo: Time series
Panel 2 — Tasa de errores HTTP 5xx
Query: rate(http_server_requests_seconds_count{status=~"5..",job="identity-api"}[5m])
Tipo: Time series, color naranja
Panel 3 — Throughput (req/s)
Query: rate(http_server_requests_seconds_count{job="identity-api"}[1m])
Tipo: Stat
Panel 4 — CPU del proceso
Query: process_cpu_usage{job="identity-api"}
Tipo: Gauge
Logs con Loki¶
# En el panel de Logs, query LogQL:
# Todos los errores de Keycloak
{container="keycloak"} |= "ERROR"
# Errores de login por realm
{container="keycloak"} | json | level="ERROR" | line_format "{{.message}}"
# Logs de Spring con traceId específico
{container="identity-api"} |= "traceId=abc123"
# Correlacionar con Tempo: hacer clic en el traceId en el log
# abre automáticamente la traza en Tempo
Alertas en Grafana¶
# grafana/provisioning/alerting/alerts.yml
apiVersion: 1
groups:
- name: Identity Platform
interval: 1m
rules:
- uid: keycloak-down
title: Keycloak no disponible
condition: C
data:
- refId: A
queryType: ''
relativeTimeRange:
from: 600
to: 0
datasourceUid: prometheus
model:
expr: up{job="keycloak"}
intervalMs: 1000
maxDataPoints: 43200
refId: A
noDataState: Alerting
execErrState: Alerting
for: 1m
annotations:
summary: "Keycloak no está respondiendo"
labels:
severity: critical
Explorar trazas desde logs
Configura el datasource de Loki con derivedFields para que los traceId en los logs sean links clicables que abren la traza en Tempo. Esto reduce el tiempo de diagnóstico de minutos a segundos.