Saltar al contenido principal

Monitoreo con Prometheus, Loki y Grafana

El stack de monitoreo es opcional y se despliega por separado del stack principal mediante docker-compose.monitoring.yml. Una vez activo, expone métricas del backend en tiempo real a través de Grafana.

Arquitectura del stack de monitoreo

backend (Spring Boot)
│ /actuator/prometheus ← Prometheus raspa cada 15 s

Prometheus ← Almacena métricas (15 días de retención)


Grafana ← Visualización de dashboards

├── Prometheus datasource
└── Loki datasource ← Logs de contenedores

Promtail ← Lee logs de Docker y los envía a Loki

Componentes

ContenedorImagenPuerto internoRol
sgi-full-prometheusprom/prometheus:latest9090Scraping y almacenamiento de métricas
sgi-full-lokigrafana/loki:2.9.103100Almacenamiento de logs
sgi-full-promtailgrafana/promtail:3.0.0Recolección de logs desde Docker
sgi-full-grafanagrafana/grafana:11.5.23000Dashboard de visualización
Versiones fijadas
  • Loki 2.9.10: Loki 3.x rompe la compatibilidad con boltdb-shipper + schema v11.
  • Promtail 3.0.0: Promtail 2.9.x usa Docker client API 1.42 (hardcodeado en el SDK de Go); los servidores modernos requieren mínimo API 1.44. Solo Promtail 3.x es compatible.
  • Grafana 11.5.2: Grafana 12 tiene un bug en el provisioning de datasources con UIDs fijos que causa crash loop al iniciar.

Redes

El stack de monitoreo usa dos redes externas que deben existir antes de desplegarlo:

RedPropósito
sgi_internalPermite a Prometheus alcanzar el backend para raspar /actuator/prometheus
proxy_networkExpone Grafana a través de Nginx Proxy Manager con HTTPS

Ambas redes se crean automáticamente al levantar el stack principal con docker compose up.

Despliegue

Prerrequisitos

  1. El stack principal debe estar corriendo (docker compose up -d).
  2. Las redes sgi_internal y proxy_network deben existir.
  3. La imagen del backend debe incluir la dependencia micrometer-registry-prometheus y tener /actuator/prometheus en rutas permitidas.

Levantar el stack de monitoreo

# Desde la raíz del repositorio
docker compose -f docker-compose.monitoring.yml up -d

Esto crea y arranca Prometheus, Loki, Promtail y Grafana.

Verificar que todos los servicios están corriendo

docker compose -f docker-compose.monitoring.yml ps

Todos deben aparecer como running o healthy.

Verificar que Prometheus puede raspar el backend

# Comprueba el endpoint de métricas del backend directamente
docker exec sgi-full-prometheus wget -qO- http://sgi-full-backend:8080/actuator/prometheus | head -20

