Skip to content

Commit 205760c

Browse files
committed
feat: implement dual logging with LoggerServiceFile (Winston) for info and LoggerServiceDb (MongoDB) for errors
1 parent 6242bfa commit 205760c

7 files changed

Lines changed: 61 additions & 29 deletions

File tree

src/app.module.ts

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,15 @@
11
import { Module } from '@nestjs/common';
2-
import { MongooseModule, MongooseModuleOptions } from '@nestjs/mongoose';
2+
import { MongooseModule } from '@nestjs/mongoose';
33
import { ConfigModule } from '@nestjs/config';
44
import { NotificationModule } from './notification/notification.module';
55
import { LoggerModule } from './logger/logger.module';
6-
import { LoggerService } from './logger/services/logger.service';
7-
import { Connection } from 'mongoose';
86

97
@Module({
108
imports: [
119
ConfigModule.forRoot({ isGlobal: true }),
12-
MongooseModule.forRootAsync({
13-
imports: [LoggerModule],
14-
useFactory: (logger: LoggerService) =>
15-
({
16-
uri: 'mongodb://localhost:27017/smartedu',
17-
connectionFactory: (connection: Connection) => {
18-
connection.on('connected', () => {
19-
logger.log('MongoDB connected successfully');
20-
});
21-
return connection;
22-
},
23-
}) as MongooseModuleOptions,
24-
inject: [LoggerService],
25-
}),
10+
MongooseModule.forRoot(
11+
process.env.MONGO_URI || 'mongodb://localhost:27017/smartedu',
12+
),
2613
NotificationModule,
2714
LoggerModule,
2815
],

src/filters/all-exceptions.filter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import {
55
HttpException,
66
} from '@nestjs/common';
77
import { Request, Response } from 'express';
8-
import { LoggerService } from '../logger/services/logger.service';
8+
import { LoggerServiceFile } from '../logger/services/logger.service.file';
99

1010
@Catch()
1111
export class AllExceptionsFilter implements ExceptionFilter {
12-
constructor(private readonly logger: LoggerService) {}
12+
constructor(private readonly logger: LoggerServiceFile) {}
1313

1414
catch(exception: unknown, host: ArgumentsHost) {
1515
const ctx = host.switchToHttp();

src/logger/logger.module.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Module } from '@nestjs/common';
22
import { MongooseModule } from '@nestjs/mongoose';
3-
import { LoggerService } from './services/logger.service';
3+
import { LoggerServiceFile } from './services/logger.service.file';
4+
import { LoggerServiceDb } from './services/logger.service.db';
45
import { LogRepository } from './infrastructure/repositories/log.repository';
56
import {
67
Logger,
@@ -12,13 +13,14 @@ import {
1213
MongooseModule.forFeature([{ name: Logger.name, schema: LoggerSchema }]),
1314
],
1415
providers: [
15-
LoggerService,
16+
LoggerServiceFile,
17+
LoggerServiceDb,
1618
LogRepository,
1719
{
1820
provide: 'ILogRepository',
1921
useClass: LogRepository,
2022
},
2123
],
22-
exports: [LoggerService, 'ILogRepository', LogRepository],
24+
exports: [LoggerServiceFile, LoggerServiceDb],
2325
})
2426
export class LoggerModule {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Injectable, Inject } from '@nestjs/common';
2+
import { ILogRepository } from '../domain/interfaces/log-repository.interface';
3+
4+
@Injectable()
5+
export class LoggerServiceDb {
6+
constructor(
7+
@Inject('ILogRepository') private readonly logRepository: ILogRepository,
8+
) {}
9+
10+
async error(
11+
message: string,
12+
trace?: string,
13+
metadata?: {
14+
recipient?: string;
15+
notificationType?: string;
16+
mediaType?: string;
17+
context?: string;
18+
},
19+
) {
20+
await this.logRepository.saveLog({
21+
level: 'error',
22+
message,
23+
trace,
24+
metadata,
25+
timestamp: new Date(),
26+
});
27+
}
28+
}

src/logger/services/logger.service.ts renamed to src/logger/services/logger.service.file.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as winston from 'winston';
33
import 'winston-daily-rotate-file';
44

55
@Injectable()
6-
export class LoggerService {
6+
export class LoggerServiceFile {
77
private readonly logger: winston.Logger;
88

99
constructor() {

src/main.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { NestFactory } from '@nestjs/core';
22
import { AppModule } from './app.module';
33
import { AllExceptionsFilter } from './filters/all-exceptions.filter';
4-
import { LoggerService } from './logger/services/logger.service';
4+
import { LoggerServiceFile } from './logger/services/logger.service.file';
5+
import { LoggerServiceDb } from './logger/services/logger.service.db';
56
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';
67

78
async function bootstrap() {
89
const app = await NestFactory.create(AppModule);
9-
const logger = app.get(LoggerService);
10+
const logger = app.get<LoggerServiceFile>(LoggerServiceFile);
11+
//const loggerDb = app.get(LoggerServiceDb);
1012
app.useGlobalFilters(new AllExceptionsFilter(logger));
1113

1214
// Configure Swagger
@@ -17,10 +19,19 @@ async function bootstrap() {
1719
.build();
1820
const document = SwaggerModule.createDocument(app, config);
1921
SwaggerModule.setup('api', app, document);
22+
console.log('Running the application on port 3000');
2023

2124
await app.listen(3000);
2225
logger.log('Application run successfully');
26+
console.log('Swagger is running on: http://localhost:3000/api');
2327
}
24-
bootstrap().catch((error) => {
28+
29+
bootstrap().catch(async (error: Error) => {
30+
const app = await NestFactory.create(AppModule);
31+
const loggerDb = app.get(LoggerServiceDb);
32+
await loggerDb.error('Error during application bootstrap', error.stack, {
33+
context: 'bootstrap',
34+
});
2535
console.log('Error during application bootstrap:', error);
36+
process.exit(1);
2637
});

src/notification/presentation/controllers/notification.controller.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import { SendNotificationDto } from '../dtos/send-notification.dto';
1313
import { Notification } from '../../domain/entities/notification.entity';
1414
import { INotificationStrategy } from '../../domain/interfaces/notification-strategy.interface';
1515
import { INotificationRepository } from '../../domain/interfaces/notification-repository.interface';
16-
import { LoggerService } from '../../../logger/services/logger.service';
16+
import { LoggerServiceFile } from '../../../logger/services/logger.service.file';
17+
import { LoggerServiceDb } from '../../../logger/services/logger.service.db';
1718

1819
@ApiTags('Notifications')
1920
@Controller('api/notifications')
@@ -22,7 +23,8 @@ export class NotificationController {
2223
private readonly notificationFactory: NotificationFactory,
2324
@Inject('INotificationRepository')
2425
private readonly notificationRepository: INotificationRepository,
25-
private readonly logger: LoggerService,
26+
private readonly logger: LoggerServiceFile,
27+
private readonly loggerDb: LoggerServiceDb,
2628
) {}
2729

2830
@Post()
@@ -61,15 +63,17 @@ export class NotificationController {
6163
// Send notification
6264
const strategy: INotificationStrategy =
6365
this.notificationFactory.createStrategy(dto.mediaType);
64-
console.log('notification strategy is created');
6566
await strategy.send(notification);
6667

68+
console.log('notification strategy creation ended');
69+
6770
// Save notification after successful send
6871
await this.notificationRepository.save(notification);
6972

7073
// Log successful send
7174
this.logger.log(
7275
`Notification (${dto.notificationType}) sent to ${dto.recipient} via ${dto.mediaType}`,
7376
);
77+
await this.loggerDb.error(`Exception occurred while sending notification`);
7478
}
7579
}

0 commit comments

Comments
 (0)