Registro en aplicaciones JavaScript: mejores prácticas para Node.js
El registro no es simplemente escribir mensajes en la consola. En las aplicaciones modernas de Node.js, es una herramienta críticamente importante para la depuración, el monitoreo y la auditoría. Un registro correctamente configurado permite encontrar errores rápidamente, analizar el comportamiento de los usuarios y garantizar la estabilidad del servicio. En este artículo, analizaremos las mejores prácticas de registro en JavaScript (Node.js), desde la elección de la biblioteca hasta la configuración de la recolección centralizada de logs.
1. Elección de la biblioteca de registro
El console.log integrado solo es bueno para el desarrollo. Para entornos de producción, se necesitan bibliotecas especializadas que proporcionen niveles de registro, formato, rotación de archivos e integración con sistemas externos.
Consideremos tres opciones populares:
- Winston — la biblioteca más popular. Flexible, con soporte para múltiples transportes (archivos, consola, HTTP, bases de datos). Ideal para sistemas complejos.
- Pino — un logger ultrarrápido. Recomendado para aplicaciones de alta carga donde el rendimiento es crítico.
- Bunyan — genera logs en formato JSON. Conveniente para el procesamiento automatizado.
Ejemplo de configuración de Winston:
const winston = require('winston');
const logger = winston.createLogger({ level: 'info', format: winston.format.json(), defaultMeta: { service: 'user-service' }, transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ],});
if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), }));}
logger.info('Servicio iniciado');logger.error('Error de conexión a la BD', { db: 'main' });2. Uso de niveles de registro
Los niveles de registro ayudan a filtrar mensajes por importancia. La jerarquía estándar (de menor a mayor criticidad):
- debug — información detallada de depuración (solo para desarrollo).
- info — eventos estándar (solicitud procesada, usuario autenticado).
- warn — problemas potenciales (poca memoria, solicitud lenta).
- error — errores críticos (fallo de módulo, excepción).
Regla: En producción, use el nivel info o superior. debug debe estar desactivado para no llenar los discos ni reducir el rendimiento.
Ejemplo de cambio dinámico de nivel:
const logger = require('./logger');
if (process.env.LOG_LEVEL) { logger.level = process.env.LOG_LEVEL;}
logger.debug('Este mensaje no aparecerá en producción');logger.info('Usuario ha iniciado sesión');logger.error('No se pudieron guardar los datos');3. Logs estructurados (JSON)
Los logs de texto son difíciles de analizar. La práctica moderna es usar logs estructurados en formato JSON. Esto permite una fácil integración con sistemas de análisis (ELK, Splunk, Grafana Loki).
¿Qué debe tener cada log?
- timestamp — hora exacta del evento (ISO 8601).
- level — nivel de registro.
- message — descripción legible para humanos.
- context — datos adicionales (ID de solicitud, nombre de usuario, código de error).
Ejemplo con Pino:
const pino = require('pino');
const logger = pino({ level: 'info', timestamp: pino.stdTimeFunctions.isoTime, formatters: { level(label) { return
```