Día 30 de 30 Fase 8: Contenedores, Kubernetes / OpenShift y Observabilidad LKA / LGTM

Observabilidad Completa: Grafana, Prometheus, Loki y OpenTelemetry / Tempo (LKA / LGTM)

Los Tres Pilares: Métricas con Micrometer, Logs Estructurados JSON con Loki y Trazas Distribuidas con Tempo

Visión de conjunto. Sales entendiendo cómo funciona y cuándo usarlo; dominarlo pide más práctica en un proyecto real.

  • 4h de estudio
  • 5 conceptos
  • 3 preguntas
  • 1 katas
GrafanaPrometheusLokiOpenTelemetryTempoMicrometerTraceID
Al terminar este día sabrás 4
  • Distinguir para qué sirven métricas, logs y trazas y cómo se correlacionan.
  • Instrumentar métricas propias con Micrometer y exponerlas a Prometheus.
  • Emitir logs JSON estructurados con identificador de traza para Loki.
  • Seguir una petición entre servicios con OpenTelemetry y Tempo, y saltar entre señales en Grafana.

Los Tres Pilares de la Observabilidad: Métricas, Logs y Trazas

Métricas (Prometheus): valores numéricos agregados a lo largo del tiempo (requests/sec, latencia p99, uso de CPU, conexiones JDBC libres). Logs (Loki): registros textuales enriquecidos con contexto de eventos ocurridos. Trazas Distribuidas (Tempo / Jaeger): el recorrido completo de una petición a través de múltiples microservicios con spans y tiempos de ejecución.

En una línea Métrica alerta en Grafana -> Clic en el TraceID en Tempo -> Abre directamente los logs correlacionados en Loki con el mismo TraceID.

Stack LGTM completo en local con un solo contenedor yaml
# compose.yaml: Grafana + Loki + Tempo + Prometheus + colector OpenTelemetry
services:
  lgtm:
    image: grafana/otel-lgtm:latest
    ports:
      - "3000:3000"     # Grafana (admin / admin)
      - "4317:4317"     # OTLP gRPC
      - "4318:4318"     # OTLP HTTP: aquí envía la aplicación trazas, métricas y logs

# Con spring-boot-docker-compose en el classpath, Spring Boot 3.4+ arranca este compose
# al ejecutar la aplicación y configura automáticamente los endpoints OTLP.
Cómo funciona por dentro

Las métricas son valores numéricos agregados en el tiempo (peticiones por segundo, latencia p99, uso de memoria). Son baratas de almacenar, ideales para paneles y alertas, y responden «¿algo va mal?». Los logs son eventos discretos con detalle (qué pedido falló y por qué) y responden «¿qué pasó exactamente?». Las trazas siguen una petición a través de todos los servicios y operaciones que toca, con su duración, y responden «¿dónde se va el tiempo o dónde falla?».

Cada pilar por separado se queda corto. La potencia aparece al correlacionarlos con un identificador común, el trace id: una alerta de latencia lleva a una traza lenta, la traza señala el servicio y el tramo culpable, y sus logs explican el motivo.

El stack LGTM de Grafana cubre los tres con herramientas abiertas: Loki para logs, Grafana para visualizar, Tempo para trazas y Mimir o Prometheus para métricas. OpenTelemetry es el estándar para generar y transportar las señales sin atarse a un proveedor.

Permite diagnosticar incidentes en minutos: la métrica detecta la anomalía, la traza localiza el microservicio culpable y el log revela la causa raíz exacta.

Se conecta con SREGrafana LGTM StackMTTR (Mean Time To Resolve)

Cuatro bloques cronometrados. No pases al siguiente sin tener el resultado esperado.

  1. Bloque 1: Métricas de Spring Boot con Micrometer y Prometheus (0 - 25 min)

    Qué estudiar. Endpoint /actuator/prometheus, métricas JVM, Timers personalizados.

    Pregunta a responder. ¿Cómo instrumentar un método de negocio para medir su tiempo de ejecución p95?

    Resultado esperado. Controlador con métrica personalizada de Micrometer expuesta en /actuator/prometheus.

  2. Bloque 2: Logs Estructurados JSON para Grafana Loki (25 - 50 min)

    Qué estudiar. Configuración de logback-spring.xml con encoder JSON, campos traceId y spanId.

    Pregunta a responder. ¿Por qué los logs estructurados facilitan las consultas en Grafana?

    Resultado esperado. logback-spring.xml configurado emitiendo JSON por consola.

  3. Bloque 3: Trazas Distribuidas con OpenTelemetry y Tempo (50 - 80 min)

    Qué estudiar. micrometer-tracing-bridge-otel, exportador OTLP hacia Tempo, propagación W3C.

    Pregunta a responder. ¿Cómo viaja el traceparent en las cabeceras HTTP entre microservicios?

    Resultado esperado. Microservicio enviando trazas a Grafana Tempo local con docker-compose.

  4. Cierre y Consolidación (80 - 90 min)

    Qué estudiar. La experiencia de depuración correlacionada en Grafana.

    Pregunta a responder. ¿Cuál es el flujo ideal para depurar una incidencia en producción?

    Resultado esperado. Diagrama del flujo Métrica -> Traza -> Log guardado.

