From n00b to ZeroCool / Profesionalización
Observabilidad sin dolor: logs, métricas y trazas para no estar ciego
Guía práctica de observabilidad con logs, métricas y trazas: qué medir, cómo instrumentar con OpenTelemetry y errores comunes para sobrevivir producción.
Lo que vale la pena leer aquí
Tu sistema está “bien”… hasta que no.
Tu sistema está “bien”… hasta que no.
Viernes, 6:40 pm. Ya traes el mindset de cerrar la laptop (la vieja que ya suena como jet), pedir tacos y hacerte el loco con el backlog. Entra el Slack: “Oye, se cayó el checkout”.
Abres el dashboard que alguien dejó “bonito” hace meses: CPU normal, RAM normal, el cluster todo verde. Pero la gente no puede pagar, el soporte está ardiendo y tu jefe ya quiere un ETA. Esa sensación es real: estás viendo production con los ojos vendados.
Eso no es falta de ganas. Es falta de observabilidad bien armada: datos que te dejen entender qué pasó, dónde se atoró y por qué… sin apostar a la suerte.
Qué te vas a llevar
- Diferencia útil entre logs, métricas y trazas (y para qué NO sirven).
- Un workflow aterrizado para instrumentar sin convertirlo en proyecto infinito.
- Cómo aplicarlo a Kubernetes, microservicios o ese monolito que vive a base de pull requests a la carrera.
- Errores que cuestan horas (y credibilidad) y cómo evitarlos.
“Tenemos monitoreo” no significa que ves
Monitoreo típico: “CPU al 80% → alerta”. Eso ayuda… cuando el problema es infraestructura.
Pero muchos incidentes son lógicos: timeouts, colas saturadas, un release con un bug, un proveedor lento, un query sin índice. Ahí la CPU puede estar relax mientras el negocio se quema.
Observabilidad es poder contestar preguntas que ni sabías que ibas a tener:
- “¿Por qué solo los usuarios de cierto banco no pueden pagar?”
- “¿Qué endpoint subió el p95 y en qué servicio se está atorando?”
- “¿Desde qué deploy empezó el desmadre y qué cambio lo detonó?”
Piénsalo como un triángulo que se complementa:
- Métricas: salud y tendencias (detectas rápido).
- Logs: contexto y evidencia (entiendes el “qué pasó”).
- Trazas: recorrido end-to-end (encuentras el “dónde se atoró”).
Puedes sobrevivir con una sola… hasta que te toque el incidente en viernes, el CTO pidiendo updates en un hilo y tu proveedor de pagos en “degradación parcial”.
Arma observabilidad que sí sirva (sin volverte SRE full-time)
1) Empieza por preguntas, no por herramientas
Antes de instalar Prometheus “porque todos lo usan”, define 3–5 preguntas operativas que te duelan de verdad:
- Disponibilidad: “¿Está respondiendo el servicio?”
- Performance real: “¿Cuál es el p95/p99 de latencia por endpoint?”
- Errores: “¿Qué porcentaje de requests falla y por qué?”
- Dependencias: “¿Qué downstream está causando timeouts?”
- Negocio (si aplica): “¿Cuántos checkouts exitosos por minuto?”
Esa lista es la vacuna contra dashboards bonitos pero inútiles.
2) Métricas: pocas, consistentes y con intención
Arranca con lo que casi siempre paga desde el primer incidente:
- RED (para servicios HTTP):
- Rate: requests/seg
- Errors: % de 5xx/4xx relevantes
- Duration: latencias p50/p95/p99
- USE (para infraestructura):
- Utilization, Saturation, Errors (CPU, memoria, IO, etc.)
En Kubernetes, “CPU alta = problema” es una simplificación peligrosa. Un servicio puede estar lento por:
- pool de conexiones agotado
- pausas de GC
- downstream lento
- locks
- un query sin índice
Decisión práctica: en tu primer sprint, comprométete a un tablero mínimo y usable:
- Latencia p95 por ruta crítica
- Error rate por ruta crítica
- Throughput
- Un objetivo tipo SLO visible (aunque sea interno)
3) Logs: buscables, correlacionables y (sobre todo) baratos
Loggear “todo” suena bien hasta que llega la factura o se llena el storage. Mejor haz logs que puedas usar en corto.
Reglas de oro
- JSON estructurado (no puro texto): para filtrar sin sufrir.
- Niveles claros:
INFO,WARN,ERROR. - Sin PII: no metas tarjetas, emails completos, tokens, addresses. Neta.
- Loggea eventos con campos, no con novelas.
Campos mínimos que sí ayudan
service.nameenvironment(prod/stage)trace_idyspan_id(para ligar con trazas)http.method,http.route,http.status_codeduration_mserror.type,error.message(ojo con mensajes gigantes)
Ejemplo de log estructurado:
{
"timestamp": "2026-08-18T01:24:11.123Z",
"level": "ERROR",
"service": "payments-api",
"environment": "prod",
"http": {"method": "POST", "route": "/checkout", "status_code": 502},
"duration_ms": 1840,
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"error": {"type": "UpstreamTimeout", "message": "gateway timeout calling acquirer"},
"deploy": {"version": "1.12.3", "git_sha": "a1b2c3d"}
}
Decisión práctica: política simple para no ensuciar tu stack:
INFO: eventos útiles (inicio de request NO, pero sí “pago autorizado”, “pedido creado”).WARN: cosas raras recuperables.ERROR: fallas que rompen flujo.
Y pon retención realista. Con presupuesto latino, suele ser mejor 7–14 días de logs buenos que 90 días de ruido caro.
4) Trazas: el mapa cuando todo está “bien” pero no funciona
Las trazas responden la pregunta que te mata en incidentes:
- “¿En qué parte exacta se fue el tiempo?”
Si tienes:
- API → Service A → Service B → DB → proveedor externo
…la traza te dibuja el árbol de spans con tiempos por tramo. Sin eso, te la pasas adivinando y haciendo rollback “por si acaso”.
Lo mínimo para que sea útil:
- Propagación de contexto (traceparent)
- Spans por request y por llamadas a dependencias (HTTP/DB)
- Sampling razonable (no todo al 100% en prod)
5) OpenTelemetry: una instrumentación, varios backends
Si estás arrancando o quieres estandarizar, OpenTelemetry (OTel) es el camino: instrumentas una vez y mandas datos a Prometheus/Grafana, Jaeger, Tempo, Elastic, Datadog, New Relic, etc.
Arquitectura típica (cloud-native):
- App instrumentada con OTel SDK / auto-instrumentation
- OTel Collector (DaemonSet/Deployment en Kubernetes)
- Exporters hacia tu stack (metrics/traces/logs)
Tradeoff real:
- OTel te da flexibilidad, pero agrega una pieza (Collector) que también debes observar. Si el Collector se cae, te quedas ciego otra vez.
6) Implementación rápida con OpenTelemetry en un servicio Node.js
Supongamos un API con Express. Objetivo: trazas + métricas básicas + logs correlacionables.
Paso 6.1: Dependencias
npm i @opentelemetry/api \
@opentelemetry/sdk-node \
@opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-trace-otlp-http \
@opentelemetry/exporter-metrics-otlp-http \
pino pino-http
Paso 6.2: Crea telemetry.js
// telemetry.js
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http');
const traceExporter = new OTLPTraceExporter({
url: process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
});
const metricExporter = new OTLPMetricExporter({
url: process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
});
const sdk = new NodeSDK({
serviceName: process.env.OTEL_SERVICE_NAME || 'payments-api',
traceExporter,
metricExporter,
instrumentations: [getNodeAutoInstrumentations()],
});
sdk.start();
Paso 6.3: Inicia la telemetría antes de tu app
// index.js
require('./telemetry');
const express = require('express');
const pinoHttp = require('pino-http');
const app = express();
app.use(pinoHttp());
app.post('/checkout', async (req, res) => {
// tu lógica...
res.json({ ok: true });
});
app.listen(3000);
Paso 6.4: Variables de entorno mínimas
export OTEL_SERVICE_NAME=payments-api
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://otel-collector:4318/v1/traces
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=http://otel-collector:4318/v1/metrics
Decisión práctica: si el primer deploy con telemetría te sube latencia o costos, baja sampling y revisa instrumentations que estén demasiado verbosas.

