nestjs / nest

A progressive Node.js framework for building efficient, scalable, and enterprise-grade server-side applications with TypeScript/JavaScript 🚀
https://nestjs.com
MIT License
67.16k stars 7.57k forks source link

[Question] Custom logger #247

Closed szkumorowski closed 6 years ago

szkumorowski commented 6 years ago

Is it possible to inject custom logger into nest components ?

szkumorowski commented 6 years ago

@chadjaros Totally agree

Best way and the simplest one - to forward on this topic is allow set for Nest

Then developers could do whatever they would like to do in this topic (disable, change colors which causes as well the errors on linux environments). Like in: http://typeorm.io/#/logging

kamilmysliwiec commented 6 years ago

Since v4.6.1 you can use your own logger implementation instead of default built-in one:

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

The Logger class has to implement LoggerService interface (@nestjs/common), for example:

class Logger implements LoggerService {
  log(message: string) {
    console.log(message);
  }
  error(message: string, trace: string) {
    console.error(message);
  }
  warn(message: string) {
    console.warn(message);
  }
}
chanlito commented 6 years ago

@kamilmysliwiec nice 🍾

chadjaros commented 6 years ago

Thank you! This is exactly what I wanted.

cojack commented 6 years ago

@kamilmysliwiec but this class is out of Nest scope, and there is no possibility to inject some services inside, Am I right?

kamilmysliwiec commented 6 years ago

@cojack yes, and actually it cannot be a part of Nest scope. This feature is only to provide an ability to override default logger (disable bootstrap messages/transport them elsewhere/etc.), it works independently. Logger starts to log messages before even 1 instance from Nest scope is instantiated. However, you are still able to use the same logger instance in Nest scope as well as a default logger, just provide it using useValue.

BorntraegerMarc commented 6 years ago

I didn't find any documentation about the custom logger feature on the official website. Is there already an open issue to add the docs for this new feature?

cojack commented 6 years ago

@kamilmysliwiec hmmm sound interesting. Please put this example in documentation.

FrancisVarga commented 6 years ago

Any documentation or example for this?

shekohex commented 6 years ago

@FrancisVarga Check this Comment https://github.com/nestjs/nest/issues/507#comment-374221089

jsdevtom commented 6 years ago

In large angular projects, I have had the experience of providing your logger in a common modules as detailed below. This has the advantage of a coherent logging when you also pass the logger to the NestFactory as @kamilmysliwiec details above:

common.module.ts

import { Module } from '@nestjs/common';
import { ConsoleLogger } from '../logger/logger';

const services = [
  ConsoleLogger,
];

@Module({
  providers: [
    ...services,
  ],
  exports: [
    ...services,
  ],
})
export class CommonModule {
}

where the logger looks like this:

logger.ts

import { Injectable, LoggerService } from '@nestjs/common';
import chalk from 'chalk';

@Injectable()
export class ConsoleLogger implements LoggerService {
  log(...messages: any[]) {
    // tslint:disable-next-line:no-console
    console.log(chalk.green(`log: [${ConsoleLogger.time()}]`), ...messages);
  }
  error(...messages: any[]) {
    // tslint:disable-next-line:no-console
    console.error(chalk.red(`error: [${ConsoleLogger.time()}]`), ...messages);
  }
  warn(...messages: any[]) {
    // tslint:disable-next-line:no-console
    console.warn(chalk.yellow(`warn: [${ConsoleLogger.time()}]`), ...messages);
  }
}

Then just inject the common module where you need it like so:

example.module.ts

import { Module } from '@nestjs/common';
import { ShopController } from './shop.controller';
import { ShopService } from './shop.service';
import { CommonModule } from '../common/common.module';

@Module({
  imports: [CommonModule],
  controllers: [ShopController],
  providers: [ShopService],
})
export class ShopModule {
}

and finally use it:

example.controller.ts

@Controller('example')
export class ShopController {

  constructor(
    private logger: ConsoleLogger,
  ) {

  @Get()
  root(): string {
    this.logger.log('hi'); // results in: log: [Sat, 23 Jun 2018 08:58:27 GMT] hi
  }

}
lock[bot] commented 5 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.