brocoders / nestjs-boilerplate

NestJS boilerplate. Auth, TypeORM, Mongoose, Postgres, MongoDB, Mailing, I18N, Docker.
https://nestjs-boilerplate-test.herokuapp.com/docs
MIT License
2.98k stars 598 forks source link

No logger is set up #908

Open maxxims opened 1 year ago

maxxims commented 1 year ago

An important part of any new project is having a good logging system set up from the very first beginning. Taking into consideration the current best practices, could you please add a nice logging system to the boilerplate?

Shchepotin commented 1 year ago

@maxxims I'll consider your proposal

Shchepotin commented 1 year ago

@igolubic for sharing your solution please use "Awesome" repos. Thanks for understanding.

pauljonescodes commented 1 year ago

For what it's worth, my solution to this right now is to have this at the top of all my classes where I'd like a logger:

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

@Injectable()
export class FilesService {
  private readonly logger = new Logger(FilesService.name);

  // ...
}

Having said that, I could see there being some sense in making this injectable module/service too, so there's a single place they could processed and filtered.

pauljonescodes commented 1 year ago

I had another chance to think about this and came up with the following:

import { Module } from '@nestjs/common';
import { AppLogger } from './app.logger.js';

/* logger module */

@Module({
  providers: [AppLogger],
  exports: [AppLogger],
})
export class LoggerModule {}

/* app logger service */

@Injectable({ scope: Scope.TRANSIENT })
export class AppLogger extends ConsoleLogger {}

/* example usage module */

@Module({
  imports: [
    LoggerModule,
    // etc
  ],
  controllers: [],
  providers: [FilesService],
  exports: [FilesService],
})
export class FilesModule {}

/* example usage service */

@Injectable()
export class FilesService {

  constructor(
    protected readonly logger: AppLogger
  ) {
    logger.setContext(FilesService.name);
  }

  async upload(file: Express.Multer.File): Promise<FileEntity> {
    this.logger.verbose(this.upload.name);
    //etc
  }
}
pauljonescodes commented 12 months ago

I've had some more time to think about this, I recommend the module solution for those that have centralized logging needs, like storing to file or uploading to a particular service or varying by environment, however I think Nest's default is the best go-to approach as it does not involve another module:

export class FilesService {
  private readonly logger = new Logger(FilesService.name);
  private readonly s3: S3;

  constructor(
    @InjectRepository(FileEntity)
    private readonly fileRepository: Repository<FileEntity>,
    @Inject(FilesConfig.KEY)
    private config: ConfigType<typeof FilesConfig>,
  ) {
    this.logger.verbose(this.constructor.name);
    // ...
  }

  async upload(file: Express.Multer.File): Promise<FileEntity> {
    this.logger.verbose(this.upload.name);
    // ...
   }
}

If you ever want to re-use your code in another Nest project, having an AppLogger dependency would be a drag, unless it is actually part of the module's requirements.

tukusejssirs commented 6 months ago

Consider using Ogma Logger.