Tres formas de comprobar si lo has entendido, de menos a más exigente: explicarlo con tus palabras, responder preguntas trampa y resolver el reto del tutor.

Explícalo desde cero

Lee cada ficha y explícala en voz alta antes de seguir: si puedes contárselo a alguien que empieza, lo has entendido.

Por qué el Trace ID es el hilo conductor de toda la arquitectura de microservicios

Lo que debes entender

En un monolito puedes seguir el hilo con un debugger o un log secuencial. En 20 microservicios distribuidos, una petición de usuario se fragmenta en decenas de llamadas HTTP y mensajes Kafka asíncronos. El Trace ID es el pasaporte único que acompaña a la petición desde que entra al Gateway hasta que sale. Cualquier log o métrica sin Trace ID es un mensaje en una botella en medio del océano.

Analogía para contarlo

El Trace ID es como el número de seguimiento de un paquete de Amazon: te dice en qué camión está, en qué almacén se detuvo y cuánto tiempo estuvo en cada parada.

Lo que suele explicarse mal

Pensar que observabilidad es solo "poner Grafana para ver gráficos bonitos de CPU". La CPU es solo un síntoma; las trazas correlacionadas con logs dan la causa exacta.

Señal de que aún no lo dominas

Si tienes que pedirle al usuario su hora exacta para buscar en los logs qué pasó con su petición.

Preguntas trampa

Responde de memoria, en voz alta o por escrito, y después abre la respuesta razonada: lo importante es el porqué, no la palabra exacta.

Nivel 1 (Básico) ¿Cuál es la diferencia entre un Trace ID y un Span ID en OpenTelemetry? Ver respuesta

Respuesta razonada

El Trace ID identifica la traza completa, es decir, el recorrido de una petición de principio a fin a través de todos los servicios. Es un identificador de 128 bits (32 caracteres hexadecimales) que se genera en el primer servicio y se propaga sin cambios a todos los demás.

El Span ID identifica una única operación dentro de esa traza (64 bits, 16 caracteres): la petición HTTP en el gateway, la consulta SQL en un servicio, la publicación en Kafka. Cada span guarda además el id de su padre, lo que permite reconstruir el árbol de llamadas y ver qué operación tardó cuánto. En la cabecera traceparent viajan ambos: el trace id común y el span id del padre.

Qué está evaluando la pregunta

El Trace ID representa el viaje completo de la petición a través de todo el sistema distribuido (es común a todos los microservicios involucrados). El Span ID representa una operación individual y acotada dentro de un servicio concreto (e.g. una consulta SQL o una llamada HTTP específica).

Nivel 2 (Intermedio) ¿Por qué no se debe incluir el ID de usuario o el email en las etiquetas (tags) de una métrica de Micrometer / Prometheus? Ver respuesta

Respuesta razonada

Por la cardinalidad. Cada combinación distinta de valores de etiquetas crea una serie temporal independiente en Prometheus, con su propio coste de memoria y almacenamiento. Una etiqueta userId con un millón de usuarios multiplica por un millón el número de series de esa métrica, lo que satura Prometheus, dispara el coste y hace las consultas lentísimas. Las etiquetas deben tener un número pequeño y acotado de valores: método HTTP, código de estado, ruta con plantilla (/tareas/{id}, no /tareas/42), región.

Además, un email en una métrica es un dato personal que acabaría en un sistema que no está pensado para protegerlo ni para borrarlo a petición (RGPD). El detalle por usuario va en logs o en atributos de los spans, que se consultan individualmente.

Qué está evaluando la pregunta

Problema de alta cardinalidad: cada combinación única de etiquetas genera una nueva serie temporal en la base de datos de Prometheus. Con miles de usuarios, Prometheus consumirá gigabytes de RAM y colapsará. Los identificadores únicos deben ir en los Logs estructurados o en los atributos de las Trazas, nunca en las métricas agregadas.

Nivel 3 (Entrevista Senior) ¿Qué problema específico de propagación de contexto de trazas surge al usar Virtual Threads de Java 21 con ThreadLocal clásico, y cómo lo resuelven Micrometer Tracing y OpenTelemetry? Ver respuesta

Respuesta razonada

