Como crear un logger en NestJS

Hola a todos, hoy os voy a explicar como podemos crear un logger con NestJS.

En NestJs, es interesante guardar todo lo que va pasando en el programa, ya que es normal que se ejecute constantemente, en caso de fallo podamos ver que ha pasado.

Lo ideal es tenerlo separados por días.

Como crear un proyecto con NestJS

Necesitamos instalar las siguientes dependencias:

$ npm install winston winston-daily-rotate-file

winston es una dependencia muy conocida para almacenar información en ficheros.

wiston-daily-rotate-file es igual que la anterior pero pudiendo rotar los logs por días.

En nuestro nuevo proyecto, crearemos una carpeta llamada services y nos crearemos dentro un servicio llamado logger.service.


import { Injectable } from '@nestjs/common';

@Injectable()
export class LoggerService {

}

Os dejo el contenido que tendría este servicio.


import { Injectable } from '@nestjs/common';
import { format, createLogger, Logger, transports } from 'winston';
import 'winston-daily-rotate-file';

@Injectable()
export class LoggerService {

    // loggers usados
    private loggerInfo: Logger;
    private loggerError: Logger;
    private loggerWarn: Logger;
    private loggerAll: Logger;

    constructor(){
        this.createLoggers();
        this.replaceConsole();
    }

    /**
     * Crea los loggers
     */
    createLoggers(){

        // Formato de texto
        const textFormat = format.printf((log) => {
            return `${log.timestamp} - [${log.level.toUpperCase().charAt(0)}] ${log.message}`;
        })

        // Formato de fecha
        const dateFormat = format.timestamp({
            format: 'YYYY-MM-DD HH:mm:ss'
        })

        // Logger de info
        this.loggerInfo = createLogger({
            level: 'info',
            format: format.combine(
                dateFormat,
                textFormat
            ),
            transports: [
                new transports.DailyRotateFile({
                    filename: 'log/info/info-%DATE%.log',
                    datePattern: 'YYYY-MM-DD',
                    maxFiles: '7d'
                })
            ]
        });

        // Logger de error
        this.loggerError = createLogger({
            level: 'error',
            format: format.combine(
                dateFormat,
                textFormat
            ),
            transports: [
                new transports.DailyRotateFile({
                    filename: 'log/error/error-%DATE%.log',
                    datePattern: 'YYYY-MM-DD',
                    maxFiles: '7d'
                })
            ]
        });

        // Logger de warn
        this.loggerWarn = createLogger({
            level: 'warn',
            format: format.combine(
                dateFormat,
                textFormat
            ),
            transports: [
                new transports.DailyRotateFile({
                    filename: 'log/warn/warn-%DATE%.log',
                    datePattern: 'YYYY-MM-DD',
                    maxFiles: '7d'
                })
            ]
        });

        // Logger donde almacenamos todo, ademas de la consola
        this.loggerAll = createLogger({
            format: format.combine(
                dateFormat,
                textFormat
            ),
            transports: [
                new transports.DailyRotateFile({
                    filename: 'log/all/all-%DATE%.log',
                    datePattern: 'YYYY-MM-DD',
                    maxFiles: '7d'
                }),
                new transports.Console()
            ]
        });

    }

    /**
     * Remplaza la funcionalidad de los console.log, console.error y console.warn
     */
    replaceConsole(){

        // console.log
        console.log = (message: any, params: any) => {
            if(params){
                this.loggerInfo.info(message + " " + JSON.stringify(params));
                this.loggerAll.info(message + " " + JSON.stringify(params));
            }else{
                this.loggerInfo.info(message);
                this.loggerAll.info(message);
            }
        }
        
        // console.error
        console.error = (message: any, params: any) => {
            if(params){
                this.loggerError.error(message + " " + JSON.stringify(params));
                this.loggerAll.error(message + " " + JSON.stringify(params));
            }else{
                this.loggerError.error(message);
                this.loggerAll.error(message);
            }
        }
        
        // console.warn
        console.warn = (message: any, params: any) => {
            if(params){
                this.loggerWarn.warn(message + " " + JSON.stringify(params));
                this.loggerAll.warn(message + " " + JSON.stringify(params));
            }else{
                this.loggerWarn.warn(message);
                this.loggerAll.warn(message);
            }
        }
    }

    // Estos métodos son necesarios

    log(message: string){
        this.loggerInfo.info(message);
        this.loggerAll.info(message);
    }
    
    error(message: string){
        this.loggerError.error(message);
        this.loggerAll.error(message);
    }
    
    warn(message: string){
        this.loggerWarn.warn(message);
        this.loggerAll.warn(message);
    }
    
    debug(message: string){ }
    
    verbose(message: string){ }
    
}


En el fichero main.ts, tenemos que agregar que use este logger.


import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggerService } from './services/logger.service';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: new LoggerService() // Creacion de nuestro logger
  });
  await app.listen(3000);
}
bootstrap();

El resultado es el siguiente:

Esto creará una carpeta log con diferentes carpetas donde se almacenaran estos logs.

Gracias al paquete de winston-daily-rotate-file cuando sea un día diferente, se almacenará automáticamente en otro fichero. Podemos indicar el numero de días máximo (maxFiles).

Te dejo el repositorio con el ejemplo completo.

https://github.com/DiscoDurodeRoer/nestjs-logger-example

Espero que os sea de ayuda. Si tenéis dudas, preguntad. Estamos para ayudarte.

Compartir

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *