In NestJS, the Logger from nestjs-pino is already designed to be a singleton when injected properly as a provider.
If you directly instantiate it in the service, it won't be a singleton.
If you do:
import { Module } from '@nestjs/common';
import { LoggerModule } from 'nestjs-pino';
@Module({
imports: [
LoggerModule.forRoot({
pinoHttp: {
level: 'info',
},
}),
],
exports: [LoggerModule],
})
export class AppModule {}
and service1
import { Injectable } from '@nestjs/common';
import { Logger } from 'nestjs-pino';
@Injectable()
export class Service1 {
constructor(private readonly logger: Logger) {}
async Do() {
this.logger.log('Log1');
}
}
and service2
import { Injectable } from '@nestjs/common';
import { Logger } from 'nestjs-pino';
@Injectable()
export class Service2 {
constructor(private readonly logger: Logger) {}
async DoOtherWork() {
this.logger.info('Log2');
}
}
and have a module like this:
import { Module } from '@nestjs/common';
import { Service1 } from './service1';
import { Service2 } from './service2';
@Module({
providers: [Service1, Service2],
exports: [Service1, Service2],
})
export class SomeModule {}
The same Logger instance will be injected into Service1 and Service2.
What i think you are interested is set the context for the service, the nestjs-pino documentation mentions that:
export class MyService {
constructor(
private readonly logger: PinoLogger
) {
// Optionally you can set context for logger in constructor or ...
this.logger.setContext(MyService.name);
}
constructor(
// ... set context via special decorator
@InjectPinoLogger(MyService.name)
private readonly logger: PinoLogger
) {}
foo() {
// PinoLogger has same methods as pino instance
this.logger.trace({ foo: 'bar' }, 'baz %s', 'qux');
this.logger.debug('foo %s %o', 'bar', { baz: 'qux' });
this.logger.info('foo');
}
}