02 · Fundamentos de Observabilidad
Mapa rápido del tool‑chain (¿qué es cada cosa y para qué sirve?)
Prometheus
Base de datos de series temporales (TSDB). Scrapea métricas vía HTTP y da un potente lenguaje de consulta (PromQL).
Estándar CNCF, pull‑based → menos overhead, enorme ecosistema de exporters y rules reutilizables.
Grafana
UI unificada: dashboards, alertas, exploración de métricas/logs/trazas.
Abstrae múltiples back‑ends; paneles listos, alertas visuales y enlaces cruzados.
Loki
Almacén de logs indexados por etiquetas en vez de por texto completo.
Consumir logs baratos (S3, local), mismo modelo de etiquetas que Prometheus ⇒ consultas coherentes.
Tempo
Almacén de trazas distribuido y altamente escalable (sucesor de Jaeger/Zipkin).
Soporta OTLP nativo, sin necesidad de índices costosos; se integra directo en Grafana.
OpenTelemetry (OTEL)
Estándar vendor‑neutral para instrumentar aplicaciones (API + SDK + spec).
"Instrumenta una vez, exporta a cualquiera"; comunidad activa, versión 1.0 estable.
Promtail
Agente daemon que lee ficheros de log y los envía a Loki con etiquetas.
Config YAML sencilla, sin sidecar pesado (a diferencia de Logstash o Fluend).
OTEL Collector (opcional)
Proxy/roteador que recibe telemetría, transforma y re‑exporta a uno o varios back‑ends.
Desacopla tu app de la infraestructura de observabilidad; centraliza sampling, batching y seguridad.
Docker Compose
Orquestador local para levantar todo el stack rápidamente.
Nada de instalar cada pieza a mano; reproducible por los alumnos en cualquier OS.
0.1 Cómo se relacionan entre sí
Prometheus tira de las métricas cada N segundos; Loki y Tempo reciben push desde los agentes/SDK.
Grafana no almacena datos; sólo los visualiza y correlaciona.
Objetivo General: Al finalizar esta clase queremos comprender los conceptos fundamentales de la observabilidad, cómo instrumentar aplicaciones Node.js con OpenTelemetry y utilizar herramientas como Grafana, Loki y Prometheus para monitorear, depurar y analizar el comportamiento de microservicios.
Parte 1: Fundamentos de la Observabilidad
1. Introducción a la Observabilidad
¿Qué es la Observabilidad y por qué es crucial?
Diferencias clave entre Monitoreo Clásico vs. Observabilidad Moderna.
Monitoreo: Sabemos qué preguntas hacer (¿Está el servidor arriba?).
Observabilidad: Capacidad de hacer preguntas nuevas y desconocidas sobre el sistema sin necesidad de redeployar código (¿Por qué este usuario específico experimenta latencia solo en este endpoint?).
Desafíos en arquitecturas de microservicios: Complejidad, debugging distribuido, fallos en cascada, "unknown unknowns".
Beneficios: Reducción del MTTR (Mean Time To Resolution), mejora de la fiabilidad, comprensión proactiva del sistema.
Caso real de estudio: El E-commerce en Black Friday.
Escenario: Picos de tráfico, errores intermitentes en el checkout, quejas de usuarios.
Pregunta: ¿Cómo correlacionamos un aumento en
http_server_requests_seconds_count{status="500"}con las trazas específicas que fallaron y los logs detallados del error para identificar que un servicio de inventario aguas abajo estaba fallando por timeouts?
Explicación: Un timeout en la BD de Productos causa que el Servicio de Productos falle, lo que a su vez hace que el Servicio de Órdenes falle, impactando al usuario. Sin observabilidad, encontrar la causa raíz (D) es un desafío.
Discusión Rápida:
¿Habeis enfrentado problemas similares y cómo los resolvieron?
¿Qué herramientas usan actualmente para monitorear sus aplicaciones?
2. Los Pilares de la Observabilidad: Logs, Métricas y Trazas
Introducción a los 3 Pilares: La base para entender el comportamiento del sistema.
Logs (Registros):
¿Qué son? Eventos discretos, inmutables y con marca de tiempo. Útiles para información detallada y errores específicos.
Buenas prácticas: Logs estructurados (JSON), niveles de log (INFO, WARN, ERROR), incluir contexto relevante (IDs de correlación, IDs de usuario).
Herramientas Comunes: Loki, ELK Stack (Elasticsearch, Logstash, Kibana).
Métricas:
¿Qué son? Agregaciones numéricas medibles en el tiempo (contadores, medidores, histogramas). Útiles para dashboards, alertas y entender tendencias.
Tipos comunes: Tasa de errores, latencia (percentiles P95, P99), throughput (RPS), uso de CPU/memoria.
Herramientas Comunes: Prometheus, DataDog, Dynatrace.
Trazas (Tracing Distribuido):
¿Qué son? Representan el flujo de una solicitud a través de múltiples servicios. Compuestas por "spans" (unidades de trabajo).
Beneficios: Identificar cuellos de botella, entender dependencias entre servicios, depurar errores en sistemas distribuidos.
Conceptos Clave:
traceId, `spanIdHerramientas Comunes: Jaeger, Tempo (parte de Grafana Stack), Zipkin, DataDog APM, Dynatrace.
Correlación entre Pilares: La magia ocurre cuando se usan juntos. Ejemplo: Una alerta de métrica (alta latencia P99) te lleva a una traza específica, donde un span anómalo te permite ver los logs de ese servicio y span particular para encontrar el error.
Explicación: La aplicación emite los tres tipos de señales, que son recolectadas por sus respectivos backends y luego visualizadas y correlacionadas en Grafana.
Ejercicio Práctico: Preparando el Entorno con Docker
docker-compose.yml:
promtail-local-config.yml:
prometheus.yml:
Levantar el Stack:
Verificar Servicios:
Grafana:
http://localhost:3000Prometheus:
http://localhost:9090Loki (API, no UI por defecto):
http://localhost:3100/ready(debería dar "ready"). Puede tardar hasta 15 segundos en estar listo. Probar concurl -i http://localhost:3100/ready
Generar Logs de Ejemplo:
Crear un archivo example-log-generator.ts:
Configurar promtail para que recolecte logs de app.log:
Explorar Logs en Grafana:
Ir a Grafana (
http://localhost:3000).Sección "Explore".
Seleccionar "Loki" como datasource (puede requerir configuración inicial si no está auto-detectado: URL
http://loki:3100).Probar query:
filename = "app.log"o similar.
3. OpenTelemetry: El Estándar de la Trazabilidad Moderna
¿Qué es OpenTelemetry (OTEL)?
Un conjunto de APIs, SDKs, herramientas y especificaciones agnósticas al proveedor.
Objetivo: Estandarizar la forma en que se recolecta y exporta la telemetría (logs, métricas, trazas).
Incubado por la CNCF (Cloud Native Computing Foundation).
Componentes Clave de OTEL:
API (Application Programming Interface): Define cómo instrumentar el código (crear spans, registrar métricas). Tu código interactúa con la API.
SDK (Software Development Kit): Implementación concreta de la API. Gestiona el muestreo (sampling), procesamiento y exportación de datos.
Exporters: Envían datos a diferentes backends (Jaeger, Prometheus, Loki, OTLP Collector, DataDog, etc.).
Collector (Opcional pero recomendado): Un proxy que recibe telemetría, la procesa/filtra y la reenvía a uno o más backends. Desacopla la app del backend.
Instrumentación en Node.js:
Automática: Librerías que "parchean" módulos comunes (HTTP, Express, gRPC, clientes de BD) para generar spans y métricas automáticamente.
Ej:
@opentelemetry/auto-instrumentations-node
Manual: Crear spans y métricas explícitamente en tu código para lógica de negocio específica.
Demo en vivo (conceptual): Mostrar una traza compleja en Jaeger o Tempo, explicando la jerarquía de spans, tags, logs en spans, y cómo ayuda a identificar cuellos de botella.
Ejercicio Práctico: Instrumentación Básica con OTEL en Node.js (15m):
(Asumir una app Express simple en ejercicio2-otel-node/app.js dentro del repo clonado).
Navegar al directorio del ejercicio:
Instalar dependencias de OTEL:
Crear archivo
tracing.ts(o similar) para configurar el SDK:
Crear
app.tspara cargartracing.tsal inicio:
Añadir Tempo al
docker-compose.yml(si no estaba):
Y un tempo-config.yaml simple:
Reiniciar Docker Compose:
docker compose up -d --force-recreate
Ejecutar la app Node.js:
node app.ts (o configurar para que corra en Docker).
Ver Trazas en Grafana/Tempo:
En Grafana, ir a "Explore".
Seleccionar "Tempo" como datasource (URL
http://tempo:3200).En la pestaña "Search", buscar trazas (puede tardar unos segundos en aparecer). Puedes filtrar por
service.name="my-node-app".Analizar una traza, especialmente la de
/slow.
Parte 2: Implementación Práctica y Casos de Uso
4. Métricas de Aplicación y Negocio + Dashboards
Más allá de las Métricas de Infraestructura: No solo CPU/Memoria. Necesitamos métricas que reflejen la salud de la aplicación y el impacto en el negocio.
Métricas GOLD (Google SRE): Latency, Errors, Traffic, Saturation. Aplicables a servicios.
Métricas de Negocio (KPIs):
Derivadas de eventos del dominio:
UserSignedUp,OrderCreated,PaymentProcessed,PaymentFailed.Ejemplos: Tasa de conversión (ej.
PaymentSuccess / PaymentAttempt), número de carritos abandonados, valor promedio de orden (AOV).¿Cómo instrumentarlas? Contadores, Gauges.
Diagrama Mermaid: Customer Journey y Métricas Relevantes
Explicación: Cada paso del journey puede generar métricas que ayudan a entender el embudo y los puntos de fricción.
Ejercicio Práctico: Instrumentar Métricas Custom y Crear Dashboard (20m):
Instalar exportador de Prometheus para OTEL (si no se hizo):
Modificar
tracing.tspara añadir el exportador de métricas:
Nota: La configuración de métricas con OTEL puede ser un poco más compleja de integrar con NodeSDK que las trazas. Para el ejercicio, la configuración del PrometheusExporter y MeterProvider es clave. El NodeSDK debería idealmente manejar la inicialización del MeterProvider. Si no, el MeterProvider debe ser configurado y sus Meters usados explícitamente.
Instrumentar una métrica de negocio en
app.js:
Configurar Prometheus para scrapear la app Node.js:
Añadir un nuevo job a
prometheus.yml(delejercicio1-docker-stacko crear uno nuevo). Asumiendo que la app Node.js está en la misma red Docker que Prometheus y se llamamy_node_app:
Importante: Si la app Node.js corre fuera de Docker (ej.
node app.jsen tu host), y Prometheus dentro de Docker,host.docker.internales el DNS para acceder al host desde un contenedor Docker (en Mac/Windows). Para Linux, sería la IP deldocker0bridge o la IP principal del host. Si Node.js también está en un contenedor, usa el nombre del servicio y puerto interno.
Reiniciar
docker-composey la app Node.js.Generar algunas órdenes:
Crear un Dashboard Básico en Grafana:
Ir a Grafana (
http://localhost:3000).Asegurar que Prometheus es un datasource (URL
http://prometheus:9090).Crear un nuevo Dashboard.
Añadir panel > "Time series" o "Stat".
Query (Total Órdenes):
sum(orders_total)osum(rate(complex_operation_success_total[5m])) by (outcome)para tasa.
5. Alertas Automatizadas y Notificaciones
¿Por qué Alertas? Notificación proactiva de problemas antes de que los usuarios los reporten (o a gran escala).
Tipos de Alertas:
Basadas en Métricas: Umbrales (CPU > 80%), tasas de error (errores 5xx > 5%), anomalías. (Prometheus + Alertmanager).
Basadas en Logs: Patrones de error específicos en logs (Loki puede generar alertas o Grafana sobre Loki).
Basadas en Trazas (Menos común para alertas directas): Más para investigación, pero se pueden derivar métricas de trazas (ej. % de trazas con error).
Buenas Prácticas para Alertas:
Accionables: Cada alerta debe llevar a una acción o investigación clara.
Evitar Fatiga por Alertas ("Alert Fatigue"): No alertar por todo. Agrupar, usar severidades, definir bien los umbrales y duraciones (
for:en Prometheus).Documentación (Runbooks): ¿Qué hacer cuando salta esta alerta?
Canales de Notificación: Slack, PagerDuty, email, etc.
Ejercicio Práctico: Configurar Alerta en Prometheus y Notificación:
Configurar Alertmanager (si no está en
docker-compose.yml):
Y un alertmanager.yml básico (para Slack, necesitarás un webhook URL real):
Indicar a Prometheus dónde está Alertmanager (
prometheus.yml):
Crear archivo
alert.rules.yml:
(Nota: http_server_requests_seconds_count es una métrica estándar que OTEL podría generar para instrumentación HTTP. Asegúrate que los nombres de métricas y labels coincidan con lo que tu app exporta).
Reiniciar
docker-compose(Prometheus y Alertmanager).Simular Errores para Disparar la Alerta:
Generar varias peticiones que fallen al endpoint
/checkoutde tu app Node.js:
O si tienes un endpoint
/errorque siempre da 500:
Verificar Alertas:
En Prometheus UI (
http://localhost:9090/alerts). Debería pasar de PENDING a FIRING.En Alertmanager UI (
http://localhost:9093).En tu canal de Slack (si lo configuraste).
6. Ejercicio Integrado: Debugging Distribuido de un Problema Real
Escenario del Problema (Guiado por el instructor):
"Los usuarios reportan que el endpoint
/api/v1/user/:id/profileestá extremadamente lento a veces, e incluso da timeouts."Este endpoint en el
ServicioA(Node.js) internamente llama a:ServicioB(Node.js) para obtener datos básicos del usuario (/users/:id).ServicioC(Node.js) para obtener el historial de compras (/users/:id/orders).ServicioD(externo, legacy) para obtener preferencias de marketing (/marketing/:email/prefs).Todos los servicios están instrumentados con OpenTelemetry y envían trazas a Tempo, métricas a Prometheus y logs a Loki.
Pasos para los Alumnos (trabajando juntos o individualmente):
Identificar la Métrica Afectada (Grafana/Prometheus):
¿Qué métrica buscarían? (Ej:
http_server_requests_seconds_bucket{path="/api/v1/user/:id/profile", service_name="servicio-a"}).Visualizar P95 o P99 de latencia. Confirmar el problema.
Buscar correlación con tasas de error si las hay.
Encontrar Trazas Relevantes (Grafana/Tempo):
Desde el dashboard de métricas, ¿cómo pivotarían a trazas? (Idealmente, un dashboard que linkee traceIDs o permita filtrar por tiempo y servicio).
Si no hay link directo, usar el explorador de Tempo. Buscar trazas para
service_name="servicio-a"conhttp.target="/api/v1/user/:id/profile"que sean lentas (ordenar por duración) o tengan errores.
Analizar la Traza (Grafana/Tempo):
Identificar el "critical path" de la traza.
¿Qué
spanestá tomando más tiempo? ¿Es enServicioA,B,CoD?¿Hay errores marcados en algún span? ¿Atributos (
tags) útiles?Suposición para el ejercicio: El
spande la llamada aServicioD(externo) es el que muestra una latencia muy alta y variable.
Correlacionar con Logs (Grafana/Loki):
De la traza/span problemático, obtener el
trace_id(yspan_idsi es útil).Ir a Loki en Grafana y buscar logs con ese
trace_id:{service_name="servicio-a", trace_id="<valor_del_trace_id>"}.¿Qué dicen los logs del
ServicioAjusto antes y después de llamar aServicioD? (Ej: "INFO: Calling Marketing Service D", "WARN: Marketing Service D call took 3500ms").¿Hay logs de timeout o de reintentos?
Crear un Dashboard Ad-Hoc (Opcional, si hay tiempo):
Un dashboard rápido en Grafana que muestre:
Latencia P99 del endpoint
/api/v1/user/:id/profile.Latencia P99 de la llamada externa a
ServicioD(si se tiene una métrica específica para ello, ej.http_client_requests_seconds_bucket{peer_service="servicio-d"}).Logs filtrados por
trace_idpara investigaciones rápidas.
Proponer un Fix o Mitigación (Discusión):
Basado en el hallazgo (ej.
ServicioDes lento):Corto plazo: Implementar un timeout más agresivo y un circuit breaker para
ServicioD. Cachear respuestas deServicioDsi los datos no son ultra-críticos en tiempo real. ¿Carga condicional de datos de marketing?Largo plazo: Hablar con el equipo de
ServicioDpara que mejoren su rendimiento o provean una API más eficiente. ¿ReemplazarServicioD?
Última actualización