level=ERROR service=checkout: «Redis connection timeout». Falla Redis.| Métricas | Logs | Trazas | |
|---|---|---|---|
| Formato | Números agregados | Eventos discretos | Spans con tiempos |
| Cardinalidad | Baja | Alta | Media |
| Volumen y coste | Bajo | Alto | Medio (con muestreo) |
| Retención típica | Meses o años | Días o semanas | Días |
| Uso principal | Alertas, paneles | Depuración, auditoría | Cuello de botella |
Ir directo a los logs sin haber mirado una métrica es buscar sin saber qué se busca. Y la cardinalidad de la tabla explica por qué no se pueden intercambiar: meter un identificador de usuario como etiqueta de una métrica multiplica las series por el número de usuarios y revienta la factura. Ese dato pertenece a un log.
No estructurado, imposible de agregar:
Error processing payment for john@email.com - amount $99.99 failed with code 402
Estructurado, consultable:
{
"timestamp": "2026-01-19T15:30:00.123Z",
"level": "ERROR",
"service": "payment-api",
"version": "2.3.1",
"environment": "production",
"request_id": "req_abc123",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"user_id": "user_456",
"event": "payment_failed",
"error_code": "CARD_DECLINED",
"message": "Payment processing failed due to insufficient funds"
}
| No estructurado | Estructurado | |
|---|---|---|
| Búsqueda | Regex frágil | level="ERROR" AND user_id="user_456" |
| Agregación | Manual | Automática: errores por hora y servicio |
| Alertas | Sobre texto | Sobre campos concretos |
| Correlación | Imposible | Por trace_id |
El campo que lo cambia todo es trace_id. Sin él tienes líneas sueltas de cinco
servicios que hablan del mismo incidente sin saberlo. Con él, los logs dejan de ser un pilar aparte
y pasan a colgar de la traza — que es lo que convierte tres herramientas en un sistema.
| Nunca | En su lugar |
|---|---|
| Contraseñas | Nada, tampoco el hash |
| Tokens y API keys | api_key: "sk_***redacted***" |
| Números de tarjeta | Los últimos cuatro: ****1234 |
| Datos personales sin necesidad | El ID del usuario, no su email |
Los logs se replican, se archivan, se exportan a un tercero y los consulta muchísima más gente que la base de datos. Un log es un almacén de datos con los permisos más laxos del sistema, y casi nadie lo trata como tal.
RED, para servicios y APIs: Rate (peticiones por segundo), Errors (tasa de fallos), Duration (latencia). USE, para recursos e infraestructura: Utilization, Saturation, Errors. Uno mira lo que el usuario experimenta; el otro, lo que la máquina sufre.
| Tipo | Qué hace | Ejemplo |
|---|---|---|
| Counter | Solo sube | Total de peticiones, total de errores |
| Gauge | Sube y baja | Memoria en uso, conexiones activas |
| Histogram | Reparte los valores en cubos | Latencia — permite calcular p95 después |
| Summary | Percentiles precalculados | Duración por cuantil |
El error clásico es medir latencia con un gauge o guardando la media. Un histograma existe justamente para poder preguntar por percentiles después, sin haber decidido de antemano cuáles — y esa pregunta es la única que describe la experiencia real de los usuarios.
| Logging | Error tracking | |
|---|---|---|
| Unidad | La línea | El issue agrupado |
| El mismo fallo 847 veces | 847 líneas | 1 issue con contador |
| Contexto | Lo que escribiste tú | Stack trace, usuario, navegador, breadcrumbs |
| Versión | Hay que deducirla | Asociada al release |
La agrupación es la función principal, no un extra. Ver «847 ocurrencias, 12 usuarios afectados, primera vez hace dos días, release v2.3.1» convierte una avalancha de ruido en un dato accionable: cuánta gente, desde cuándo, y con qué despliegue empezó. Esa última columna es la que cierra el círculo con el módulo de CI/CD.
@sentry/node en ^7.91.0 y
usa Sentry.Handlers.requestHandler() y
new Sentry.Integrations.Express({ app }) en el backend, pero en el frontend escribe
Sentry.browserTracingIntegration() y replayIntegration(), que es la
forma funcional de las integraciones. ¿Pertenecen las dos formas a la misma versión mayor del SDK,
o hay un salto de v7 a v8 mezclado dentro del mismo capítulo? Conviene resolverlo antes de copiar
nada: si son de versiones distintas, el resultado no es un aviso de deprecación sino un error en
el arranque. Y una segunda: la guía cita «OWASP A09:2025 — Logging & Alerting Failures»
como referencia estable. ¿Es esa la numeración definitiva del Top 10 de 2025, o la de un borrador
que todavía podía cambiar? Es el tipo de cita que en una entrevista invita a una repregunta.
Coge un console.log real de un proyecto tuyo y reescríbelo como JSON con los ocho
campos: timestamp, level, service, version,
environment, request_id, event y message. Es
mecánico y tarda cinco minutos.
Y ahora la pregunta incómoda, que es el ejercicio de verdad: ¿de dónde sacas el
request_id si ese log está en una función a la que no llega el objeto de la
petición? Propagar el contexto sin ensuciar todas las firmas es la parte difícil de la
instrumentación, y llega mucho antes que la decisión de qué herramienta comprar.