Si devuelve líneas con métricas (# HELP, # TYPE), el scraping está funcionando.

También puedes abrir la UI de Prometheus en el servidor (si tienes acceso por túnel o red interna):

http://<servidor>:9090/targets

El target sgi-backend debe aparecer como UP.

Actualizar el stack de monitoreo

git pull
docker compose -f docker-compose.monitoring.yml up -d

Detener el stack de monitoreo

# Detiene sin eliminar datos
docker compose -f docker-compose.monitoring.yml down

# Detiene Y elimina todos los datos históricos (métricas, logs)
docker compose -f docker-compose.monitoring.yml down -v

Acceder a Grafana

Grafana está disponible en:

https://sgi-grafana.escuelamilitar.edu.pe

Las credenciales por defecto son:

CampoValor por defecto
Usuarioadmin
Contraseñaadmin
Cambia la contraseña por defecto

En el primer acceso, Grafana pedirá cambiar la contraseña. Usa una contraseña segura y guárdala en un gestor de contraseñas. Si necesitas restablecerla, usa las variables de entorno GRAFANA_USER y GRAFANA_PASSWORD en el archivo .env.

Dashboard precargado: SGI-EMCH Backend

Al arrancar, Grafana carga automáticamente el dashboard "SGI-EMCH Backend" (UID sgi-emch-backend-v1) con los siguientes paneles:

Sección: JVM & Sistema

PanelMétrica
Heap usado (%)jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"} * 100
Threads activosjvm_threads_live_threads
GC pausas/minrate(jvm_gc_pause_seconds_count[1m]) * 60
GC tiempo total/minrate(jvm_gc_pause_seconds_sum[1m]) * 60

Sección: HTTP — Tráfico y Errores

PanelMétrica
Requests por minutosum(rate(http_server_requests_seconds_count[1m])) * 60
Tasa de error (%)(errores) / (total) * 100

Sección: Latencia HTTP

PanelMétrica
P50 latenciahistogram_quantile(0.50, ...)
P95 latenciahistogram_quantile(0.95, ...)
P99 latenciahistogram_quantile(0.99, ...)

Sección: Base de Datos (HikariCP)

PanelMétrica
Conexiones activashikaricp_connections_active
Conexiones pendienteshikaricp_connections_pending
Tiempo de adquisición P99histogram_quantile(0.99, hikaricp_connection_acquired_nanos_bucket) / 1e6

Sección: Caché Caffeine

PanelMétrica
Hit rate por caché (%)rate(cache_gets_total{result="hit"}[5m]) / (hits + misses) * 100
Misses por minutorate(cache_gets_total{result="miss"}[1m]) * 60

Sección: Logs en vivo

Panel de logs de Loki con filtro {container="sgi-full-backend"} — muestra los últimos registros del backend en tiempo real.

Provisionamiento automático

Los datasources y el dashboard se configuran automáticamente al arrancar Grafana mediante archivos YAML en monitoring/grafana/provisioning/:

monitoring/
├── prometheus/
│ └── prometheus.yml # Configuración de scraping (job sgi-backend)
├── loki/
│ └── loki-config.yaml # Configuración de almacenamiento de logs
├── promtail/
│ └── promtail-config.yaml # Recolección de logs de contenedores sgi-full-*
└── grafana/
└── provisioning/
├── datasources/
│ └── datasources.yaml # Prometheus (UID: prometheus-sgi) y Loki (UID: loki-sgi)
└── dashboards/
├── dashboards.yaml # Proveedor de tipo "file" apuntando a esta carpeta
└── sgi-backend.json # Dashboard precargado

Los UIDs de datasource fijos (prometheus-sgi, loki-sgi) son referenciados directamente en el JSON del dashboard, eliminando la necesidad de variables de template.

Diagnóstico de problemas

Grafana muestra "No data" en los paneles

  1. Verifica que el target en Prometheus esté UP:
    docker exec sgi-full-prometheus wget -qO- http://localhost:9090/api/v1/targets | grep health
  2. Asegúrate de que haya transcurrido al menos 1 minuto desde el inicio del backend para que Prometheus tenga datos suficientes.
  3. Ajusta el rango de tiempo en Grafana al momento en que el backend inició.

Promtail no recolecta logs

Verifica los logs de Promtail:

docker logs sgi-full-promtail --tail 50

Debe aparecer msg="added Docker target" para cada contenedor sgi-full-*.

Backend devuelve 401 en /actuator/prometheus

El endpoint debe estar en la lista de rutas públicas de SecurityConfig.java. Verifica:

docker exec sgi-full-prometheus wget -qS http://sgi-full-backend:8080/actuator/prometheus 2>&1 | grep HTTP

Debe mostrar HTTP/1.1 200. Si muestra 401, reconstruye el backend:

docker compose build backend && docker compose up -d backend

Grafana no arranca (crash loop)

Si los logs muestran Datasource provisioning error: data source not found, el volumen grafana_data tiene estado inconsistente. Reinicializa:

docker compose -f docker-compose.monitoring.yml stop grafana
docker rm sgi-full-grafana
docker volume rm sgi-emch_grafana_data
docker compose -f docker-compose.monitoring.yml up -d grafana