7) Kubernetes: Collector básico y una ruta clara de datos
En K8s normalmente usas el OpenTelemetry Collector. Conceptualmente (sin casarte con vendor) la cosa va así:
receivers: otlp (HTTP/gRPC)processors: batch + memory_limiterexporters: tempo/jaeger para trazas, prometheus remote write para métricas, y logs a tu stack
Punto clave: ponle límites. Un Collector sin memory_limiter es como microondas sin timer: parece útil… hasta que se te quema todo.
Tradeoff real:
- DaemonSet: más cerca de los pods (menos latency, más consumo distribuido).
- Deployment: más simple, pero puede volverse cuello de botella.
Si tu cluster es chico (típico startup con budget apretado), empieza con Deployment bien dimensionado y escala cuando los datos te lo pidan.
8) Alertas que no te despierten por tonterías
La banda odia alertas porque casi siempre están mal: disparan por ruido y no te dicen qué hacer.
Hazlas accionables:
- Alerta por síntoma, no por causa:
- p95 > X por 10 min
- error rate > Y%
- saturación de cola
- Define severidad:
SEV1: usuarios no pueden comprarSEV2: degradación fuerteSEV3: se investiga en horario hábil
Tip de guerra: si una alerta no viene con “qué veo” y “qué hago”, es spam con esteroides.
Screenshots sugeridos
- Dashboard en Grafana con paneles RED por endpoint (
/checkout,/login). - Vista de traza en Jaeger/Tempo mostrando un request con spans: API → DB → proveedor.
- Ejemplo de log JSON en tu agregador (Elastic/Loki/Cloud Logging) filtrando por
trace_id. - Pantalla de alertas: regla de error rate + enlace a runbook.
- Comparación antes/después: latencia p95 y error rate tras un deploy.
Errores comunes + solución
1) “Tenemos logs, ya con eso”
Síntoma: encuentras el error, pero no sabes impacto ni frecuencia.
Solución: agrega métricas RED para magnitud y tendencias. Logs te dicen el “qué”, métricas el “cuánto”.
2) Métricas sin etiquetas útiles (o con etiquetas peligrosas)
Síntoma: no puedes segmentar por endpoint o servicio… o tu Prometheus se muere por cardinalidad.
Solución: usa etiquetas controladas (route, status_code, service). Evita user_id, order_id, etc.
3) Trazas sin propagación de contexto
Síntoma: cada servicio muestra trazas separadas; no hay historia completa.
Solución: asegura headers traceparent/tracestate entre servicios y en gateways/ingress.
4) Sampling mal puesto
Síntoma: no ves el incidente porque justo no se muestreó… o se te dispara la factura.
Solución:
- head sampling bajo en general (ej. 1–10%)
- tail sampling para errores y high latency (en Collector si puedes)
5) Dashboards bonitos, cero decisiones
Síntoma: la gráfica se ve cool, pero nadie la usa en el jale.
Solución: cada dashboard debe responder una pregunta operativa y apuntar a una acción (runbook, query de logs, vista de trazas).

