Observabilidad para microservicios: métricas, traces y logs que realmente importan
847 alertas en una semana
Eso es lo que recibía el equipo de operaciones de un cliente cuando empezamos a trabajar con ellos. 847 alertas en 7 días. El resultado predecible: las ignoraban todas. Cuando una alerta real surgió (un servicio de pagos con latencia degradada que estaba causando timeouts para un 12% de los clientes), tardó 4 horas en detectarse. No porque no hubiera una alerta. Había 23 alertas relacionadas. Pero estaban enterradas en un mar de ruido.
Ese escenario es el resultado directo de confundir monitorización con observabilidad. Monitorizar es recoger datos. Observar es entender el sistema. La diferencia no es semántica. Es operativa. Y tiene un coste medible en downtime, en horas de ingeniería perdidas, y en clientes que se van sin decir por qué.
Qué métricas instrumentar (y cuáles ignorar)
El instinto natural es instrumentar todo. CPU, memoria, disco, red, latencia de cada endpoint, tasa de error de cada servicio, longitud de cada cola. El resultado es un dashboard con 200 paneles que nadie mira y un sistema de alertas que genera 847 notificaciones semanales.
La alternativa: empezar por las cuatro señales doradas de Google SRE.
Latencia. Tiempo que tarda una petición en completarse. Pero no la media. La media es mentirosa. Un servicio con latencia media de 120ms puede tener un p99 de 3.2 segundos, lo que significa que 1 de cada 100 usuarios espera más de 3 segundos. Instrumentamos p50, p95, y p99. El p50 nos dice como va el usuario típico. El p99 nos dice como van los usuarios que peor lo pasan. Si el p99 se dispara pero el p50 se mantiene, tenemos un problema que afecta a pocos usuarios pero de forma severa.
Y hay un detalle crítico: medir latencia por separado para peticiones exitosas y fallidas. Las peticiones que devuelven un error 500 a menudo son rápidas (el servicio falla rápido). Si las mezclas con las exitosas, la latencia media baja cuando hay más errores. Counterintuitivo y peligroso.
Tráfico. Peticiones por segundo. Pero desglosado por tipo de operación, no agregado. El tráfico de lectura y el de escritura tienen perfiles completamente diferentes. Un pico de lecturas puede ser normal (campaña de marketing, hora punta). Un pico de escrituras puede ser anómalo (un script descontrolado, un ataque, un loop en un microservicio).
Errores. Tasa de errores como porcentaje del tráfico total. No número absoluto. 500 errores por hora suena terrible. 500 errores por hora con 2 millones de peticiones por hora es una tasa del 0.025%, que probablemente está dentro de tu SLO. 500 errores por hora con 10,000 peticiones por hora es un 5%, y eso es una crisis.
Saturación. Cuánto de la capacidad del servicio está en uso. CPU, memoria, conexiones a base de datos, goroutines, threads, lo que sea el recurso limitante de tu servicio particular. La saturación es la métrica predictiva: te dice cuando vas a tener un problema, no cuando ya lo tienes.
Esas cuatro métricas, bien instrumentadas, cubren el 80% de las necesidades de observabilidad. Todo lo demás es contexto adicional para diagnóstico, no para alerting.
Distributed tracing: la pieza que cambia todo
Imagina una petición de un usuario que pasa por el API gateway, luego al servicio de autenticación, luego al servicio de pedidos, que llama al servicio de inventario, que consulta la base de datos, que genera un evento en Kafka, que es consumido por el servicio de facturación. Siete servicios. Si la petición tarda 4 segundos, dónde está el cuello de botella?
Sin tracing distribuido, la respuesta es: no tenemos idea. Cada servicio tiene sus propios logs. Correlacionar los logs de siete servicios para una petición individual es un ejercicio manual que lleva 30 minutos como mínimo. Y si tienes miles de peticiones por minuto, encontrar la que falló es buscar una aguja en un pajar.
Con tracing distribuido (OpenTelemetry, que es el estándar de facto), cada petición recibe un trace ID que la sigue a través de todos los servicios. Cada paso dentro de un servicio genera un span con su duración, sus atributos, y su relación con el span padre. El resultado es un árbol de llamadas que te muestra exactamente dónde se gastó el tiempo.
Implementamos tracing con OpenTelemetry SDK en cada servicio. Los traces se envían a un collector (OpenTelemetry Collector) que los exporta a Jaeger o Tempo. En producción, no tracemos el 100% de las peticiones. Tracemos un 10% con muestreo probabilístico, más un 100% de las peticiones que devuelven error, más un 100% de las peticiones con latencia superior al p95. Eso nos da suficiente cobertura para diagnosticar problemas sin el coste de almacenar traces de cada petición.
Correlación con métricas de negocio
Aquí es donde el tracing deja de ser una herramienta de infra y se convierte en una herramienta de negocio.
Añadimos atributos de negocio a los spans. No solo el endpoint y el método HTTP. El ID del cliente, el tipo de operación (compra, devolución, consulta), el valor monetario de la transacción. Con esos atributos, podemos responder preguntas como: los clientes premium experimentan la misma latencia que los estándar? Las transacciones de alto valor tienen más errores? La degradación de latencia del servicio de inventario está afectando a las ventas?
Un ejemplo real: detectamos que el 8% de las peticiones al servicio de pagos con tarjeta tenían una latencia superior a 5 segundos. Sin correlación de negocio, eso era “un problema de rendimiento”. Con correlación, descubrimos que el 100% de esas peticiones lentas eran pagos con tarjeta internacional procesados por una pasarela de pagos secundaria. El problema no era nuestro servicio. Era el timeout del proveedor externo. La solución fue aumentar el timeout y mostrar un spinner al usuario, no optimizar nuestro código.
Sin los atributos de negocio en el trace, habríamos pasado días optimizando un servicio que no era el problema.
Logs: menos es más
Los logs son la señal de observabilidad más antigua y la más abusada. La mayoría de equipos logean demasiado. Un servicio que genera 500 MB de logs por hora está generando ruido, no información.
Nuestras reglas para logging efectivo:
Structured logging siempre. JSON, no texto libre. Un log como {"level":"error","service":"payments","trace_id":"abc123","error":"timeout","gateway":"secondary","latency_ms":5200} es buscable, filtrable, y parseable. Un log como ERROR: Payment failed after 5.2 seconds on secondary gateway requiere regex para extraer datos. En producción, con millones de líneas, la diferencia es crítica.
Un evento, un log. No tres logs para una operación: “Starting payment processing”, “Payment sent to gateway”, “Payment completed”. Un solo log al final con el resultado y los datos relevantes: éxito o fallo, duración, gateway utilizada, importe. Los logs intermedios son útiles en desarrollo. En producción, son ruido.
Log levels con disciplina. ERROR es algo que requiere acción humana inmediata. WARN es algo que podría convertirse en error si no se resuelve. INFO son eventos de negocio significativos (pedido creado, pago procesado, usuario registrado). DEBUG solo se activa temporalmente para diagnosticar un problema específico y se desactiva después.
Hemos reducido el volumen de logs de clientes entre un 60% y un 80% sin perder información relevante. El resultado: búsquedas más rápidas en Loki/Elasticsearch, facturas de almacenamiento más bajas, y operadores que pueden encontrar la información que necesitan en segundos en vez de minutos.
Alerting: la parte que todo el mundo hace mal
Volvamos a las 847 alertas semanales. Cómo se llega ahí?
Se llega alertando sobre síntomas en vez de sobre impacto al usuario. Una alerta de “CPU al 85%” no dice nada sobre si los usuarios están afectados. Puede que el servicio funcione perfectamente al 85% de CPU. Puede que falle al 60%. La CPU es un input, no un outcome.
Las alertas deben definirse en términos de SLOs (Service Level Objectives). Un SLO dice: “el 99.5% de las peticiones al servicio de pagos tendrán una latencia inferior a 2 segundos”. La alerta se dispara cuando el error budget se está consumiendo más rápido de lo esperado, no cuando una métrica individual cruza un umbral.
Implementamos alertas basadas en burn rate. Si tu SLO es 99.5% de disponibilidad mensual (equivalente a 3.6 horas de downtime permitido), y en las últimas 6 horas has consumido el 20% de tu error budget, la alerta se dispara. Eso te da tiempo de reaccionar antes de violar el SLO, pero no te despierta a las 3 de la mañana porque un servicio tuvo 5 errores en un minuto.
Resultado para el cliente de las 847 alertas: redujimos a 12-15 alertas semanales. Cada una requería atención. La tasa de falsos positivos bajó del 94% al 8%. El MTTR (Mean Time To Resolve) bajó de 4 horas a 22 minutos, porque cuando sonaba una alerta, los ingenieros sabían que era real y tenían el trace ID en la notificación para empezar a diagnosticar inmediatamente.
El stack que recomendamos
Después de implementar observabilidad en una docena de entornos de microservicios, este es el stack que converge para empresas medianas:
Métricas: Prometheus + Grafana. Open source, maduro, ecosistema enorme de exporters. Para quien no quiera operar Prometheus, Grafana Cloud ofrece Prometheus-as-a-service con un tier gratuito generoso.
Traces: OpenTelemetry + Tempo (o Jaeger). OpenTelemetry como SDK de instrumentación es no-negociable: es el estándar, tiene soporte en todos los lenguajes, y es vendor-neutral. Tempo como backend de traces si ya usas Grafana. Jaeger si prefieres algo independiente.
Logs: Loki + Grafana. Loki es significativamente más barato que Elasticsearch para logs porque no indexa el contenido completo, solo las etiquetas. Para búsquedas full-text frecuentes, Elasticsearch sigue siendo superior. Pero para la mayoría de casos de uso de logs en producción, Loki es suficiente y cuesta una fracción.
Alerting: Grafana Alerting con SLOs definidos en Prometheus. Alertas basadas en burn rate, no en umbrales estáticos.
El coste total de operar este stack para un entorno de 15-20 microservicios está entre 400 y 800 euros/mes si lo autogestionas, o entre 600 y 1,200 euros/mes en Grafana Cloud. Comparado con Datadog (que para el mismo volumen puede costar 3,000-5,000 euros/mes), es una diferencia significativa.
Datadog es un producto excelente. Pero para una empresa mediana, el coste escala de forma agresiva con el volumen de datos. Y el volumen de datos de observabilidad crece más rápido de lo que esperas.
Dónde empezar
Si tu sistema de microservicios no tiene observabilidad o tiene la variante “monitorización básica con demasiadas alertas”, el plan de implementación es:
Semana 1-2: Instrumentar las cuatro señales doradas con Prometheus en los 3-5 servicios más críticos. Crear un dashboard en Grafana con p50/p95/p99 de latencia, tasa de error, y tráfico por servicio.
Semana 3-4: Implementar tracing con OpenTelemetry en esos mismos servicios. Configurar muestreo al 10% con 100% para errores y latencia alta. Desplegar Tempo o Jaeger.
Semana 5-6: Definir SLOs para los servicios críticos. Crear alertas basadas en burn rate. Eliminar todas las alertas de umbral estático existentes.
Semana 7-8: Consolidar logs en Loki. Migrar a structured logging. Aplicar las reglas de “un evento, un log” y reducir el volumen.
Es un esfuerzo de dos meses para un equipo de 2-3 ingenieros trabajando a tiempo parcial. El retorno es inmediato: la primera incidencia que diagnosticas en 20 minutos en vez de 4 horas paga la inversión.
Para equipos que necesitan ayuda con la implementación, nuestros servicios de cloud y DevOps incluyen observabilidad como componente estándar. Porque un sistema que no puedes observar es un sistema que no puedes operar. También puedes revisar cómo la observabilidad conecta con las estrategias de despliegue sin downtime y con el testing en producción.
