Estás lanzando un servicio completamente nuevo: diseña su stack de observabilidad desde cero
Logs, métricas y trazas son tres compras separadas hasta que las conectas con un trace_id y un SLO — esta es la pregunta capstone que evalúa si sabes hacerlo.
APRENDE HACIENDOPon a prueba tu intuición3 pasos
Estás lanzando un servicio completamente nuevo: diseña su stack de observabilidad desde cero
Usa los ejemplos y la explicación de la lección para comprobar tu idea.
Reflexión personal. No se envía a ningún servicio de IA.#Por qué esta pregunta es una favorita en el nivel senior
"Diseña la observabilidad para un servicio nuevo" es una pregunta de diseño de sistemas disfrazada de operaciones. Evalúa si piensas en la preparación para producción antes del primer incidente, si conoces la diferencia entre recolectar datos y poder actuar sobre ellos a las 3 de la madrugada, y si eres capaz de razonar sobre costo y relación señal-ruido en lugar de simplemente nombrar cada herramienta que has escuchado. Una buena respuesta recorre logging, métricas, trazado y alertas como un solo sistema conectado — no como cuatro compras separadas — y conecta explícitamente todo el conjunto con lo que realmente hace un ingeniero de guardia cuando lo llaman.
Los tres pilares clásicos de la observabilidad son logs, métricas y trazas. Una respuesta senior añade una cuarta capa, a menudo pasada por alto, que convierte señales crudas en algo sobre lo que un humano puede actuar: alertas construidas sobre SLOs y presupuestos de error, más el tooling de guardia que conecta todo. Así se construye todo esto, en orden, para un servicio completamente nuevo.
#Paso 1: Logging estructurado, desde el primer commit
El logging es la base porque es lo más barato de hacer bien desde temprano y lo más caro de agregar después. Cada línea de log que emite el servicio debe ser JSON estructurado con un esquema consistente: timestamp, level, service, environment y — algo crítico — trace_id y span_id inyectados por la instrumentación de trazado. Este único campo, trace_id, es lo que te permite pasar de "veo un error en los logs" a "muéstrame cada span de la petición exacta que produjo este error", que es el vínculo entre pilares más útil de todo el stack.
La disciplina en los niveles de log importa más de lo que la mayoría de los equipos admite: DEBUG para desarrollo local, INFO para eventos de negocio significativos (no cada entrada/salida de función), WARN para anomalías recuperables, ERROR para fallos que requieren atención. Un servicio que registra todo en INFO encarece el pipeline de agregación y hace imposible encontrar la señal entre el ruido. Los logs tampoco deben llevar nunca PII ni secretos en texto plano — una clave de API filtrada en una línea de log es un incidente de seguridad, no solo un problema de higiene.
#Paso 2: Métricas usando los métodos RED y USE
Las métricas responden "¿el sistema está sano, en conjunto, ahora mismo?" de forma barata y con alta resolución. Instrumenta el servicio con una librería cliente de Prometheus (u OpenTelemetry Metrics, que puede exportar a Prometheus o a un backend comercial) y expón un endpoint /metrics para el scraping. Dos marcos cubren casi todo lo que necesitas:
- RED (para servicios): Rate (tasa de peticiones), Errors (errores), Duration (duración/latencia, idealmente como histograma para poder calcular p50/p95/p99 y no solo un promedio que esconde la latencia de cola).
- USE (para recursos): Utilization (utilización), Saturation (saturación), Errors (errores) — CPU, memoria, pool de conexiones, profundidad de cola.
Estos se mapean directamente a las cuatro señales doradas del libro de SRE de Google: latencia, tráfico, errores y saturación. Construye un dashboard de Grafana por servicio usando exactamente estas cuatro señales como su fila superior, antes de añadir debajo cualquier métrica de negocio personalizada — un dashboard que empieza con quince métricas a medida y entierra la latencia y la tasa de errores es un dashboard que nadie puede usar durante un incidente.
#Paso 3: Trazado distribuido para ver a través de los límites de servicio
Una vez que una petición cruza más de un servicio, las métricas y los logs por sí solos no pueden mostrarte la forma del grafo de llamadas. Instrumenta el servicio con un SDK de OpenTelemetry, que propaga el contexto de traza mediante el header traceparent de W3C en cada llamada saliente HTTP/gRPC, de modo que un único trace_id une cada span de cada servicio que tocó la petición. Los spans se exportan a un OpenTelemetry Collector, que los distribuye hacia un backend de trazado — Jaeger, Grafana Tempo, o un APM comercial.
A cualquier escala real, no puedes registrar cada span de cada petición para siempre — el costo de almacenamiento y procesamiento es prohibitivo. Aquí es donde importa el muestreo (sampling): el muestreo basado en cabeza (head-based) decide si conservar una traza justo al inicio (barato, pero podrías descartar la única traza que necesitabas); el muestreo basado en cola (tail-based) almacena en buffer la traza completa y decide al final, lo cual te permite conservar deliberadamente el 100% de las trazas que fallaron o fueron lentas mientras muestreas hacia abajo las aburridas, rápidas y exitosas. El muestreo tail-based es operativamente más complejo (necesita un collector con buffer) pero te da las trazas que realmente importan para depurar, no solo una muestra aleatoria de tráfico mayormente sano.
#Paso 4: Alertas basadas en SLOs y presupuestos de error, no en umbrales estáticos
Este es el paso que separa un diseño senior de uno junior. Las alertas de umbral estático ("avisar si CPU > 80%") son ruidosas y no reflejan el impacto real en el usuario. El mejor enfoque: define un Service Level Indicator (SLI) — por ejemplo, la proporción de peticiones completadas exitosamente dentro de un objetivo de latencia — y un Service Level Objective (SLO) sobre él, como "99.9% de las peticiones tienen éxito en menos de 300ms, medido en una ventana móvil de 30 días". La brecha entre 100% y el SLO (0.1% aquí) es tu presupuesto de error (error budget) — la cantidad de "maldad" que te permites gastar antes de romper tu promesa a los usuarios.
Genera alertas por tasa de consumo (burn rate), no sobre el SLI crudo: qué tan rápido está consumiendo el servicio su presupuesto de error, en múltiples ventanas de tiempo (por ejemplo, una ventana rápida de 5 minutos para detectar una caída súbita, y una ventana más lenta de 1 hora para detectar una degradación persistente y de menor grado). Una alerta de ventana única y estática, o dispara con pequeños picos que se autorresuelven, o pasa por alto un problema de combustión lenta durante horas. Las alertas de múltiples ventanas y múltiples tasas de consumo avisan solo cuando el presupuesto realmente está en riesgo, lo cual reduce directamente la fatiga de alertas.
Enruta las alertas a través de Alertmanager (Prometheus) o un equivalente comercial, y luego hacia PagerDuty u Opsgenie para la programación de guardias, las políticas de escalamiento y la deduplicación. Cada aviso debería enlazar a un runbook — si un humano tiene que improvisar una respuesta desde cero a las 3 de la madrugada, la alerta no estaba lista para producción.
#Uniendo todo para la guardia
Lo importante de este diagrama no son los nombres de las herramientas — cambia Datadog, New Relic o Elastic por cualquier nodo y la forma no cambia. Lo importante es el camino de correlación: se dispara un aviso porque una alerta de burn rate sobre un SLO cruzó un umbral, el ingeniero de guardia abre Grafana y ve cuál señal dorada se movió, profundiza desde la métrica hacia las trazas específicas lentas o fallidas que comparten esa ventana de tiempo, y desde el trace_id de una traza salta directo a las líneas de log exactas de cada servicio que tocó esa petición — sin emparejar manualmente timestamps entre tres interfaces distintas. Ese camino de correlación, construido desde el día uno mediante la propagación de trace_id, es la diferencia entre un diagnóstico de 10 minutos y uno de 90.
#Trade-offs de costo y operación que vale la pena mencionar en voz alta
Un entrevistador va a valorar una respuesta que plantea trade-offs de forma proactiva en lugar de presentar un diseño de presupuesto ilimitado:
- Control de cardinalidad en métricas. Un label de Prometheus con valores no acotados (ID de usuario, URL cruda con parámetros de ruta) causa una explosión de cardinalidad y puede tumbar el propio backend de métricas — los labels deben mantenerse de baja cardinalidad (plantilla de ruta, clase de código de estado, no la ruta cruda).
- Estrategia de muestreo para trazas. Retener el 100% de las trazas rara vez es asequible pasado cierto volumen de peticiones; el muestreo tail-based sesgado hacia errores y peticiones lentas captura la mayor parte del valor de depuración a una fracción del costo.
- Volumen de logs y niveles de retención. Almacenamiento caliente para logs recientes, almacenamiento frío/archivo más barato para retención larga impulsada por cumplimiento normativo, y disciplina en los niveles de log para no pagar por almacenar ruido.
- La fatiga de alertas es un fallo de diseño, no un problema de ajuste. Si la guardia rutinariamente reconoce y descarta avisos sin actuar, los umbrales del SLO o las ventanas de burn rate están mal, no las personas.
🧠 Check your understanding
0/3 · 0/3 answered1. Un equipo define un SLO de "99.9% de las peticiones tienen éxito en menos de 300ms sobre una ventana móvil de 30 días". ¿Qué representa el 0.1% restante?
2. ¿Por qué suele preferirse el muestreo tail-based sobre el head-based para el trazado distribuido en un sistema con restricciones de costo?
3. ¿Qué combinación representa mejor el método RED para monitorear un servicio (a diferencia del método USE para un recurso)?