JSPM

nestjs-pino

0.2.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 673179
  • Score
    100M100P100Q185393F
  • License MIT

Pino logger for NestJS

Package Exports

  • nestjs-pino

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (nestjs-pino) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

NestJS-Pino logo

NestJS-Pino

npm Travis (.org) Coverage Status Snyk Vulnerabilities for npm package

✨✨✨ Logging in NestJS via Pino with REQUEST CONTEXT IN ANY PLACE ✨✨✨

Example

In controller:

import { Logger } from 'nestjs-pino';

@Controller()
export class AppController {
  constructor(
    private readonly myService: MyService,
    private readonly logger: Logger
  ) {}

  @Get()
  getHello(): string {
    this.logger.log("calling AppController.getHello");
    return `Hello ${this.myService.getWorld()}`;
  }
}

In service:

import { Logger } from 'nestjs-pino';

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

  getWorld() {
    this.logger.debug("calling MyService.getWorld");
    return "World!";
  }
}

Output (every log has request context):

{"level":30,"time":1568720266616,"pid":25566,"hostname":"my-host","req":{"id":1,"method":"GET","url":"/","headers":{...},"remoteAddress":"::1","remotePort":53753},"msg":"calling AppController.getHello","v":1}
{"level":20,"time":1568720266616,"pid":25566,"hostname":"my-host","req":{"id":1,"method":"GET","url":"/","headers":{...},"remoteAddress":"::1","remotePort":53753},"msg":"calling MyService.getWorld","v":1}
{"level":30,"time":1568720266623,"pid":25566,"hostname":"my-host","req":{"id":1,"method":"GET","url":"/","headers":{...},"remoteAddress":"::1","remotePort":53753},"res":{"statusCode":200,"headers":{...}},"responseTime":9,"msg":"request completed","v":1}

Install

npm i nestjs-pino

Register module

Default params

Just import LoggerModule to your module:

import { LoggerModule } from 'nestjs-pino';

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

Configure

Also, you can configure it. forRoot function has the same API as express-pino-logger has (it's the same as pino itself and can take existing logger via { logger: pino(...) }):

import { LoggerModule } from 'nestjs-pino';

@Module({
  imports: [
    LoggerModule.forRoot(
      {
        name: 'add some name to every JSON line',
        level: process.env.NODE_ENV !== 'production' ? 'debug' : 'info',
        prettyPrint: process.env.NODE_ENV !== 'production',
        useLevelLabels: true,
        // and all the others...
      },
      someWritableStream
    )
  ],
  ...
})
class MyModule {}

Extreme mode

If you want to enable extreme mode you should read pino extreme mode docs.

If you are ok with that, so you can configure module like this:

import * as pino from 'pino';
import { LoggerModule } from 'nestjs-pino';

const dest = pino.extreme();
const logger = pino(dest);

@Module({
  imports: [LoggerModule.forRoot({ logger })],
  ...
})
class MyModule {}

Also you can read more about Log loss prevention.

Usage as Logger service

Logger implements standard NestJS LoggerService interface. So if you are familiar with built in NestJS logger you are good to go.

// my.service.ts
import { Logger } from 'nestjs-pino';

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

  getWorld() {
    this.logger.debug("calling MyService.getWorld");
    return "World!";
  }
}

Usage as NestJS app logger

import { Logger } from 'nestjs-pino';

const app = await NestFactory.create(MyModule, { logger: new Logger() });

FAQ

Q: How does it work?

A: It use express-pino-logger under hood, so every request has it's own child-logger, and with help of async_hooks Logger can get it while calling own methods. So your logs can be groupped by req.id.

Q: Why use async_hooks instead of REQUEST scope?

A: REQUEST scope can have perfomance issues depending on your app. TL;DR: using it will cause to instantiating every class, that injects Logger, as a result it will slow down your app.

Q: I'm using old nodejs version, will it work for me?

A: Please read this.

Q: What about pino built in methods/levels?

A: Pino built in methods are not compatible to NestJS built in LoggerService methods, so decision is to map pino methods to LoggerService methods to save Logger API:

  • trace=verbose
  • debug=debug
  • info=log
  • warn=warn
  • error=error