I have a web application on Nest.js where I make use of pino to log exceptions .
Service1.ts
import {Logger} from 'nestjs-pino';
export class Service1{
constructor(private readonly logger : Logger) {}
async Do()
{
...
this.logger.log("Log1");
}
}
Service2.ts
import {Logger} from 'nestjs-pino';
export class Service2{
constructor(private readonly logger : Logger) {}
async DoOtherWork()
{
...
this.logger.log("Log1");
}
}
Since the Service files will be called from multiple UI operations so my understanding is multiple Logger classes will be created . So , is it a good idea to have Logger as a Singleton class ?
How can I make changes to the Nest.js application to have Logger as a singleton class with thread safety?
I have a web application on Nest.js where I make use of pino to log exceptions .
Service1.ts
import {Logger} from 'nestjs-pino';
export class Service1{
constructor(private readonly logger : Logger) {}
async Do()
{
...
this.logger.log("Log1");
}
}
Service2.ts
import {Logger} from 'nestjs-pino';
export class Service2{
constructor(private readonly logger : Logger) {}
async DoOtherWork()
{
...
this.logger.log("Log1");
}
}
Since the Service files will be called from multiple UI operations so my understanding is multiple Logger classes will be created . So , is it a good idea to have Logger as a Singleton class ?
How can I make changes to the Nest.js application to have Logger as a singleton class with thread safety?
Share Improve this question asked Mar 17 at 14:27 VA1267VA1267 3253 silver badges12 bronze badges 1- Yes you can use middleware concept of nestjs and create a logger middleware – Kazi Akib Javed Commented Mar 19 at 4:48
1 Answer
Reset to default 0In 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');
}
}