Logging Estructurado
Formatos, niveles, centralización y buenas prácticas para logging en sistemas distribuidos.
¿Por qué logging estructurado?
En un sistema monolítico, leer logs en texto plano puede ser suficiente. Pero en una arquitectura distribuida con decenas de servicios, los logs no estructurados se vuelven inmanejables. El logging estructurado — donde cada entrada es un objeto con campos bien definidos — es la base para poder buscar, filtrar y correlacionar eventos a escala.
Formatos de log
JSON como estándar
El formato más adoptado para logs estructurados es JSON. Cada línea de log es un objeto con campos consistentes:
{
"timestamp": "2024-01-15T10:30:00.123Z",
"level": "INFO",
"service": "order-service",
"traceId": "abc123def456",
"message": "Orden creada exitosamente",
"orderId": "ORD-789",
"userId": "USR-456",
"duration_ms": 145
}
Campos esenciales
Todo log estructurado debería incluir como mínimo:
- timestamp: Momento exacto en formato ISO 8601 con zona horaria UTC.
- level: Severidad del evento (DEBUG, INFO, WARN, ERROR, FATAL).
- service: Nombre del servicio que emite el log.
- traceId / correlationId: Identificador para correlacionar logs entre servicios.
- message: Descripción legible del evento.
Niveles de log
Los niveles de log permiten filtrar por severidad y controlar el volumen de información:
| Nivel | Uso | Ejemplo |
|---|---|---|
| DEBUG | Detalle interno para desarrollo | ”Query ejecutada en 12ms” |
| INFO | Eventos normales del negocio | ”Orden ORD-789 creada” |
| WARN | Situaciones anómalas no críticas | ”Retry #2 al servicio de pagos” |
| ERROR | Fallos que requieren atención | ”Timeout al conectar con DB” |
| FATAL | El servicio no puede continuar | ”No se pudo iniciar el pool de conexiones” |
Buenas prácticas con niveles
- Usá INFO para eventos de negocio significativos, no para cada línea de código.
- Reservá ERROR para situaciones que realmente necesitan intervención humana.
- Configurá niveles dinámicamente por servicio — poder subir a DEBUG en producción sin redeploy es invaluable.
- Evitá loguear datos sensibles (contraseñas, tokens, PII) en cualquier nivel.
Centralización de logs
El problema de los logs distribuidos
Cuando tenés 20 microservicios corriendo en múltiples instancias, los logs están dispersos en decenas de contenedores. Sin centralización, diagnosticar un problema requiere conectarse manualmente a cada instancia.
Stack de centralización
El patrón más común es el stack ELK (Elasticsearch, Logstash, Kibana) o su variante EFK (Elasticsearch, Fluentd, Kibana):
- Recolección: Cada servicio escribe logs a stdout/stderr. Un agente (Fluentd, Filebeat, Fluent Bit) los recolecta.
- Procesamiento: Los logs se parsean, enriquecen y transforman antes de almacenarse.
- Almacenamiento: Elasticsearch indexa los logs para búsqueda rápida.
- Visualización: Kibana permite buscar, filtrar y crear dashboards sobre los logs.
Alternativas modernas
- Loki (Grafana): Almacena logs indexando solo las etiquetas, no el contenido completo. Más económico que Elasticsearch para volúmenes altos.
- CloudWatch Logs (AWS): Solución managed para entornos AWS.
- Datadog Logs: Plataforma SaaS con correlación automática entre logs, métricas y trazas.
Buenas prácticas
Contexto, no ruido
Cada línea de log debe aportar contexto útil. Preguntate: “Si me despierta una alerta a las 3 AM, ¿este log me ayuda a entender qué pasó?”
Correlation IDs
Propagá un traceId o correlationId en cada request que atraviese múltiples servicios. Esto permite reconstruir el flujo completo de una operación filtrando por un solo ID.
Sampling en producción
Para servicios de alto tráfico, loguear cada request puede ser costoso. Implementá sampling: logueá el 100% de errores pero solo un porcentaje de requests exitosos.
Retención y rotación
Definí políticas claras de retención:
- Logs de ERROR/FATAL: 90 días mínimo.
- Logs de INFO: 30 días.
- Logs de DEBUG: Solo en ambientes de desarrollo o habilitados temporalmente.
No loguear datos sensibles
Nunca incluyas en logs: contraseñas, tokens de acceso, números de tarjeta, datos personales identificables (PII). Usá masking o redacción automática si es necesario.
Logging en la práctica
Patrón: Request logging middleware
Un middleware que loguea automáticamente cada request entrante y su respuesta:
→ REQUEST | method=POST path=/api/orders traceId=abc123 userId=USR-456
← RESPONSE | method=POST path=/api/orders traceId=abc123 status=201 duration=145ms
Patrón: Error logging con contexto
Cuando ocurre un error, incluí todo el contexto necesario para diagnosticarlo sin necesidad de reproducirlo:
ERROR | service=payment-service traceId=abc123 orderId=ORD-789
message="Pago rechazado por el proveedor"
provider=stripe errorCode=card_declined
retryCount=0 userId=USR-456
Resumen
El logging estructurado es el primer pilar de la observabilidad. Logs bien formateados, centralizados y con contexto adecuado permiten diagnosticar problemas rápidamente, entender el comportamiento del sistema y cumplir con requisitos de auditoría. La inversión en una buena estrategia de logging se paga con creces la primera vez que necesitás investigar un incidente en producción.