How to use nestjs Logging service

Javascriptnode.jsTypescriptLoggingNestjs

Javascript Problem Overview


I tried to use the internal Logger of nestjs (described on https://docs.nestjs.com/techniques/logger -> but with no description of how to use it)

But I had problems (tried to inject LoggerService and so on)

Can anybody explain how to do this?

Javascript Solutions


Solution 1 - Javascript

Best practice

Better than accessing the Logger statically is to create an instance for your class:

@Controller()
export class AppController {
  private readonly logger = new Logger(AppController.name);

  @Get()
  async get() {
    this.logger.log('Getting stuff');
  }
}


Why is this better?

  1. You can provide a context in the constructor like new Logger(AppController.name) so that the class name (or anything else) will be part of all log messages in this class.

  2. If you at some point want to extend or replace the default LoggerService, you do not need to change any of your application code besides setting the new logger. Your new logger will automatically be used. If you access it statically it will continue to take the default implementation.

const app = await NestFactory.create(AppModule, {logger: new MyLogger()});
  1. You can mock the Logger in your tests:
module.useLogger(new NoOpLogger());

Solution 2 - Javascript

You need to import first into your class:

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

and then you can begin with logging:

Logger.log('info')
Logger.warn('warning')
Logger.error('something went wrong! ', error)

Solution 3 - Javascript

The answer is simple. There are static methods on the Logger class.

e.g.

static log(message: string, context = '', isTimeDiffEnabled = true) 

Usage:

Logger.log('Only a test');

Solution 4 - Javascript

This answer might be useful for others who are trying with CustomLogger Implementation. I am trying to show a sample custom logger implementation and how it can be injected to the Nestjs framework.

I understand that Nestjs inherently uses pino logger. This is just a custom implementation of logger service (which you can replace with bunyan, winston, etc..) This is the folder structure I use:

> src /  
>   modules /
>      database /
>        ...
>        database.module.ts
>      api /
>        services /
>        controllers /
>        interceptors /
>        middlewares /
>        models /
>        schemas /
>      shared /
>        services /
>           app.util.service.ts
>           pino.logger.service.ts
>        utils / 
>        interceptors /
>        filters /
>        main.ts    
>        app.controller.ts    
>        app.service.ts
>        server.util.service.ts 

This is the main gist of it. So the logger service is implemented as follows

import {Injectable, LoggerService, Scope} from "@nestjs/common";
import * as pino from 'pino';
import {AppUtilService} from "./app.util.service";
import * as os from "os";
import {APP_LOG_REDACT, APP_MESSAGE_KEY} from "../utils/app.constants";

    @Injectable({
        scope: Scope.DEFAULT
    })
    export class PinoLoggerService implements LoggerService{
        constructor(private appUtilService: AppUtilService) {

        }

        logService = (fileNameString): pino.Logger => {
            return pino({
                useLevelLabels: true,
                prettyPrint: this.appUtilService.isDevEnv(),
                // tslint:disable-next-line: object-literal-sort-keys
                messageKey: APP_MESSAGE_KEY,
                level: this.appUtilService.getLogLevel(),
                redact: {
                    paths: APP_LOG_REDACT,
                    censor: '**SECRET-INFO**'
                },
                base: {
                    hostName: os.hostname(),
                    platform: os.platform(),
                    processId: process.pid,
                    timestamp: this.appUtilService.getCurrentLocaleTimeZone(),
                    // tslint:disable-next-line: object-literal-sort-keys
                    fileName: this.appUtilService.getFileName(fileNameString),
                },
            });
        }

        debug(message: any, context?: string): any {
        }

        error(message: any, trace?: string, context?: string): any {
        }

        log(message: any, context?: string): any {
        }

        warn(message: any, context?: string): any {
        }

    }

The custom implementation is implemented with the my specific options in pinojs github I am using fastifyjs instead of express (again to match my prject needs). So I've added the logger in fastify js server options. If you are using express, its better to specify the new custom implementation in the Nest application Adapter as stated above.

My util service that takes care of implementing the fastify server

import * as fastify from "fastify";
import {Http2Server, Http2ServerRequest, Http2ServerResponse} from "http2";
import {DocumentBuilder, SwaggerModule} from "@nestjs/swagger";
import * as fs from "fs";
import * as path from "path";
import * as uuid from "uuid";
import * as qs from "query-string";
import {PinoLoggerService} from "./modules/shared/services/pino.logger.service";
import {AppUtilService} from "./modules/shared/services/app.util.service";
import {AppConstantsService} from "./modules/shared/services/app.constants.service";
import {AppModel} from "./modules/shared/model/app.model";
import {Reflector} from "@nestjs/core";
export class ServerUtilService {
    private logService;
    private appConstantsService;
    private appUtilServiceInstance: AppUtilService;
    private fastifyInstance: fastify.FastifyInstance<Http2Server, Http2ServerRequest, Http2ServerResponse>;
    constructor() {
        this.appUtilServiceInstance = new AppUtilService();
        this.logService = new PinoLoggerService(this.appUtilServiceInstance);
        this.appConstantsService = new AppConstantsService(this.appUtilServiceInstance);
    }

    retrieveAppConstants(): AppModel {
        return this.appConstantsService.getServerConstants();
    }

    retrieveAppUtilService(): AppUtilService {
        return this.appConstantsService;
    }
    createFastifyServerInstance = (): fastify.FastifyInstance<Http2Server, Http2ServerRequest, Http2ServerResponse> => {
        const serverConstants = this.appConstantsService.getServerConstants();
        const httpsOptions = {
            cert: fs.readFileSync(path.join(process.cwd() + '/https-keys/cert.pem')),
            key: fs.readFileSync(path.join(process.cwd() + '/https-keys/key.pem')),

            allowHTTP1: true,
            rejectUnauthorized: true,
        };
        this.fastifyInstance = fastify({

            http2: true,
            https: httpsOptions,
            bodyLimit: 26214400,
            pluginTimeout: 20000,
            genReqId: () => {
                return uuid.v4().toString();
            },
            requestIdHeader: serverConstants.requestIdHeader,
            modifyCoreObjects: true,
            trustProxy: serverConstants.trustProxy,
            ignoreTrailingSlash: true,
            logger: this.logService,
            querystringParser: (str) => {
                return qs.parse(str);
            },
        });
        this.addContentTypeParser();
        return this.fastifyInstance;
    };

    private addContentTypeParser() {
        this.fastifyInstance.addContentTypeParser('*', (req, done) => {
            let data = '';
            req.on('data', chunk => {
                console.log('inside data listener event');
                return data += chunk; });
            req.on('end', () => {
                done(null,data);
            })
        });
    }

   
}
export const ServerUtilServiceInstance = new ServerUtilService();

And in my main.ts

async function bootstrap() {
  const fastifyServerInstance = 
  ServerUtilServiceInstance.createFastifyServerInstance();
  const serverConstants = ServerUtilServiceInstance.retrieveAppConstants();
  const app: NestFastifyApplication = await NestFactory.create<NestFastifyApplication>(
      AppModule,
      new FastifyAdapter(fastifyServerInstance)
  );
    ....
    ... // global filters, interceptors, pipes
    ....
    await app.listen(serverConstants.port, '0.0.0.0');

}

Solution 5 - Javascript

Event better best practice inject the existing logger.

app.module.ts

import { Logger, Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService, Logger],
})
export class AppModule {}

And in the app.service.ts

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

@Injectable()
export class AppService {
  constructor(private readonly logger: Logger) {}

  sayHello() {
    this.logger.log('Hello world!') 
  }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionmaku_atView Question on Stackoverflow
Solution 1 - JavascriptKim KernView Answer on Stackoverflow
Solution 2 - JavascriptDani MachView Answer on Stackoverflow
Solution 3 - Javascriptmaku_atView Answer on Stackoverflow
Solution 4 - Javascriptvijayakumarpsg587View Answer on Stackoverflow
Solution 5 - JavascriptAdrian HView Answer on Stackoverflow