From ad2499618bc3cc967ccda8b03a716dce591e8fd0 Mon Sep 17 00:00:00 2001 From: gregorsulcer Date: Fri, 15 Dec 2023 10:57:09 +0100 Subject: [PATCH] feat: rabbitMQ --- src/app.module.ts | 16 ++++++++-- src/main.ts | 2 ++ src/middleware/logger.middleware.ts | 47 +++++++++++++++++++++++++++++ src/rabbitmq/rabbitmq.ts | 29 ++++++++++++++++++ 4 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 src/middleware/logger.middleware.ts create mode 100644 src/rabbitmq/rabbitmq.ts diff --git a/src/app.module.ts b/src/app.module.ts index 9286622..8bed3b4 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,4 +1,9 @@ -import { Module } from '@nestjs/common'; +import { + MiddlewareConsumer, + Module, + NestModule, + RequestMethod, +} from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import * as process from 'process'; @@ -9,6 +14,7 @@ import { OffersModule } from './api/offers/offers.module'; import { ConfigModule, ConfigService } from '@nestjs/config'; import configuration from './config/configuration'; import { HttpModule } from '@nestjs/axios'; +import { LoggerMiddleware } from './middleware/logger.middleware'; @Module({ imports: [ @@ -32,4 +38,10 @@ import { HttpModule } from '@nestjs/axios'; controllers: [AppController], providers: [AppService], }) -export class AppModule {} +export class AppModule implements NestModule { + configure(consumer: MiddlewareConsumer) { + consumer + .apply(LoggerMiddleware) + .forRoutes({ path: '*', method: RequestMethod.ALL }); + } +} diff --git a/src/main.ts b/src/main.ts index d466655..5084c83 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,11 +5,13 @@ import { Logger as NestLogger } from '@nestjs/common'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import 'dotenv/config'; import * as process from 'process'; +import { setupRabbitMQ } from './rabbitmq/rabbitmq'; async function bootstrap() { const app = await NestFactory.create(AppModule, { cors: { origin: '*' } }); app.setGlobalPrefix('api/v1'); app.useGlobalPipes(new ValidationPipe()); + setupRabbitMQ(); const config = new DocumentBuilder() .setTitle('Discounts-service api') diff --git a/src/middleware/logger.middleware.ts b/src/middleware/logger.middleware.ts new file mode 100644 index 0000000..4f99b98 --- /dev/null +++ b/src/middleware/logger.middleware.ts @@ -0,0 +1,47 @@ +import { Injectable, NestMiddleware } from '@nestjs/common'; +import { NextFunction, Request, Response } from 'express'; +import { v4 as uuidd } from 'uuid'; +import * as process from 'process'; +import { getRabbitMQChannel } from '../rabbitmq/rabbitmq'; + +@Injectable() +export class LoggerMiddleware implements NestMiddleware { + use(req: Request, res: Response, next: NextFunction) { + if (next) { + next(); + } + + const correlationIdHeader = 'X-Correlation-Id'; + if (!req[correlationIdHeader]) { + req.headers[correlationIdHeader] = uuidd(); + } + + const timestamp = new Date().toISOString(); + const urlString = `${req.protocol}://${req.get('host')}${req.originalUrl}`; + const serviceName = '[discounts-service]'; + const message = `<* ${req.method} ${req.originalUrl} *>`; + + res.on('finish', () => { + const { statusCode } = res; + + const log = { + timestamp, + type: statusCode >= 500 ? 'ERROR' : statusCode >= 400 ? 'WARN' : 'INFO', + correlationId: req.headers[correlationIdHeader], + urlString, + message, + serviceName, + }; + + const rabbitMQChannel = getRabbitMQChannel(); + if (rabbitMQChannel) { + rabbitMQChannel.publish( + process.env.RABBITMQ_EXCHANGE, + '', + Buffer.from(JSON.stringify(log)), + ); + console.log('Log message sent to RabbitMQ:', log); + } + }); + } +} diff --git a/src/rabbitmq/rabbitmq.ts b/src/rabbitmq/rabbitmq.ts new file mode 100644 index 0000000..f8a9e9e --- /dev/null +++ b/src/rabbitmq/rabbitmq.ts @@ -0,0 +1,29 @@ +import * as process from 'process'; +import * as amqp from 'amqplib/callback_api'; + +const rabbitMQURL = process.env.RABBITMQ_URL; +const rabbitMQExchange = process.env.EXCHANGE_NAME; +const rabbitMQQueue = process.env.QUEUE_NAME; +let rabbitMQChannel: amqp.Channel; + +export const setupRabbitMQ = () => { + try { + amqp.connect(rabbitMQURL, (error0, connection) => { + if (error0) throw error0; + + connection.createChannel((error1, channel) => { + if (error1) throw error1; + + channel.assertExchange(rabbitMQExchange, 'direct', { durable: true }); + channel.assertQueue(rabbitMQQueue, { durable: true }); + channel.bindQueue(rabbitMQQueue, rabbitMQExchange, ''); + rabbitMQChannel = channel; + console.log('Connected to RabbitMQ'); + }); + }); + } catch (e) { + console.log(e); + } +}; + +export const getRabbitMQChannel = () => rabbitMQChannel;