M5 — Observabilidad
Outcome del módulo: cuando el servicio falla, lo ves en un dashboard antes de que alguien te avise. Sin esto, operás a ciegas.
Diferencia clave: monitoring = ver métricas que definiste de antemano. Observabilidad = poder responder preguntas nuevas sobre el sistema sin re-deployar, a partir de lo que emite.
Concepto 1 — Los 3 pilares (logs, métricas, traces)
Idea núcleo: tres señales complementarias. Logs = qué pasó (evento). Métricas = cuánto/cuántos (agregado). Traces = por dónde pasó una request (recorrido).
Entender (capa 1)
Texto:
- Logs: eventos discretos con contexto. En prod: estructurados (JSON), no
printni texto libre — para poder filtrar/consultar. - Métricas: números agregados en el tiempo (requests/seg, latencia p95, error rate). Baratas de almacenar, ideales para dashboards y alertas.
- Traces: el camino de UNA request a través de servicios, con timing por tramo (span). Responde “¿dónde se fue el tiempo?”.
Visual:
flowchart TD
Q[¿qué pregunta respondo?] --> L[Logs<br/>¿qué pasó exactamente aquí?]
Q --> M[Métricas<br/>¿cuánto/con qué frecuencia?]
Q --> T[Traces<br/>¿por dónde pasó y dónde tardó?]
Video: Observability Explained | Logs, Metrics & Traces (The Three Pillars) — SystemDR
Ejemplo (log plano → estructurado):
# ❌ imposible de consultar/filtrar en agregado
print(f"user {uid} pagó {amount}")
# ✅ estructurado: cada campo es consultable
import structlog
log = structlog.get_logger()
log.info("payment_succeeded", user_id=uid, amount=amount, currency="COP")
Fijar (capa 2)
Nota atómica:
- Front: ¿cuándo mirás logs, métricas o traces?
- Back: métricas para detectar QUE algo anda mal (error rate sube); traces para ver DÓNDE (qué servicio/tramo tarda o falla); logs para el detalle de QUÉ pasó exactamente en ese punto. Se usan en cascada.
Feynman: “Las métricas son el tablero del auto (velocidad, temperatura): ves que algo sube. El trace es el GPS de tu viaje: por dónde fuiste y dónde te trabaste. Los logs son el diario detallado de cada parada.”
Aplicar (capa 3)
Convertí los print de un servicio a logs estructurados con structlog. Emití una métrica de contador (ej: pagos exitosos) y consultala.
Límites
- Logs son caros a volumen; no loguees todo en INFO en hot paths. Niveles + sampling.
- Nunca loguees secretos/PII (cruza con M4).
Concepto 2 — OpenTelemetry (el estándar)
Idea núcleo: OTel es el estándar vendor-neutral para instrumentar las 3 señales una sola vez y exportarlas a cualquier backend (Grafana, Jaeger, Datadog…).
Entender (capa 1)
Texto: instrumentás con la API de OpenTelemetry (spans, métricas, logs con contexto) y configurás un exporter. Cambiás de herramienta de visualización sin re-instrumentar. Un span representa una operación con inicio/fin; los spans se anidan formando el trace; el contexto se propaga entre servicios (trace-id) para seguir la request de punta a punta.
Visual:
flowchart LR
CODE[app instrumentada con OTel SDK] --> COL[OTel Collector] --> B1[Grafana/Tempo]
COL --> B2[Jaeger]
COL --> B3[otro backend]
Video: OpenTelemetry & Python: Manual Instrumentation for Beginners — Adam Gardner
Ejemplo:
from opentelemetry import trace
tracer = trace.get_tracer(__name__)
def checkout(cart):
with tracer.start_as_current_span("checkout") as span:
span.set_attribute("cart.items", len(cart))
with tracer.start_as_current_span("charge_payment"):
charge(cart) # span anidado: se ve su tiempo aparte
Fijar (capa 2)
Nota atómica:
- Front: ¿qué es un span y cómo se forma un trace?
- Back: un span = una operación con timing y atributos. Los spans se anidan (padre/hijo) y comparten un trace-id; ese árbol de spans = el trace, que muestra el recorrido y dónde se fue el tiempo en una request.
Feynman: “El trace es la factura detallada de un viaje: cada span es un tramo con su costo de tiempo. Ves que el viaje total fue 2s y que 1.8s se fueron en un solo tramo (la DB).”
Aplicar (capa 3)
Instrumentá un endpoint con OTel: un span padre + un span anidado para la llamada a DB. Verificá en el visualizador que ves el desglose de tiempo por tramo.
Límites
- Instrumentar todo genera overhead y ruido; empezá por los endpoints/servicios críticos y usá sampling en alto volumen.
Concepto 3 — Métricas: Prometheus, Grafana, Sentry
Idea núcleo: Prometheus recolecta métricas, Grafana las grafica, Sentry captura errores con contexto.
Entender (compacto):
- Prometheus: modelo pull (scrapea
/metrics); tipos: counter (sube), gauge (sube/baja), histogram (distribución, p50/p95/p99). - Grafana: dashboards sobre Prometheus (y otros); paneles de latencia, throughput, errores.
- Sentry: captura excepciones con stacktrace + contexto (request, user, release); ideal para el “qué se rompió” a nivel error.
- Las 4 golden signals (SRE): latencia, tráfico, errores, saturación.
from prometheus_client import Counter
payments = Counter("payments_total", "pagos", ["status"])
payments.labels(status="success").inc()
Video: How to set up Prometheus monitoring for your services — Google Cloud Tech Nota atómica: Front: ¿counter, gauge o histogram para latencia? Back: histogram — captura la distribución y permite calcular percentiles (p95/p99), que es lo que importa en latencia (el promedio miente). Counter para conteos monótonos, gauge para valores que suben y bajan (memoria, conexiones). Feynman: “El promedio de latencia es como decir ‘en promedio el restaurante atiende rápido’ mientras 1 de cada 20 clientes espera una hora. El p99 te muestra a ese cliente furioso.” Aplicar: exponé métricas Prometheus en un servicio, graficá latencia p95 y error rate en Grafana. Integrá Sentry y provocá una excepción para verla capturada. Límites: demasiadas labels de alta cardinalidad (ej: user_id) explotan Prometheus; labels acotadas.
Concepto 4 — SLO / SLI / error budget
Idea núcleo: definir “estar sano” con números. SLI = la medida. SLO = el objetivo. Error budget = cuánto podés fallar antes de frenar features.
Entender (capa 1)
Texto:
- SLI (Indicator): la métrica real, ej ”% de requests < 300ms” o ”% de requests sin error”.
- SLO (Objective): el target sobre el SLI, ej “99.9% de requests OK en 30 días”.
- Error budget: 100% − SLO. Con 99.9%, tu presupuesto de fallo es 0.1% (~43 min/mes). Si lo gastás, se frena el lanzamiento de features y se prioriza estabilidad.
Visual:
flowchart LR
SLI[SLI · % requests OK medido] --> SLO[SLO · objetivo 99.9%]
SLO --> EB[Error budget · 0.1% = 43min/mes]
EB --> DEC{¿budget gastado?}
DEC -->|sí| FREEZE[frenar features · estabilizar]
DEC -->|no| SHIP[seguir shippeando]
Video: SLO vs SLI vs SLA vs Error Budget | Google SRE in Plain English — Tech Tutorials with Piyush
Fijar (capa 2)
Nota atómica:
- Front: ¿qué es el error budget y para qué sirve?
- Back: es 100% − SLO: cuánta falla te podés permitir en el período. Sirve para decidir objetivamente: si aún hay budget, shippeás features; si lo gastaste, frenás y priorizás estabilidad. Convierte “confiabilidad” en una decisión con número, no discusión.
Feynman: “El error budget es el saldo de una tarjeta de ‘permiso para fallar’. Mientras te quede saldo, gastás en features nuevas. Si lo agotás, no comprás más hasta reponerlo estabilizando.”
Aplicar (capa 3)
Definí 1 SLI (ej: latencia < 300ms) y 1 SLO (99%) para un servicio. Calculá su error budget mensual y armá el cálculo de consumo actual.
Límites
- 100% de uptime es un anti-objetivo (imposible y carísimo); el SLO se fija según lo que el usuario realmente necesita, no “lo más alto posible”.
Concepto 5 — Alerting que sirve
Idea núcleo: alertar sobre síntomas del usuario, no sobre causas internas. Una alerta que no requiere acción es ruido que entrena a ignorar.
Entender (compacto):
- Alertá sobre SLO en riesgo (latencia/errores que ve el usuario), no sobre “CPU al 80%” (puede ser normal).
- Toda alerta debe ser accionable y linkear al runbook.
- Evitá alert fatigue: pocas alertas, importantes; el resto son dashboards.
flowchart TD
A{¿esto degrada la experiencia del usuario AHORA?} -->|sí| PAGE[alerta accionable + runbook]
A -->|no| DASH[dashboard, no alerta]
Nota atómica: Front: ¿sobre qué se debe alertar? Back: sobre síntomas que afectan al usuario (error rate, latencia, SLO en riesgo), no sobre causas internas (CPU, memoria) que no siempre implican problema. Cada alerta debe ser accionable y tener runbook; lo demás va a dashboard. Feynman: “Alertar por CPU alta es como que suene la alarma de incendio cada vez que prendés la estufa. Alertás cuando hay humo donde no debe (el usuario sufre), no por cada uso normal.” Aplicar: configurá 1 alerta sobre error rate (síntoma) con umbral y un runbook de 3 pasos. Provocá el fallo y verificá que dispara. Límites: umbrales muy sensibles = fatiga; muy laxos = te enterás tarde. Se calibran con datos reales.
Checklist de dominio M5
Marcás cuando podés explicar (Feynman) + aplicar:
- 3 pilares (logs estructurados / métricas / traces)
- OpenTelemetry (spans, traces, propagación de contexto)
- Prometheus + Grafana + Sentry (counter/gauge/histogram, golden signals)
- SLO / SLI / error budget
- Alerting accionable (síntomas, no causas)
Salida verificable del módulo: un servicio instrumentado con OTel (logs estructurados + 1 métrica histogram + 1 trace con span anidado), un dashboard con latencia p95 y error rate, 1 SLO definido con su error budget, y 1 alerta accionable que dispara al provocar un fallo.