Logger is a built-in function of NestJS. See how to use and customize logger.

Enable/disable logger display

  1. When we create an app, we can configure logger by adding a second parameter to the create parameter
const app = await NestFactory.create(ApplicationModule, {
  logger: false});await app.listen(3000);
Copy the code

Source:

public async create<T extends INestApplication = INestApplication>(
    module: any, serverOrOptions? : AbstractHttpAdapter | NestApplicationOptions, options? : NestApplicationOptions, ):Promise<T> {}
Copy the code
  • NestApplicationContextOptions NestApplicationOptions inheritance
export class NestApplicationContextOptions { logger? : LoggerService | LogLevel[] | boolean; }Copy the code

The logger levels:

  • ‘log’
  • ‘error’
  • ‘warn’
  • ‘debug’
  • ‘verbose.
// Level type
export type LogLevel = 'log' | 'error' | 'warn' | 'debug' | 'verbose';

// Configure logger hierarchy when creating app
const app = await NestFactory.create(ApplicationModule, {
  logger: ['error'.'warn']});await app.listen(3000);
Copy the code

LoggerService interface

To implement custom Logger we must implement LoggerService

export interface LoggerService {
  log(message: any, context? :string);
  error(message: any, trace? :string, context? :string);
  warn(message: any, context? :string); debug? (message:any, context? :string); verbose? (message:any, context? :string);
}

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

export class MyLogger implements LoggerService {
  log(message: string) {}
  error(message: string, trace: string) {}
  warn(message: string) {}
  debug(message: string) {}
  verbose(message: string){}}Copy the code

Extending existing Loggers

A logger that extends nestJS needs to inherit the NestJS logger interface, which in turn inherits the LoggerService interface

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

export class MyLogger extends Logger {
  error(message: string, trace: string) {
    super.error(message, trace); }}Copy the code

The source code

@Injectable(a)export class Logger implements LoggerService {
  private static logLevels: LogLevel[] = [
    'log'.'error'.'warn'.'debug'.'verbose',];private staticlastTimestamp? :number;
  private staticinstance? :typeof Logger | LoggerService = Logger;

  constructor(
    @Optional(a)protectedcontext? :string.@Optional(a)private readonly isTimestampEnabled = false.) {}
  error(message: any, trace = ' ', context? :string) {}
  log(message: any, context? :string) {}
  warn(message: any, context? :string) {}
  debug(message: any, context? :string) {}
  verbose(message: any, context? :string) {}
  setContext(context: string) {}
  static overrideLogger(logger: LoggerService | LogLevel[] | boolean) {}
  static log(message: any, context = ' ', isTimeDiffEnabled = true) {}
  static error(
    message: any,
    trace = ' ',
    context = ' ',
    isTimeDiffEnabled = true.) {}
  static warn(message: any, context = ' ', isTimeDiffEnabled = true) {}
  static debug(message: any, context = ' ', isTimeDiffEnabled = true) {}
  static verbose(message: any, context = ' ', isTimeDiffEnabled = true) {}
  private callFunction(
    name: 'log' | 'warn' | 'debug' | 'verbose',
    message: any, context? :string.) {}
  private getInstance(): typeof Logger | LoggerService {}
  private isLogLevelEnabled(level: LogLevel): boolean {}
  private static printMessage(
    message: any,
    color: (message: string) = >string,
    context = ' ', isTimeDiffEnabled? :boolean.) {}
  private staticupdateAndGetTimestampDiff( isTimeDiffEnabled? :boolean,
  ): string {}
  private static printStackTrace(trace: string){}}Copy the code

The logger module

import { Module } from '@nestjs/common';
import { MyLogger } from './my-logger.service';

@Module({
  providers: [MyLogger],
  exports: [MyLogger],
})
export class LoggerModule {}
Copy the code

Inject LoggerModule into AppModule and get MyLogger instance through app get method. The app also provides a useLogger to use the Logger.

const app = await NestFactory.create(ApplicationModule, {
	// Close the system log
  logger: false}); app.useLogger(app.get(MyLogger))await app.listen(3000);
Copy the code

This may seem like a bit of a hassle, but we can just create an instance and inject it without using Module.

const app = await NestFactory.create(ApplicationModule, {
	// Close the system log
  logger: false});// Use custom logs
app.useLogger(new MyLogger());
await app.listen(3000);
Copy the code

Injection scope is specified by passing the Scope property to the @Injectable() decorator option object

Scope is an enumeration type

export enum Scope {
  /** * Providers can be shared between multiple classes. Provider life cycle * is strictly related to the application life cycle. Once an application has * bootstrap, all providers are instantiated. * /
  DEFAULT,
  /** * each use instantiates the provider's new private instance. * /
  TRANSIENT,
  /** * instantiate a new instance */ for each request processing pipe
  REQUEST,
}
Copy the code
The scope option acts as configuration metadata for the Logger class and specifies a temporary range,
// To ensure that Logger has a unique instance in each function module
import { Injectable, Scope, Logger } from '@nestjs/common';

@Injectable({ scope: Scope.TRANSIENT })
export class MyLogger extends Logger {}

import { Module } from '@nestjs/common';
import { MyLogger } from './my-logger.service';

@Module({
  providers: [MyLogger],
  exports: [MyLogger],
})
export class LoggerModule {}

import { Injectable } from '@nestjs/common';
import { MyLogger } from './my-logger.service';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  constructor(private myLogger: MyLogger) {
    this.myLogger.setContext('CatsService');
  }

  findAll(): Cat[] {
    this.myLogger.warn('About to return cats! ');
    return this.cats; }}const app = await NestFactory.create(ApplicationModule, {
  logger: false}); app.useLogger(new MyLogger());
await app.listen(3000);
Copy the code

With scope injection, we can have a Logger instance in each Module by defining a separate Module. When used, we use MyLogger in the service. Finally, we need to call useLogger in our app to instantiate MyLogger.

The third party logger

Production applications often have specific logging requirements, including advanced filtering, formatting, and centralized logging. Nest’s built-in logger is used to monitor the behavior of the Nest system and can also be used during development for basic formatted text recording in function modules, but production applications typically leverage dedicated recording modules such as Winston. As with any standard Node.js application, you can take full advantage of such modules in Nest.