Crear un logger eficiente en JavaScript es posible combinando dos patrones esenciales: Singleton y Factory. Esta combinación permite gestionar registros o logs de manera centralizada y versátil, adaptándose fácilmente a las necesidades específicas del proyecto.
¿Qué es el patrón singleton y cómo implementarlo en JavaScript?
El patrón Singleton asegura que una clase tenga una única instancia en la aplicación. En JavaScript, puedes lograr esto definiendo una clase que verifica si ya existe una instancia antes de crear una nueva.
Al usar Singleton, se asegura que cada vez que se instancia la clase Logger sea la misma instancia, centralizando los logs en un solo lugar.
¿Cómo funciona el patrón factory para crear diferentes tipos de loggers?
El patrón Factory permite crear diferentes tipos de objetos a partir de una sola clase o interfaz. Así puedes crear fácilmente loggers específicos según tus necesidades.
Este ejemplo muestra cómo crear dos tipos de logger con un Factory:
¿Cómo combinar los patrones singleton y factory en una aplicación real?
Integrando ambos patrones, puedes manejar logs efectivamente en diferentes modalidades (consola, archivo, etc.), sin perder la centralización.
Aquí está el archivo principal para implementar estos conceptos combinados:
constLoggerFactory=require('./loggerFactory');constLogger=require('./logger');const loggerInstance =newLogger();const consoleLogger =LoggerFactory.createLogger('console');const fileLogger =LoggerFactory.createLogger('file');consoleLogger.log('esto es un mensaje de en consola');fileLogger.log('esto es un mensaje de log en archivo');loggerInstance.getLogs().forEach(log=>console.log(log));
Al ejecutar este código, verás cómo cada tipo de logger maneja su función específica, y todos los logs se mantienen en una ubicación centralizada gracias al patrón singleton.
¿Te animas a completar el reto propuesto? Cuéntame tus resultados en los comentarios.
y automaticamente esta agregando los logs en el archivo.
Mi solución al reto. Yo toda la logica la agregue directo desde la clase FileLogger, donde al inicio reseteo el archivo a contenido en blanco y despues tengo una función llamada "saveLog(msg)" que es privada, que me permite guardar todos los logs en el archivo
Para evitar borrar los registros previos y mantener el historial de logs, lo ideal es inicializar this.logssolo la primera vez que se crea la instancia. Así:
classLogger{constructor(){if(!Logger.instance){this.logs=[];// Solo se inicializa una vezLogger.instance=this;}returnLogger.instance;}log(message){const timestamp =newDate().toISOString();this.logs.push(`${timestamp}: ${message}`);console.log(`${timestamp}: ${message}`);}getLogs(){returnthis.logs;}}
Si quisiéramos escribir en un archivo los logs provenientes del FileLogger podríamos hacer lo siguiente:const fs = require('fs');const path = require('path');const Logger = require('./logger');
const loggerInstance = new Logger(); // Singleton instance
class ConsoleLogger { constructor() { this.logger = loggerInstance; }
log(message) { this.logger.log(message); }}
class FileLogger { constructor(filePath = path.join(__dirname, 'logs.txt')) { this.logger = loggerInstance; this.filePath = filePath; }
log(message, level = 'info') { this.logger.log(message);
const timestamp = new Date().toISOString(); const formattedMessage = \[${timestamp}] \[${level.toUpperCase()}] ${message}\n;
fs.appendFileSync(this.filePath, formattedMessage, 'utf8'); this.logger.log(message, level); // Registrar en el logger base }}
class LoggerFactory { static createLogger(type) { switch (type) { case 'console': return new ConsoleLogger(); case 'file': return new FileLogger(); default: throw new Error('Invalid logger type'); } }}
module.exports = LoggerFactory;