Checklist final
- Tengo métricas RED (Rate/Errors/Duration) por ruta crítica.
- Tengo logs estructurados (JSON) con
trace_idy campos consistentes. - Tengo trazas end-to-end con propagación de contexto entre servicios.
- Mis alertas están basadas en síntomas (latencia/error rate) y tienen severidad.
- Existe un runbook mínimo: “si pasa X, revisa Y, ejecuta Z”.
- Retención y sampling definidos (costos bajo control).
- Puedo ir de una alerta → dashboard → traza → logs sin llorar.
FAQ
1) ¿Qué va primero: logs, métricas o trazas?
Métricas primero para detectar y dimensionar. Luego trazas para ubicar cuellos de botella. Y logs estructurados para evidencia fina. En la práctica iteras, pero no te cases con “solo logs”.
2) ¿Observabilidad es lo mismo que monitoreo?
No. Monitoreo te dice “algo anda mal” (y a veces ni eso). Observabilidad te deja entender “qué”, “dónde” y “por qué” con datos correlacionados.
3) ¿Cuánto sampling debo usar en trazas?
Depende del tráfico. Un arranque razonable: 1–10% en prod, y conserva 100% de errores o high-latency con tail sampling si puedes.
4) ¿Cómo evito que los logs se vuelvan carísimos?
Estructura + niveles bien usados + retención corta. Evita loggear payloads completos. Si necesitas payload, guarda hashes/IDs y reconstruye desde DB o eventos.
5) ¿Qué stack recomiendan para empezar sin vender el riñón?
OpenTelemetry + Grafana (Prometheus para métricas y Tempo/Jaeger para trazas) + Loki/Elastic para logs. Ajústalo a tu infraestructura y, sobre todo, a quién lo va a operar de verdad.
Siguiente episodio: teaser
Una vez que ya ves, toca responder rápido: SLOs, error budgets y cómo decidir cuándo frenar releases sin pelearte con producto.
Spoiler: no es “ser aguafiestas”. Es evitar que production te cobre la factura con intereses.
Idea para cerrar bien este post: toma una sola práctica de aquí y conviértela en algo que tu equipo pueda aplicar hoy.
Cuando un artículo aterriza en decisiones reales, deja de ser contenido y se vuelve ventaja.


