Introducción al registro en aplicaciones TypeScript
\n\nEl registro es el proceso de registrar eventos que ocurren durante la ejecución de un programa. Para aplicaciones TypeScript, especialmente aquellas que se ejecutan en el entorno Node.js, un registro bien configurado no es solo una buena práctica, sino una herramienta críticamente importante para la depuración, monitoreo y análisis de errores.
\n\nMuchos desarrolladores principiantes se limitan a usar console.log(). Sin embargo, en un entorno de producción este enfoque es ineficaz: no permite gestionar de forma flexible los niveles de importancia, filtrar mensajes o guardarlos en archivos. En este artículo, analizaremos cómo crear un sistema de registro profesional en TypeScript desde cero.
¿Por qué no deberías usar console.log en producción?
\n\nVeamos un ejemplo típico:
\n\n// Mal enfoque: usamos console.log directamente\nfunction processOrder(orderId: string): void {\n console.log(`Processing order ${orderId}`);\n try {\n // lógica de negocio\n } catch (error) {\n console.error(`Error processing order: ${error}`);\n }\n}\n\n\nProblemas de este enfoque:
\n- \n
- Falta de niveles de registro: no se pueden separar mensajes de depuración de errores críticos. \n
- Sin formato: es difícil leer grandes volúmenes de datos. \n
- No se puede redirigir: todos los mensajes van solo a stdout/stderr. \n
- Problemas de rendimiento: la escritura síncrona en la consola puede ralentizar la aplicación. \n
Mejores prácticas de registro en TypeScript
\n\n1. Elección de una biblioteca de registro
\n\nPara TypeScript se recomienda usar una de las dos bibliotecas populares:
\n- \n
- Winston — un registrador potente y flexible con soporte para transportes (archivo, consola, bases de datos). \n
- Pino — un registrador ultrarrápido, ideal para aplicaciones de alta carga. \n
Instalemos Winston:
\nnpm install winston\nnpm install @types/winston --save-dev\n\n\n2. Creación de un registrador configurable
\n\nCreemos el módulo logger.ts:
import winston from 'winston';\n\nconst logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.simple()\n )\n }),\n new winston.transports.File({ \n filename: 'logs/error.log', \n level: 'error' \n }),\n new winston.transports.File({ \n filename: 'logs/combined.log' \n })\n ]\n});\n\nexport default logger;\n\n\nAhora podemos usar el registrador en cualquier módulo:
\nimport logger from './logger';\n\nfunction getUser(id: string) {\n logger.info(`Fetching user with ID: ${id}`);\n try {\n // lógica para obtener usuario\n logger.debug('User data retrieved successfully');\n } catch (error) {\n logger.error('Failed to fetch user', { userId: id, error });\n }\n}\n\n\n3. Uso de niveles de registro
\n\nNiveles estándar (del menos importante al más importante):
\n- \n
- debug — información detallada de depuración (solo para desarrollo). \n
- info — mensajes informativos estándar. \n
- warn — advertencias sobre problemas potenciales. \n
- error — errores que requieren atención. \n
Configure el nivel de registro mediante variables de entorno:
\n// En el archivo .env\nLOG_LEVEL=debug # para desarrollo\nLOG_LEVEL=warn # para producción\n\n\n4. Registro estructurado
\n\nPase informaci