Skip to content

Latest commit

Β 

History

History
358 lines (276 loc) Β· 7.94 KB

README.md

File metadata and controls

358 lines (276 loc) Β· 7.94 KB

Logger Logo Nest Logo

Logger module and service for Nest,
a progressive Node.js framework for building efficient and scalable server-side applications.

NPM Version Package License Test Status

Installation

npm

npm install @andreafspeziale/nestjs-log

yarn

yarn add @andreafspeziale/nestjs-log

pnpm

pnpm add @andreafspeziale/nestjs-log

How to use?

Module

The module is Global by default.

LoggerModule.forRoot(options)

src/core/core.module.ts

import { Module } from '@nestjs/common';
import { LoggerModule } from '@andreafspeziale/nestjs-log';

@Module({
  imports: [
    LoggerModule.forRoot({
      level: LoggerLevel.Error,
      customLevelsOrder: false
      pretty: true,
      colorize: false,
      redact: ['password'],
      exclude: ['/swagger'] // Exclude routes from LoggerInterceptor
    }),
  ],
  ...
})
export class CoreModule {}
  • level is optional and its default is Debug
  • customLevelsOrder is optional and its default is false (Enables a personal levels hierarchy taste)
  • pretty is optional and its default is true
  • colorize is optional and its default is true
  • redact is optional and its default is []
  • exclude is optional and its default is []

Swagger example

BTW, using by using defaults you can ignore the provided schemas described in the "Environment variables management" chapter and just:

export const loggerModuleOptions = {
  level: LoggerLevel.Debug,
  customLevelsOrder: false,
  pretty: true,
  colorize: true,
  redact: [],
  exclude: [],
};

src/core/core.module.ts

import { Module } from '@nestjs/common';
import { LoggerModule } from '@andreafspeziale/nestjs-log';

@Module({
  imports: [
    LoggerModule.forRoot({}),
  ],
  ...
})
export class CoreModule {}

LoggerModule.forRootAsync(options)

src/core/core.module.ts

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { LoggerModule } from '@andreafspeziale/nestjs-log';
import { Config } from './config';

@Module({
  imports: [
    ConfigModule.forRoot({
      ....
    }),
    LoggerModule.forRootAsync({
      useFactory: (cs: ConfigService<Config, true>) => cs.get<ConfigService['logger']>('logger'),
      inject: [ConfigService],
    }),
  ],
  ....
})
export class CoreModule {}

Decorators

use the client and create your own service

InjectLoggerOptions() and InjectLogger()

src/samples/samples.service.ts

import { Injectable } from '@nestjs/common';
import {
  InjectLoggerOptions,
  InjectLogger,
  LoggerClient,
  LoggerModuleOptions,
  LoggerClient,
} from '@andreafspeziale/nestjs-log';

@Injectable()
export class SamplesService {
  constructor(
    @InjectLoggerOptions()
    private readonly loggerModuleOptions: LoggerModuleOptions, // Showcase purposes
    @InjectLogger() private readonly loggerClient: LoggerClient
  ) {}

  ....
}

Service

out of the box service with a set of features

LoggerService

src/samples/samples.service.ts

import { LoggerService } from '@andreafspeziale/nestjs-log';
import { SampleReturnType, MyParams } from './samples.interfaces'

@Injectable()
export class SamplesService {
  constructor(
    private readonly loggerService: LoggerService
  ) {
    this.logger.setContext(SamplesService.name);
  }

  async sampleMethod(params: MyParams): Promise<SampleReturn> {
    this.logger.debug('Doing something...', {
      fn: this.sampleMethod.name,
      params,
    });

    ....
  }
}

You'll see:

{
  context: 'SamplesService',
  fn: 'sampleMethod',
  params: {
    ....,
  },
  reqId: '557a8e30-62e6-11ef-b821-ebc5f38e9e30',
  level: 'debug',
  message: 'Doing something...',
  timestamp: '2024-08-25T13:31:28.843Z'
}

reqId will be there as soon as you developing a backend server and:

src/main.ts

import { rTracerFastifyMiddleware } from '@andreafspeziale/nestjs-log';

async function bootstrap() {
  const app = await NestFactory.create....;

  ....

  // I usually use Fastify but feel free to use Express importing rTracerExpressMiddleware instead of rTracerFastifyMiddleware
  app.use(rTracerFastifyMiddleware());

  ....

  await app.listen....;
}
bootstrap();

Middleware or Interceptor?

Use middleware in case of Express, use interceptor in case of Fastify.

At each request you'll see something like this:

{
  context: 'LoggerInterceptor',
  fn: 'intercept',
  request: {
    route: 'POST /whatever',
    query: {},
    body: {
      ....
    }
  },
  reqId: '557a8e30-62e6-11ef-b821-ebc5f38e9e30',
  level: 'http',
  message: 'Incoming request...',
  timestamp: '2024-08-25T13:31:28.798Z'
}

Middleware

src/core/core.module.ts

import { LoggerMiddleware, LoggerModule } from '@andreafspeziale/nestjs-log';
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';

@Module({
  imports: [
    ....,
    LoggerModule....
  ],
  providers: [....],
})
export class CoreModule implements NestModule {
  configure(consumer: MiddlewareConsumer): void {
    consumer
      .apply(LoggerMiddleware)
      .exclude('(.*)/healthz', '/swagger(.*)', '/favicon.ico')
      .forRoutes('*');
  }
}

Interceptor

src/samples/samples.controller.ts

import { Body, Controller, Post, UseInterceptors } from '@nestjs/common';
import { LoggerInterceptor } from '@andreafspeziale/nestjs-log';
import { MyPayloadDTO, MyReturnDTO } from './dto';
import { SamplesService } from './samples.service';

@Controller('samples')
@UseInterceptors(LoggerInterceptor)
export class SearchController {
  constructor(private readonly samplesService: SamplesService) {}

  @Post()
  async search(@Body() payload: MyPayloadDTO): Promise<MyReturnDTO> {
    return this.samplesService.sampleMethod(payload);
  }
}

or

src/core/core.module.ts

import { LoggerInterceptor, LoggerModule } from '@andreafspeziale/nestjs-log';
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module({
  imports: [
    ....,
    LoggerModule.... // Use the "exclude" module option to exclude routes from LoggerInterceptor
  ],
  providers: [{
    provide: APP_INTERCEPTOR,
    useClass: LoggerInterceptor,
  }],
})
export class CoreModule {}

Environment variables management

Please refer to @andreafspeziale/nestjs-search for more info about the environment variables features exported from my packages.

nestjs-log exports some features as well.

Zod

import { loggerSchema } from '@andreafspeziale/nestjs-log/dist/zod';

....

Class transformer/validator

import { LoggerSchema, ILoggerSchema } from '@andreafspeziale/nestjs-search/dist/class-validator';

....

Test

  • pnpm test

Stay in touch

License

nestjs-log MIT licensed.