Need help with nest-winston?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

gremo
256 Stars 36 Forks MIT License 727 Commits 13 Opened issues

Description

A Nest module wrapper form winston logger

Services available

!
?

Need anything else?

Contributors list

# 26
netlify
TypeScr...
GraphQL
javascr...
325 commits
# 303,768
Symfony
PHP
google-...
CSS
96 commits
# 73,871
Kotlin
Shell
Java
Node.js
3 commits
# 21,659
bitbuck...
html5
vuejs
Clojure
2 commits
# 574,039
Raspber...
C++
CSS
octopri...
1 commit
# 172,071
wiki-en...
jQuery
HTML
nextjs
1 commit
# 65,482
HTML
Nest
TypeScr...
lodash
1 commit
# 649,854
JavaScr...
TypeScr...
1 commit
# 96,994
cldr
C++
C
jqgrid
1 commit
# 483,491
Shell
HTML
CSS
csp
1 commit

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

Having troubles configuring

nest-winston
? Clone this repository and
cd
in a sample:
cd sample/quick-start
npm install
npm run start:dev

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)); await app.listen(3000); } 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) }) }); await app.listen(3000); } 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(), winston.format.ms(), nestWinstonModuleUtilities.format.nestLike('MyApp', { prettyPrint: true }), ), }), // 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

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.