Code Monkey home page Code Monkey logo

nest-winston's Introduction

Nest Logo

A Nest module wrapper for winston logger.

NPM version NPM downloads Travis build GitHub issues dependencies status devDependencies status

Installation

npm install --save nest-winston winston

Quick start

Import WinstonModule into the root AppModule and use the forRoot() method to configure it. This method accepts the same options object as createLogger() function from the winston package:

import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';

@Module({
  imports: [
    WinstonModule.forRoot({
      // options
    }),
  ],
})
export class AppModule {}

Afterward, the winston instance will be available to inject across entire project (and in your feature modules, being WinstonModule a global one) using the WINSTON_MODULE_PROVIDER injection token:

import { Controller, Inject } from '@nestjs/common';
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
import { Logger } from 'winston';

@Controller('cats')
export class CatsController {
  constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) { }
}

Async configuration

Caveats: because the way Nest works, you can't inject dependencies exported from the root module itself (using exports). If you use forRootAsync() and need to inject a service, that service must be either imported using the imports options or exported from a global module.

Maybe you need to asynchronously pass your module options, for example when you need a configuration service. In such case, use the forRootAsync() method, returning an options object from the useFactory method:

import { Module } from '@nestjs/common';
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';

@Module({
  imports: [
    WinstonModule.forRootAsync({
      useFactory: () => ({
        // options
      }),
      inject: [],
    }),
  ],
})
export class AppModule {}

The factory might be async, can inject dependencies with inject option and import other modules using the imports option.

Alternatively, you can use the useClass syntax:

WinstonModule.forRootAsync({
  useClass: WinstonConfigService,
})

With the above code, Nest will create a new instance of WinstonConfigService and its method createWinstonModuleOptions will be called in order to provide the module options.

Replacing the Nest logger

This module also provides the WinstonLogger class (custom implementation of the LoggerService interface) to be used by Nest for system logging. This will ensure consistent behavior and formatting across both Nest system logging and your application event/message logging.

Change your main.ts as shown below:

import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useLogger(app.get(WINSTON_MODULE_NEST_PROVIDER));
}
bootstrap();

Then inject the logger using the WINSTON_MODULE_NEST_PROVIDER token and the LoggerService typing:

import { Controller, Inject, LoggerService } from '@nestjs/common';
import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston';

@Controller('cats')
export class CatsController {
  constructor(@Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService) { }
}

Under the hood, the WinstonLogger class uses the configured winston logger instance (through forRoot or forRootAsync), forwarding all calls to it.

Replacing the Nest logger (also for bootstrapping)

Important: by doing this, you give up the dependency injection, meaning that forRoot and forRootAsync are not needed and shouldn't be used. Remove them from your main module.

Using the dependency injection has one minor drawback. Nest has to bootstrap the application first (instantiating modules and providers, injecting dependencies, etc.) and during this process the instance of WinstonLogger is not yet available, which means that Nest falls back to the internal logger.

One solution is to create the logger outside of the application lifecycle, using the createLogger function, and pass it to NestFactory.create. Nest will then wrap our winston logger (the same instance returned by the createLogger method) into the Logger class, forwarding all calls to it:

import { WinstonModule } from 'nest-winston';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, {
    logger: WinstonModule.createLogger({
      // options (same as WinstonModule.forRoot() options)
    })
  });
}
bootstrap();

Change your main module to provide the Logger service:

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

@Module({
  providers: [Logger],
})
export class AppModule {}

Then inject the logger simply by type hinting it with Logger from @nestjs/common:

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

@Controller('cats')
export class CatsController {
  constructor(private readonly logger: Logger) {}
}

Alternative syntax using the LoggerService typing and the @Inject decorator:

import { Controller, Inject, Logger, LoggerService } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  constructor(@Inject(Logger) private readonly logger: LoggerService) {}
}

Injection and usage summary

Here is a summary of the three techniques explained above:

Injection token and typing Module config Usage
WINSTON_MODULE_PROVIDER
Logger from winston
Yes + Your application/message logging
WINSTON_MODULE_NEST_PROVIDER
LoggerService from @nestjs/common
Yes + Your application/message logging
+ Nest logger
none
Logger from @nestjs/common
No + Your application/message logging
+ Nest logger
+ Application bootstrapping

Utilities

The module also provides a custom Nest-like special formatter for console transports:

import { Module } from '@nestjs/common';
import { utilities as nestWinstonModuleUtilities, WinstonModule } from 'nest-winston';
import * as winston from 'winston';

@Module({
  imports: [
    WinstonModule.forRoot({
      transports: [
        new winston.transports.Console({
          format: winston.format.combine(
            winston.format.timestamp(),
            nestWinstonModuleUtilities.format.nestLike(),
          ),
        }),
        // other transports...
      ],
      // other options
    }),
  ],
})
export class AppModule {}

Contributing

New features and bugfixes are always welcome! In order to contribute to this project, follow a few easy steps:

  1. Fork this repository, clone it on your machine and run npm install
  2. Open your local repository with Visual Studio Code and install all the suggested extensions
  3. Create a branch my-awesome-feature and commit to it
  4. Run npm run lint, npm run test and npm run build and verify that they complete without errors
  5. Push my-awesome-feature branch to GitHub and open a pull request

nest-winston's People

Contributors

gremo avatar ibrcko avatar j3bb9z avatar kadrian avatar kierans avatar mizozobu avatar nemanja-mudrinic avatar piranit avatar renovate-bot avatar renovate[bot] avatar trejgun avatar viceice avatar vorotech avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.