Logging
Cómo implementar logging estructurado basado en niveles en Python, JavaScript y Java con mejores prácticas para observabilidad en producción.
Visión general
El logging es la práctica de registrar eventos de aplicación, errores y estado para debugging, monitoreo y auditoría. Un buen logging es estructurado, basado en niveles e incluye metadata contextual (timestamps, request IDs, user IDs) sin exponer datos sensibles.
En producción, los logs son tu fuente primaria de verdad cuando las cosas fallan. Invierte en logging desde el principio.
Cuándo usarlo
Usa esta recipe cuando:
- Debuggeas comportamiento de aplicación en producción
- Monitoreas errores, rendimiento y eventos de negocio
- Auditas acciones de usuarios para compliance o seguridad
- Construyes dashboards y alertas desde datos de log
- Traces requests a través de servicios distribuidos
Solución
Python (Loguru)
from loguru import logger
import sys
# Configurar logging estructurado JSON para producción
logger.remove()
logger.add(sys.stdout, format="{time} {level} {message}", level="INFO")
logger.add("app.log", rotation="10 MB", retention="7 days", level="DEBUG")
# Uso
logger.debug("Processing user {}", user_id)
logger.info("User {} logged in", user_id)
logger.warning("Rate limit approaching for API key {}", api_key[:4])
logger.error("Database connection failed: {}", exc_info=True)
# Logging estructurado
logger.bind(request_id="abc-123").info("Request completed", extra={"duration_ms": 45})
JavaScript (Winston)
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'app.log', maxsize: 10_000_000, maxFiles: 5 }),
],
});
// Uso
logger.debug('Processing user %s', userId);
logger.info('User logged in', { userId });
logger.warn('Rate limit approaching', { apiKey: apiKey.slice(0, 4) });
logger.error('Database connection failed', { error });
Java (SLF4J + Logback)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
public void login(String userId) {
logger.debug("Processing user {}", userId);
logger.info("User {} logged in", userId);
try {
// ...
} catch (Exception e) {
logger.error("Database connection failed", e);
}
}
}
Niveles de Log
| Nivel | Cuándo usar | Ejemplo |
|---|---|---|
| DEBUG | Info diagnóstica detallada | Valores de variables, iteraciones de loops |
| INFO | Eventos normales de la aplicación | Requests procesados, trabajos completados |
| WARN | Problemas recuperables | Uso de API deprecada, límite de rate cercano |
| ERROR | Operaciones fallidas | Timeout de base de datos, archivo no encontrado |
| FATAL/CRITICAL | Sistema inusable | Out of memory, disco lleno |
Mejores prácticas
- Usa logs estructurados JSON en producción para parsing fácil por agregadores de logs (ELK, Datadog, CloudWatch)
- Incluye correlation IDs: Pasa un
request_ida través de todos los logs en una cadena de request - Nunca loguees secretos: Enmascara API keys, tokens y PII antes de loguear
- Loguea al nivel correcto: Usa DEBUG para dev, INFO para ops normales, WARN para anomalías, ERROR para fallos
- Habilita rotación de logs: Previene agotamiento de disco con rotación basada en tamaño o tiempo
- Loguea excepciones con stack traces: Siempre incluye el objeto de excepción, no solo el mensaje
Errores comunes
- Loguear demasiado en nivel INFO, ahogando la señal en ruido
- Usar
printoconsole.logen producción en lugar de un framework de logging - Incluir contraseñas en bruto, tokens o PII en la salida de logs
- No configurar rotación de logs, llenando discos de servidor
- Tragar excepciones sin loguear el stack trace completo
Preguntas frecuentes
P: ¿Debería loguear cada request de API? R: Sí, en nivel INFO con método, path, status code y duración. Usa middleware para logging automático de requests.
P: ¿Qué es structured logging y por qué usarlo? R: El structured logging genera JSON o pares clave-valor en lugar de texto plano. Habilita filtrado, agregación y alertas en sistemas de gestión de logs.
P: ¿Cómo correlaciono logs entre microservicios?
R: Genera un trace_id en el punto de entrada y propágalo a través de headers HTTP o metadata de mensajes. Inclúyelo en cada statement de log.
Recursos Relacionados
Handle Errors in APIs
Patterns for consistent, predictable API error handling across multiple languages and frameworks.
RecipeMiddleware
How to implement request/response middleware for logging, auth, and error handling across Python, JavaScript, and Java.
RecipeEnvironment Variables
How to read, set, and manage environment variables securely across Python, JavaScript, and Java.