Los hilos virtuales sí soportan ThreadLocal, pero cada tarea se ejecuta en un hilo virtual nuevo, y un hilo nuevo no hereda el contexto del que lo lanzó. Si dentro de una petición repartes trabajo en un newVirtualThreadPerTaskExecutor(), las subtareas arrancan sin traza activa ni MDC: sus spans aparecen como trazas huérfanas y sus logs sin traceId. Además, guardar objetos costosos en ThreadLocal deja de tener sentido con millones de hilos de vida corta.

Micrometer lo resuelve con la librería Context Propagation: captura el contexto actual (ContextSnapshot) y lo restaura en el hilo de destino. Se aplica envolviendo el executor (ContextExecutorService.wrap(...)) o, para @Async y los ejecutores de Spring, con ContextPropagatingTaskDecorator. Reactor usa el mismo mecanismo con Hooks.enableAutomaticContextPropagation(). A futuro, Scoped Values ofrecen un modelo de contexto inmutable y heredable más adecuado para hilos virtuales.

Qué está evaluando la pregunta

Las librerías de tracing clásicas guardaban el TraceContext en un ThreadLocal. Al usar millones de Virtual Threads creados y destruidos rápidamente, o pools de tareas asíncronas, el contexto no se propaga automáticamente entre hilos a menos que se use un Executor decorado (ContextPropagatingExecutorService) o ScopedValue de Java 21+. Las versiones modernas de Micrometer Tracing gestionan esta propagación interceptando la creación de tareas asíncronas.

Reto del tutor

Un microservicio en producción tiene picos de latencia de 5 segundos esporádicos. Los logs no muestran excepciones ni errores (HTTP 200). En Grafana ves que la CPU está al 15% y la memoria al 40%. ¿Qué pasos exactos seguirías para encontrar la causa raíz usando observabilidad completa?

Lo que una respuesta suele tener bien

Propone mirar las trazas y los tiempos de base de datos.

Lo que suele quedarse en la superficie

Decir "revisar más logs".

El concepto de fondo que suele faltar

No usar la cascada de observabilidad metódicamente: métricas de percentil p99 -> trazas distribuidas en Tempo -> spans individuales de BD o llamadas externas -> logs correlacionados.

Cómo lo respondería alguien senior en una entrevista

El procedimiento metodológico SRE: (1) En Grafana, consultar la métrica de latencia por percentil http_server_requests_seconds{quantile="0.99"} para identificar la ventana temporal exacta de los picos; (2) En Grafana Tempo, filtrar trazas de esa ventana con duración > 4s; (3) Abrir el waterfall de una de esas trazas y observar qué Span consume el 95% del tiempo (e.g. una query a PostgreSQL o una llamada a un servicio externo); (4) Si es la BD, verificar en Prometheus la métrica hikaricp_connections_pending (espera por conexión libre en el pool) o pausas de GC; (5) Con el TraceID del span lento, ir a Grafana Loki para ver los logs contextuales de esa ejecución específica (parámetros de consulta, volumen de datos procesado).

Proyecto «Pedidos» · paso 30 de 30

Observabilidad completa

Saber qué pasa en producción: cuántos pedidos entran, cuánto tardan y dónde fallan.

De qué va el proyecto

El backend de una tienda online: clientes, catálogo de productos y pedidos con sus líneas, pagos y envíos. Empieza como un proyecto Maven con records y termina como un sistema con API REST, seguridad, mensajería, contenedores y observabilidad. Cada paso construye sobre el anterior, así que trabaja siempre en el mismo repositorio.

Qué hacer

  1. Publica métricas de negocio con Micrometer: pedidos confirmados, importe vendido y tiempo de confirmación.
  2. Emite los logs en JSON con el trace id incluido.
  3. Propaga la traza de pedidos a notificaciones a través de Kafka y visualízala en Grafana con Tempo.

Está listo cuando

  • Un panel de Grafana muestra pedidos por minuto y la latencia p95 de la API.
  • Desde un log de error puedes saltar a la traza completa del pedido en los dos servicios.

Katas: ejercicios cortos

Reglas de oro

  • Nunca pongas IDs de usuario ni valores de alta cardinalidad en tags de métricas.
  • Emite siempre logs en formato JSON estructurado con TraceID y SpanID automáticos.
  • Propaga las cabeceras de traza W3C (traceparent) en todas las llamadas HTTP y mensajes Kafka.
  • Configura un endpoint /actuator/prometheus seguro y monitorea el percentil p99, no solo el promedio.
  • Integra Data Links en Grafana para navegar con un clic entre Métricas, Trazas (Tempo) y Logs (Loki).
Se guarda automáticamente

Fuentes oficiales

Revisado el . Este día en Markdown