diff --git a/apps/api/.env.example b/apps/api/.env.example index 3c1b2516..e59ca246 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -11,6 +11,9 @@ NODE_ENV= # Use "development" for graphql playground to work # Notification configuration MAX_RETRY_COUNT=3 # Max retry count, default is 3 +# Log Level +LOG_LEVEL=info # Log level, default is info + # Database configuration DB_TYPE= DB_HOST= diff --git a/apps/api/src/common/decorators/is-data-valid.decorator.ts b/apps/api/src/common/decorators/is-data-valid.decorator.ts index 58cee8a5..ba943c90 100644 --- a/apps/api/src/common/decorators/is-data-valid.decorator.ts +++ b/apps/api/src/common/decorators/is-data-valid.decorator.ts @@ -11,7 +11,7 @@ import { ChannelType } from 'src/common/constants/notifications'; import { SMTPDataDto } from 'src/modules/notifications/dtos/providers/smtp-data.dto'; import { MailgunDataDto } from 'src/modules/notifications/dtos/providers/mailgun-data.dto'; import { Wa360DialogDataDto } from 'src/modules/notifications/dtos/providers/wa360Dialog-data.dto'; -import { BadRequestException } from '@nestjs/common'; +import { BadRequestException, Logger } from '@nestjs/common'; import { CreateNotificationDto } from 'src/modules/notifications/dtos/create-notification.dto'; import { WaTwilioDataDto } from 'src/modules/notifications/dtos/providers/waTwilio-data.dto'; import { SmsTwilioDataDto } from 'src/modules/notifications/dtos/providers/smsTwilio-data.dto'; @@ -26,20 +26,28 @@ import { VcTwilioDataDto } from 'src/modules/notifications/dtos/providers/vcTwil @ValidatorConstraint({ name: 'isDataValidConstraint', async: true }) @Injectable() export class IsDataValidConstraint implements ValidatorConstraintInterface { - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async validate(value: object, args: ValidationArguments): Promise { + this.logger.debug('Request data validation started'); const object = args.object as { providerId: number; data: object }; let channelTypeFromProviderId = null; try { channelTypeFromProviderId = (await this.providersService.getById(object.providerId)) .channelType; + this.logger.debug( + `Fetched channel type: ${channelTypeFromProviderId} from provider Id: ${object.providerId}`, + ); } catch (error) { throw new Error(`Error while fetching channelType from ProviderId: ${error}`); } const validateAndThrowError = async (validationData: object): Promise => { + this.logger.debug('Awaiting Validation of request data as per request channel type'); const errors: ValidationError[] = await validate(validationData); if (errors.length > 0) { diff --git a/apps/api/src/common/guards/api-key/api-key.guard.ts b/apps/api/src/common/guards/api-key/api-key.guard.ts index 528c290f..62fcc71b 100644 --- a/apps/api/src/common/guards/api-key/api-key.guard.ts +++ b/apps/api/src/common/guards/api-key/api-key.guard.ts @@ -26,10 +26,15 @@ export class ApiKeyGuard implements CanActivate { async validateRequest(execContext: ExecutionContext): Promise { const request = execContext.switchToHttp().getRequest(); + this.logger.debug( + `Request validation started for request body: ${JSON.stringify(request.body)}`, + ); // Get api key header incase of http request if (request && request.headers) { + this.logger.debug(`Fetching request header and provider ID: ${request.body.providerId}`); const serverApiKeyHeader = request.headers['x-api-key']; + this.logger.debug('Fetching provider Id'); const requestProviderId = request.body.providerId; const validationResult = await this.validateApiKeyHeader( serverApiKeyHeader, @@ -44,6 +49,9 @@ export class ApiKeyGuard implements CanActivate { // Get api key header incase of graphql request const ctx = GqlExecutionContext.create(execContext); const req = ctx.getContext().req; + this.logger.debug( + `Fetching request header and provider ID for GraphQL: ${req.body.providerId}`, + ); const serverApiKeyHeader = req.headers['x-api-key']; const requestProviderId = request.body.providerId; const validationResult = await this.validateApiKeyHeader(serverApiKeyHeader, requestProviderId); @@ -59,6 +67,7 @@ export class ApiKeyGuard implements CanActivate { serverApiKeyHeader: string, requestProviderId: number, ): Promise { + this.logger.debug('validateApiKeyHeader started'); let apiKeyToken = null; if (serverApiKeyHeader) { @@ -69,6 +78,7 @@ export class ApiKeyGuard implements CanActivate { } const apiKeyEntry = await this.serverApiKeysService.findByServerApiKey(apiKeyToken); + this.logger.debug(`Fetching Server API Key from request token: ${JSON.stringify(apiKeyEntry)}`); if (!apiKeyEntry) { //this.logger.error('Invalid x-api-key'); @@ -77,6 +87,9 @@ export class ApiKeyGuard implements CanActivate { // Get channel type from providerId & Set the channelType based on providerEntry const providerEntry = await this.providersService.getById(requestProviderId); + this.logger.debug( + `Fetched providerEntry from DB (using request providerId): ${JSON.stringify(providerEntry)}`, + ); if (!providerEntry) { this.logger.error('Provider does not exist'); @@ -91,6 +104,9 @@ export class ApiKeyGuard implements CanActivate { // Set correct ApplicationId after verifying const inputApplicationId = await this.getApplicationIdFromApiKey(apiKeyToken); + this.logger.debug( + `Fetched ApplicationId from DB using APIKeyToken: ${JSON.stringify(inputApplicationId)}`, + ); if (inputApplicationId != providerEntry.applicationId) { this.logger.error('The applicationId for Server Key and Provider do not match.'); @@ -98,6 +114,9 @@ export class ApiKeyGuard implements CanActivate { } if (apiKeyToken && apiKeyToken === apiKeyEntry.apiKey) { + this.logger.debug( + 'Requested providerId is valid. The applicationId for Server Key and Provider match. Valid Request.', + ); return true; } diff --git a/apps/api/src/config/logger.config.ts b/apps/api/src/config/logger.config.ts index 2039b7e1..44ef91b0 100644 --- a/apps/api/src/config/logger.config.ts +++ b/apps/api/src/config/logger.config.ts @@ -3,6 +3,9 @@ import { transports, format } from 'winston'; import { join } from 'path'; import { v4 as uuidv4 } from 'uuid'; import 'winston-daily-rotate-file'; +import { ConfigService } from '@nestjs/config'; + +const configService = new ConfigService(); const logDir = 'logs'; const logFormat = format.combine( @@ -57,5 +60,6 @@ const transportsConfig = [ ]; export const loggerConfig = WinstonModule.createLogger({ + level: configService.get('LOG_LEVEL', 'info'), transports: transportsConfig, }); diff --git a/apps/api/src/jobs/consumers/notifications/notification.consumer.ts b/apps/api/src/jobs/consumers/notifications/notification.consumer.ts index f3fe4577..6cf8759b 100644 --- a/apps/api/src/jobs/consumers/notifications/notification.consumer.ts +++ b/apps/api/src/jobs/consumers/notifications/notification.consumer.ts @@ -33,18 +33,31 @@ export abstract class NotificationConsumer { try { this.logger.log(`Sending notification with id: ${id}`); + this.logger.debug( + `Processing notification queue for channel type: ${notification.channelType}`, + ); const result = await sendNotification(); if (SkipProviderConfirmationChannels.includes(notification.channelType)) { + this.logger.debug( + `Channel type: ${notification.channelType} is included in skip queue. Provider confirmation skipped for notification id ${notification.id}`, + ); notification.deliveryStatus = DeliveryStatus.SUCCESS; this.webhookService.triggerWebhook(notification); } else { + this.logger.debug( + `Notification id ${notification.id} is awaiting confirmation from provider`, + ); notification.deliveryStatus = DeliveryStatus.AWAITING_CONFIRMATION; } + this.logger.debug(`Updating result of notification with id ${notification.id}`); notification.result = { result }; } catch (error) { if (notification.retryCount < this.maxRetryCount) { + this.logger.debug( + `Some error occured while sendiing Notification with ID ${notification.id}. Retry Count ${notification.retryCount}/${this.maxRetryCount}. Sending notification again`, + ); notification.deliveryStatus = DeliveryStatus.PENDING; notification.retryCount++; } else { @@ -54,10 +67,14 @@ export abstract class NotificationConsumer { notification.deliveryStatus = DeliveryStatus.FAILED; } + this.logger.debug(`Updating result of notification with id ${notification.id}`); notification.result = { result: { message: error.message, stack: error.stack } }; this.logger.error(`Error sending notification with id: ${id}`); this.logger.error(JSON.stringify(error, ['message', 'stack'], 2)); } finally { + this.logger.debug( + `processNotificationQueue completed. Saving notification in DB: ${JSON.stringify(notification)}`, + ); await this.notificationRepository.save(notification); } } @@ -73,7 +90,11 @@ export abstract class NotificationConsumer { try { this.logger.log(`Checking delivery status from provider for notification with id: ${id}`); + this.logger.debug( + `Processing awaiting confirmation notification queue for channel type: ${notification.channelType}`, + ); const response = await getNotificationStatus(); + this.logger.debug(`Updating result of notification with id ${notification.id}`); notification.result = { result: response.result as Record }; notification.deliveryStatus = response.deliveryStatus; @@ -113,6 +134,9 @@ export abstract class NotificationConsumer { ); this.logger.error(JSON.stringify(error, ['message', 'stack'], 2)); } finally { + this.logger.debug( + `processAwaitingConfirmationNotificationQueue completed. Saving notification in DB: ${JSON.stringify(notification)}`, + ); await this.notificationRepository.save(notification); } } diff --git a/apps/api/src/jobs/producers/notifications/notifications.job.producer.ts b/apps/api/src/jobs/producers/notifications/notifications.job.producer.ts index 3709222a..8725a534 100644 --- a/apps/api/src/jobs/producers/notifications/notifications.job.producer.ts +++ b/apps/api/src/jobs/producers/notifications/notifications.job.producer.ts @@ -13,12 +13,17 @@ export class NotificationQueueProducer { ) {} async addNotificationToQueue(queueType: string, notification: Notification): Promise { + this.logger.debug('Started addNotificationToQueue'); const provider = await this.providersService.getById(notification.providerId); + this.logger.debug( + `Fetched provider ${JSON.stringify(provider)} from notification ${JSON.stringify(notification)}`, + ); const queue = this.queueService.getOrCreateQueue( queueType, provider.channelType.toString(), notification.providerId.toString(), ); + this.logger.debug(`Adding notification with id ${notification.id} to queue`); await queue.add(notification.id.toString(), { id: notification.id, providerId: notification.providerId, diff --git a/apps/api/src/modules/notifications/notifications.controller.ts b/apps/api/src/modules/notifications/notifications.controller.ts index 1b5b1286..4c1cc927 100644 --- a/apps/api/src/modules/notifications/notifications.controller.ts +++ b/apps/api/src/modules/notifications/notifications.controller.ts @@ -19,6 +19,7 @@ export class NotificationsController { ): Promise> { try { // ApiKeyGuard checks if requested providerId is valid, correct channelType and applicationId present + this.logger.debug(`Notification Request Data: ${JSON.stringify(notificationData)}`); const createdNotification = await this.notificationService.createNotification(notificationData); this.logger.log('Notification created successfully.'); diff --git a/apps/api/src/modules/notifications/notifications.service.ts b/apps/api/src/modules/notifications/notifications.service.ts index 5df468ca..bc4fea27 100644 --- a/apps/api/src/modules/notifications/notifications.service.ts +++ b/apps/api/src/modules/notifications/notifications.service.ts @@ -44,6 +44,9 @@ export class NotificationsService extends CoreService { // Set correct application name using applicationId notification.createdBy = await this.getApplicationNameFromId(notification.applicationId); notification.updatedBy = await this.getApplicationNameFromId(notification.applicationId); + this.logger.debug( + `New Notification created. Saving notification in DB: ${JSON.stringify(notification)}`, + ); return this.notificationRepository.save(notification); } @@ -89,12 +92,17 @@ export class NotificationsService extends CoreService { async addNotificationsToQueue(): Promise { this.logger.log('Starting CRON job to add pending notifications to queue'); + this.logger.debug(`isProcessingQueue value: ${this.isProcessingQueue}`); + if (this.isProcessingQueue) { this.logger.log('Notifications are already being added to queue, skipping this CRON job'); return; } this.isProcessingQueue = true; + this.logger.debug( + `isProcessingQueue value before initializing allPendingNotifications: ${this.isProcessingQueue}`, + ); let allPendingNotifications: Notification[] = []; try { @@ -103,6 +111,10 @@ export class NotificationsService extends CoreService { this.isProcessingQueue = false; this.logger.error('Error fetching pending notifications'); this.logger.error(JSON.stringify(error, null, 2)); + this.logger.debug( + `isProcessingQueue value when error fetching pending notifications: ${this.isProcessingQueue}`, + ); + return; } @@ -110,20 +122,37 @@ export class NotificationsService extends CoreService { for (const notification of allPendingNotifications) { try { + this.logger.debug( + `NotificationId: ${notification.id}, DeliveryStatus: ${notification.deliveryStatus}`, + ); notification.deliveryStatus = DeliveryStatus.IN_PROGRESS; + this.logger.debug( + `Updated deliveryStatus to ${DeliveryStatus.IN_PROGRESS}. Saving notification in DB: ${JSON.stringify(notification)}`, + ); await this.notificationRepository.save(notification); await this.notificationQueueService.addNotificationToQueue(QueueAction.SEND, notification); } catch (error) { + this.logger.debug( + `Error encountered. NotificationId: ${notification.id}, DeliveryStatus: ${notification.deliveryStatus}`, + ); notification.deliveryStatus = DeliveryStatus.PENDING; + this.logger.debug(`Updating result of notification with id ${notification.id}`); notification.result = { result: { message: error.message, stack: error.stack } }; this.logger.error(`Error adding notification with id: ${notification.id} to queue`); this.logger.error(JSON.stringify(error, null, 2)); + this.logger.debug( + `isProcessingQueue value while adding notification with id: ${notification.id} to queue: ${this.isProcessingQueue}`, + ); } finally { + this.logger.debug(`Saving notification in DB: ${JSON.stringify(notification)}`); await this.notificationRepository.save(notification); } } this.isProcessingQueue = false; + this.logger.debug( + `isProcessingQueue value after adding ${allPendingNotifications.length} pending notifications to queue: ${this.isProcessingQueue}`, + ); } async getProviderConfirmation(): Promise { @@ -131,6 +160,8 @@ export class NotificationsService extends CoreService { 'Starting CRON job to add notifications to queue for confirmation from provider', ); + this.logger.debug(`isProcessingConfirmationQueue value: ${this.isProcessingConfirmationQueue}`); + if (this.isProcessingConfirmationQueue) { this.logger.log( 'Notifications are already being added to confirmation queue, skipping this CRON job', @@ -139,6 +170,9 @@ export class NotificationsService extends CoreService { } this.isProcessingConfirmationQueue = true; + this.logger.debug( + `isProcessingConfirmationQueue value before initializing allAwaitingConfirmationNotifications: ${this.isProcessingConfirmationQueue}`, + ); let allAwaitingConfirmationNotifications: Notification[] = []; try { @@ -147,6 +181,9 @@ export class NotificationsService extends CoreService { this.isProcessingConfirmationQueue = false; this.logger.error('Error fetching awaiting confirmation notifications'); this.logger.error(JSON.stringify(error, null, 2)); + this.logger.debug( + `isProcessingConfirmationQueue value when error fetching awaiting confirmation notifications: ${this.isProcessingConfirmationQueue}`, + ); return; } @@ -156,21 +193,39 @@ export class NotificationsService extends CoreService { for (const notification of allAwaitingConfirmationNotifications) { try { + this.logger.debug( + `NotificationId: ${notification.id}, DeliveryStatus: ${notification.deliveryStatus}`, + ); notification.deliveryStatus = DeliveryStatus.QUEUED_CONFIRMATION; + this.logger.debug( + `Updated deliveryStatus to ${DeliveryStatus.QUEUED_CONFIRMATION}. Saving notification in DB: ${JSON.stringify(notification)}`, + ); await this.notificationRepository.save(notification); await this.notificationQueueService.addNotificationToQueue( QueueAction.DELIVERY_STATUS, notification, ); } catch (error) { + this.logger.debug( + `Error encountered. NotificationId: ${notification.id}, DeliveryStatus: ${notification.deliveryStatus}`, + ); notification.deliveryStatus = DeliveryStatus.AWAITING_CONFIRMATION; this.logger.error(`Error adding notification with id: ${notification.id} to queue`); this.logger.error(JSON.stringify(error, null, 2)); + this.logger.debug( + `isProcessingConfirmationQueue value while adding notification with id: ${notification.id} to queue: ${this.isProcessingConfirmationQueue}`, + ); + this.logger.debug( + `Updated Delivery status to ${DeliveryStatus.AWAITING_CONFIRMATION}. Saving notification in DB: ${JSON.stringify(notification)}`, + ); await this.notificationRepository.save(notification); } } this.isProcessingConfirmationQueue = false; + this.logger.debug( + `isProcessingConfirmationQueue value after adding ${allAwaitingConfirmationNotifications.length} awaiting confirmation notifications to queue: ${this.isProcessingConfirmationQueue}`, + ); } getPendingNotifications(): Promise { @@ -211,6 +266,7 @@ export class NotificationsService extends CoreService { // Get the applicationId currently being used for filtering data based on api key const filterApplicationId = await this.getApplicationIdFromApiKey(authorizationHeader); + this.logger.debug(`Fetch notifications with applicationId: ${filterApplicationId}`); const baseConditions = [ { field: 'status', value: Status.ACTIVE }, diff --git a/apps/api/src/modules/notifications/queues/queue.service.ts b/apps/api/src/modules/notifications/queues/queue.service.ts index cae059ed..a9a16f0b 100644 --- a/apps/api/src/modules/notifications/queues/queue.service.ts +++ b/apps/api/src/modules/notifications/queues/queue.service.ts @@ -72,6 +72,9 @@ export class QueueService { getOrCreateQueue(action: string, providerType: string, providerId: string): Queue { const queueName = `${action}-${providerType}-${providerId}`; + this.logger.debug( + `Started process getOrCreateQueue for (action-providerType-providerId): ${queueName}`, + ); if (!this.queues.has(queueName)) { this.logger.log(`Creating new queue and worker for ${queueName}`); @@ -84,6 +87,10 @@ export class QueueService { private createWorker(action: string, providerType: string, queueName: string): void { const processJob = async (job): Promise => { + this.logger.debug( + `Processing notification ${JSON.stringify(job.data)}. Searching for action ${action} for channel type ${providerType}`, + ); + switch (`${action}-${providerType}`) { // SMTP cases case `${QueueAction.SEND}-${ChannelType.SMTP}`: diff --git a/apps/api/src/modules/providers/mailgun/mailgun.module.ts b/apps/api/src/modules/providers/mailgun/mailgun.module.ts index 6add0c22..61858d2c 100644 --- a/apps/api/src/modules/providers/mailgun/mailgun.module.ts +++ b/apps/api/src/modules/providers/mailgun/mailgun.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { MailgunService } from './mailgun.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -6,7 +6,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [ConfigModule, ProvidersModule], - providers: [MailgunService, ProvidersService], + providers: [MailgunService, ProvidersService, Logger], exports: [MailgunService], }) export class MailgunModule {} diff --git a/apps/api/src/modules/providers/mailgun/mailgun.service.ts b/apps/api/src/modules/providers/mailgun/mailgun.service.ts index 07c4387a..49c022db 100644 --- a/apps/api/src/modules/providers/mailgun/mailgun.service.ts +++ b/apps/api/src/modules/providers/mailgun/mailgun.service.ts @@ -1,4 +1,4 @@ -import { Injectable, BadRequestException } from '@nestjs/common'; +import { Injectable, BadRequestException, Logger } from '@nestjs/common'; import * as FormData from 'form-data'; import Mailgun, { MailgunClientOptions, @@ -19,11 +19,15 @@ export class MailgunService { private mailgunClient: ReturnType; private mailgunDomain: string; - constructor(private readonly providersService: ProvidersService) { + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) { this.mailgun = new Mailgun(FormData); } async assignClient(providerId: number): Promise { + this.logger.debug('Started assigning mailgun client'); const mailgunConfig = await this.providersService.getConfigById(providerId); this.mailgunClient = this.mailgun.client({ username: 'api', @@ -39,6 +43,7 @@ export class MailgunService { ): Promise { try { await this.assignClient(providerId); + this.logger.debug('Sending Mailgun email'); return this.mailgunClient.messages.create(this.mailgunDomain, mailgunNotificationData); } catch (error) { throw new Error(`Failed to send message: ${error.message}`); @@ -48,6 +53,8 @@ export class MailgunService { async formatNotificationData( notificationData: Record, ): Promise> { + this.logger.debug('Formatting notification data for mailgun'); + if (notificationData.attachments) { const formattedNotificationData = { ...notificationData }; @@ -65,6 +72,7 @@ export class MailgunService { private async formatAttachments( attachments: CreateNotificationAttachmentDto[], ): Promise<{ filename: string; data: Buffer; contentType: string }[]> { + this.logger.debug('Formatting attachments for mailgun'); return Promise.all( attachments.map(async (attachment) => { let data: Buffer | string | Stream = attachment.content; @@ -92,10 +100,12 @@ export class MailgunService { async getDeliveryStatus(messageId: string, providerId: number): Promise { try { + this.logger.debug('Fetching delivery status from mailgun'); await this.assignClient(providerId); const response = await this.mailgunClient.events.get(this.mailgunDomain, { 'message-id': messageId, }); + this.logger.debug(`Delivery status: ${response.items[0]}`); return response.items[0]; } catch (error) { throw new Error(`Failed to fetch delivery status: ${error.message}`); diff --git a/apps/api/src/modules/providers/providers.service.ts b/apps/api/src/modules/providers/providers.service.ts index 347f2ff4..04491367 100644 --- a/apps/api/src/modules/providers/providers.service.ts +++ b/apps/api/src/modules/providers/providers.service.ts @@ -58,11 +58,13 @@ export class ProvidersService extends CoreService { } async getConfigById(providerId: number): Promise | null> { + this.logger.debug(`Fetching config for provider with id: ${providerId}`); const configEntity = await this.providerRepository.findOne({ where: { providerId, status: Status.ACTIVE }, }); if (configEntity) { + this.logger.debug('config entry fetched successfully'); return configEntity.configuration as unknown as Record; } diff --git a/apps/api/src/modules/providers/push-sns/push-sns.module.ts b/apps/api/src/modules/providers/push-sns/push-sns.module.ts index 72ad8da0..0ff377ac 100644 --- a/apps/api/src/modules/providers/push-sns/push-sns.module.ts +++ b/apps/api/src/modules/providers/push-sns/push-sns.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { PushSnsService } from './push-sns.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -6,7 +6,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [ConfigModule, ProvidersModule], - providers: [PushSnsService, ProvidersService], + providers: [PushSnsService, ProvidersService, Logger], exports: [PushSnsService], }) export class PushSnsModule {} diff --git a/apps/api/src/modules/providers/push-sns/push-sns.service.ts b/apps/api/src/modules/providers/push-sns/push-sns.service.ts index d84bb0cf..341aa319 100644 --- a/apps/api/src/modules/providers/push-sns/push-sns.service.ts +++ b/apps/api/src/modules/providers/push-sns/push-sns.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { SNS } from 'aws-sdk'; import { ProvidersService } from '../providers.service'; @@ -11,9 +11,13 @@ export interface PushSnsData { export class PushSnsService { private sns: SNS; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignSnsConfig(providerId: number): Promise { + this.logger.debug('Started assigning SNS client'); const snsConfig = await this.providersService.getConfigById(providerId); this.sns = new SNS({ @@ -33,6 +37,7 @@ export class PushSnsService { TargetArn: data.target, }; + this.logger.debug('Sending SNS push notification'); return this.sns.publish(params).promise(); } } diff --git a/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.module.ts b/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.module.ts index 7e165624..8dcbbb13 100644 --- a/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.module.ts +++ b/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { SmsKapsystemService } from './sms-kapsystem.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -7,7 +7,7 @@ import { HttpModule } from '@nestjs/axios'; @Module({ imports: [HttpModule, ConfigModule, ProvidersModule], - providers: [SmsKapsystemService, ProvidersService], + providers: [SmsKapsystemService, ProvidersService, Logger], exports: [SmsKapsystemService], }) export class SmsKapsystemModule {} diff --git a/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.service.ts b/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.service.ts index ec8bb32f..1c5e13d2 100644 --- a/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.service.ts +++ b/apps/api/src/modules/providers/sms-kapsystem/sms-kapsystem.service.ts @@ -1,5 +1,5 @@ import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { ProvidersService } from '../providers.service'; import { firstValueFrom } from 'rxjs'; @@ -34,9 +34,11 @@ export class SmsKapsystemService { constructor( private httpService: HttpService, private readonly providersService: ProvidersService, + private logger: Logger, ) {} async assignKAPSystemValues(providerId: number): Promise { + this.logger.debug('Started assigning KAPSystem values'); const smsKapsystemConfig = await this.providersService.getConfigById(providerId); this.apiUrl = smsKapsystemConfig.KAP_SMS_BASE_API_URL as string; this.username = smsKapsystemConfig.KAP_SMS_ACCOUNT_USERNAME as string; @@ -66,6 +68,7 @@ export class SmsKapsystemService { `?username=${this.username}&password=${this.password}&from=${this.from}&` + objToQueryString(body); + this.logger.debug('Sending KAPSystem SMS'); const response = await this.httpService.get(this.apiUrl); const res = await firstValueFrom(response); diff --git a/apps/api/src/modules/providers/sms-plivo/sms-plivo.module.ts b/apps/api/src/modules/providers/sms-plivo/sms-plivo.module.ts index 8c16d5ce..ed73a60b 100644 --- a/apps/api/src/modules/providers/sms-plivo/sms-plivo.module.ts +++ b/apps/api/src/modules/providers/sms-plivo/sms-plivo.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { SmsPlivoService } from './sms-plivo.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -6,7 +6,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [ConfigModule, ProvidersModule], - providers: [SmsPlivoService, ProvidersService], + providers: [SmsPlivoService, ProvidersService, Logger], exports: [SmsPlivoService], }) export class SmsPlivoModule {} diff --git a/apps/api/src/modules/providers/sms-plivo/sms-plivo.service.ts b/apps/api/src/modules/providers/sms-plivo/sms-plivo.service.ts index 69efdb5c..5b8c27dc 100644 --- a/apps/api/src/modules/providers/sms-plivo/sms-plivo.service.ts +++ b/apps/api/src/modules/providers/sms-plivo/sms-plivo.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as plivo from 'plivo'; import { ProvidersService } from '../providers.service'; @@ -50,9 +50,13 @@ export interface PlivoMessageStatusResponse { export class SmsPlivoService { private plivoClient; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignTransport(providerId: number): Promise { + this.logger.debug('Started assigning transport for SMS Plivo'); const smsPlivoConfig = await this.providersService.getConfigById(providerId); const authId = smsPlivoConfig.PLIVO_SMS_AUTH_ID as string; const authToken = smsPlivoConfig.PLIVO_SMS_AUTH_TOKEN as string; @@ -65,6 +69,7 @@ export class SmsPlivoService { const smsPlivoConfig = await this.providersService.getConfigById(providerId); const fromNumber = smsPlivoConfig.PLIVO_SMS_NUMBER as string; + this.logger.debug('Sending Plivo SMS'); const response = await this.plivoClient.messages.create({ src: fromNumber, dst: body.to, @@ -81,8 +86,10 @@ export class SmsPlivoService { providerId: number, ): Promise { try { + this.logger.debug('Fetching delivery status from Plivo SMS'); await this.assignTransport(providerId); const response = await this.plivoClient.messages.get(messageUuid); + this.logger.debug(`Delivery status: ${response}`); return response; } catch (error) { throw new Error(`Failed to fetch delivery status: ${error.message}`); diff --git a/apps/api/src/modules/providers/sms-twilio/sms-twilio.module.ts b/apps/api/src/modules/providers/sms-twilio/sms-twilio.module.ts index 6038c09f..e75b5023 100644 --- a/apps/api/src/modules/providers/sms-twilio/sms-twilio.module.ts +++ b/apps/api/src/modules/providers/sms-twilio/sms-twilio.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { SmsTwilioService } from './sms-twilio.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -6,7 +6,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [ConfigModule, ProvidersModule], - providers: [SmsTwilioService, ProvidersService], + providers: [SmsTwilioService, ProvidersService, Logger], exports: [SmsTwilioService], }) export class SmsTwilioModule {} diff --git a/apps/api/src/modules/providers/sms-twilio/sms-twilio.service.ts b/apps/api/src/modules/providers/sms-twilio/sms-twilio.service.ts index e8a3bce4..a9b4198c 100644 --- a/apps/api/src/modules/providers/sms-twilio/sms-twilio.service.ts +++ b/apps/api/src/modules/providers/sms-twilio/sms-twilio.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as Twilio from 'twilio'; import { ProvidersService } from '../providers.service'; @@ -34,9 +34,13 @@ export interface SmsTwilioResponseData { export class SmsTwilioService { private twilioClient; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignTransport(providerId: number): Promise { + this.logger.debug('Started assigning transport for SMS Twilio'); const smsTwilioConfig = await this.providersService.getConfigById(providerId); const accountSid = smsTwilioConfig.TWILIO_SMS_ACCOUNT_SID as string; const authToken = smsTwilioConfig.TWILIO_SMS_AUTH_TOKEN as string; @@ -48,6 +52,7 @@ export class SmsTwilioService { const smsTwilioConfig = await this.providersService.getConfigById(providerId); const fromSmsNumber = smsTwilioConfig.TWILIO_SMS_NUMBER as string; + this.logger.debug('Sending Twilio SMS'); const message = await this.twilioClient.messages.create({ body: body.message, from: fromSmsNumber, @@ -58,8 +63,10 @@ export class SmsTwilioService { async getDeliveryStatus(sid: string, providerId: number): Promise { try { + this.logger.debug('Fetching delivery status from twilio SMS'); await this.assignTransport(providerId); const message = await this.twilioClient.messages(sid).fetch(); + this.logger.debug(`Delivery status: ${message}`); return message; } catch (error) { throw new Error(`Failed to fetch delivery status: ${error.message}`); diff --git a/apps/api/src/modules/providers/smtp/smtp.module.ts b/apps/api/src/modules/providers/smtp/smtp.module.ts index 2cba6f6e..0cc023cd 100644 --- a/apps/api/src/modules/providers/smtp/smtp.module.ts +++ b/apps/api/src/modules/providers/smtp/smtp.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { SmtpService } from './smtp.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -6,7 +6,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [ConfigModule, ProvidersModule], - providers: [SmtpService, ProvidersService], + providers: [SmtpService, ProvidersService, Logger], exports: [SmtpService], }) export class SmtpModule {} diff --git a/apps/api/src/modules/providers/smtp/smtp.service.ts b/apps/api/src/modules/providers/smtp/smtp.service.ts index 3528d28a..55f3cf36 100644 --- a/apps/api/src/modules/providers/smtp/smtp.service.ts +++ b/apps/api/src/modules/providers/smtp/smtp.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as nodemailer from 'nodemailer'; import { ProvidersService } from '../providers.service'; @@ -6,9 +6,13 @@ import { ProvidersService } from '../providers.service'; export class SmtpService { private transporter: nodemailer.Transporter; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignTransport(providerId: number): Promise { + this.logger.debug('Started assigning smtp transport'); const smtpConfig = await this.providersService.getConfigById(providerId); this.transporter = nodemailer.createTransport({ host: smtpConfig.SMTP_HOST as string, @@ -25,6 +29,7 @@ export class SmtpService { providerId: number, ): Promise { await this.assignTransport(providerId); + this.logger.debug('Sending SMTP email'); return this.transporter.sendMail(smtpNotificationData); } } diff --git a/apps/api/src/modules/providers/vc-twilio/vc-twilio.module.ts b/apps/api/src/modules/providers/vc-twilio/vc-twilio.module.ts index a24db905..2df6298d 100644 --- a/apps/api/src/modules/providers/vc-twilio/vc-twilio.module.ts +++ b/apps/api/src/modules/providers/vc-twilio/vc-twilio.module.ts @@ -1,11 +1,11 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { VcTwilioService } from './vc-twilio.service'; import { ProvidersModule } from '../providers.module'; import { ProvidersService } from '../providers.service'; @Module({ imports: [ProvidersModule], - providers: [VcTwilioService, ProvidersService], + providers: [VcTwilioService, ProvidersService, Logger], exports: [VcTwilioService], }) export class VcTwilioModule {} diff --git a/apps/api/src/modules/providers/vc-twilio/vc-twilio.service.ts b/apps/api/src/modules/providers/vc-twilio/vc-twilio.service.ts index 5f247dd3..3665845c 100644 --- a/apps/api/src/modules/providers/vc-twilio/vc-twilio.service.ts +++ b/apps/api/src/modules/providers/vc-twilio/vc-twilio.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as Twilio from 'twilio'; import { ProvidersService } from '../providers.service'; @@ -85,9 +85,13 @@ export class VcTwilioService { private twilioClient; private twilioVoiceCallObject: Partial; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignTransport(providerId: number): Promise { + this.logger.debug('Started assigning transport for VC Twilio'); const vcTwilioConfig = await this.providersService.getConfigById(providerId); const accountSid = vcTwilioConfig.TWILIO_VC_ACCOUNT_SID as string; const authToken = vcTwilioConfig.TWILIO_VC_AUTH_TOKEN as string; @@ -146,6 +150,7 @@ export class VcTwilioService { // Function to create correct object for twilioClient and verify if one of url, twiml exist in request body this.twilioVoiceCallObject = {}; await this.filterRequestBody(body); + this.logger.debug('Sending Twilio VC'); const voiceCall = await this.twilioClient.calls.create(this.twilioVoiceCallObject); return voiceCall; } catch (error) { @@ -155,8 +160,10 @@ export class VcTwilioService { async getDeliveryStatus(sid: string, providerId: number): Promise { try { + this.logger.debug('Fetching delivery status from twilio VC'); await this.assignTransport(providerId); const message = await this.twilioClient.calls(sid).fetch(); + this.logger.debug(`Delivery status: ${message}`); return message; } catch (error) { throw new Error(`Failed to fetch delivery status: ${error.message}`); diff --git a/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.module.ts b/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.module.ts index 57b1a9aa..7bfcb2b1 100644 --- a/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.module.ts +++ b/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.module.ts @@ -1,11 +1,11 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { WaTwilioBusinessService } from './wa-twilio-business.service'; import { ProvidersModule } from '../providers.module'; import { ProvidersService } from '../providers.service'; @Module({ imports: [ProvidersModule], - providers: [WaTwilioBusinessService, ProvidersService], + providers: [WaTwilioBusinessService, ProvidersService, Logger], exports: [WaTwilioBusinessService], }) export class WaTwilioBusinessModule {} diff --git a/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.service.ts b/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.service.ts index 3a599c2f..b49a8207 100644 --- a/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.service.ts +++ b/apps/api/src/modules/providers/wa-twilio-business/wa-twilio-business.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as Twilio from 'twilio'; import { ProvidersService } from '../providers.service'; @@ -36,9 +36,13 @@ export interface WaTwilioBusinessResponseData { export class WaTwilioBusinessService { private twilioClient; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignTransport(providerId: number): Promise { + this.logger.debug('Started assigning transport for Whatsapp Business Twilio'); const waTwilioBusinessConfig = await this.providersService.getConfigById(providerId); const accountSid = waTwilioBusinessConfig.TWILIO_WA_ACCOUNT_SID as string; const authToken = waTwilioBusinessConfig.TWILIO_WA_AUTH_TOKEN as string; @@ -50,6 +54,7 @@ export class WaTwilioBusinessService { providerId: number, ): Promise { await this.assignTransport(providerId); + this.logger.debug('Sending Twilio Whatsapp Business'); const message = await this.twilioClient.messages.create({ contentSid: body.contentSid, from: body.from, @@ -61,8 +66,10 @@ export class WaTwilioBusinessService { async getDeliveryStatus(sid: string, providerId: number): Promise { try { + this.logger.debug('Fetching delivery status from twilio whatsapp Business'); await this.assignTransport(providerId); const message = await this.twilioClient.messages(sid).fetch(); + this.logger.debug(`Delivery status: ${message}`); return message; } catch (error) { throw new Error(`Failed to fetch delivery status: ${error.message}`); diff --git a/apps/api/src/modules/providers/wa-twilio/wa-twilio.module.ts b/apps/api/src/modules/providers/wa-twilio/wa-twilio.module.ts index 7ab493eb..2ea60d4f 100644 --- a/apps/api/src/modules/providers/wa-twilio/wa-twilio.module.ts +++ b/apps/api/src/modules/providers/wa-twilio/wa-twilio.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { WaTwilioService } from './wa-twilio.service'; import { ConfigModule } from '@nestjs/config'; import { ProvidersModule } from '../providers.module'; @@ -6,7 +6,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [ConfigModule, ProvidersModule], - providers: [WaTwilioService, ProvidersService], + providers: [WaTwilioService, ProvidersService, Logger], exports: [WaTwilioService], }) export class WaTwilioModule {} diff --git a/apps/api/src/modules/providers/wa-twilio/wa-twilio.service.ts b/apps/api/src/modules/providers/wa-twilio/wa-twilio.service.ts index 6452f732..581fe62d 100644 --- a/apps/api/src/modules/providers/wa-twilio/wa-twilio.service.ts +++ b/apps/api/src/modules/providers/wa-twilio/wa-twilio.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import * as Twilio from 'twilio'; import { ProvidersService } from '../providers.service'; @@ -34,9 +34,13 @@ export interface WaTwilioResponseData { export class WaTwilioService { private twilioClient; - constructor(private readonly providersService: ProvidersService) {} + constructor( + private readonly providersService: ProvidersService, + private logger: Logger, + ) {} async assignTransport(providerId: number): Promise { + this.logger.debug('Started assigning transport for Whatsapp Twilio'); const waTwilioConfig = await this.providersService.getConfigById(providerId); const accountSid = waTwilioConfig.TWILIO_WA_ACCOUNT_SID as string; const authToken = waTwilioConfig.TWILIO_WA_AUTH_TOKEN as string; @@ -54,6 +58,7 @@ export class WaTwilioService { from: `whatsapp:${fromWhatsAppNumber}`, to: `whatsapp:${body.to}`, }); + this.logger.debug('Sending Twilio Whatsapp'); return message; } catch (error) { throw new Error(`Failed to send message: ${error.message}`); @@ -62,8 +67,10 @@ export class WaTwilioService { async getDeliveryStatus(sid: string, providerId: number): Promise { try { + this.logger.debug('Fetching delivery status from twilio SMS'); await this.assignTransport(providerId); const message = await this.twilioClient.messages(sid).fetch(); + this.logger.debug(`Delivery status: ${message}`); return message; } catch (error) { throw new Error(`Failed to fetch delivery status: ${error.message}`); diff --git a/apps/api/src/modules/providers/wa360dialog/wa360dialog.module.ts b/apps/api/src/modules/providers/wa360dialog/wa360dialog.module.ts index 192d7eb4..cc69906d 100644 --- a/apps/api/src/modules/providers/wa360dialog/wa360dialog.module.ts +++ b/apps/api/src/modules/providers/wa360dialog/wa360dialog.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { Logger, Module } from '@nestjs/common'; import { Wa360dialogService } from './wa360dialog.service'; import { HttpModule } from '@nestjs/axios'; import { ConfigModule } from '@nestjs/config'; @@ -7,7 +7,7 @@ import { ProvidersService } from '../providers.service'; @Module({ imports: [HttpModule, ConfigModule, ProvidersModule], - providers: [Wa360dialogService, ProvidersService], + providers: [Wa360dialogService, ProvidersService, Logger], exports: [Wa360dialogService], }) export class Wa360dialogModule {} diff --git a/apps/api/src/modules/providers/wa360dialog/wa360dialog.service.ts b/apps/api/src/modules/providers/wa360dialog/wa360dialog.service.ts index fae6ce17..ba4ebcb2 100644 --- a/apps/api/src/modules/providers/wa360dialog/wa360dialog.service.ts +++ b/apps/api/src/modules/providers/wa360dialog/wa360dialog.service.ts @@ -1,5 +1,5 @@ import { HttpService } from '@nestjs/axios'; -import { Injectable } from '@nestjs/common'; +import { Injectable, Logger } from '@nestjs/common'; import { ProvidersService } from '../providers.service'; export interface Wa360DialogData { @@ -50,9 +50,11 @@ export class Wa360dialogService { constructor( private httpService: HttpService, private readonly providersService: ProvidersService, + private logger: Logger, ) {} async assignWA360Values(providerId: number): Promise { + this.logger.debug('Started assigning 360Dialog Whatsapp values'); const wa360Config = await this.providersService.getConfigById(providerId); this.apiUrl = wa360Config.WA_360_DIALOG_URL as string; this.apiKey = wa360Config.WA_360_DIALOG_API_KEY as string; @@ -64,6 +66,7 @@ export class Wa360dialogService { 'D360-API-KEY': this.apiKey, 'Content-Type': 'application/json', }; + this.logger.debug('Sending 360Dialog Whatsapp'); const response = await this.httpService.post(this.apiUrl, body, { headers }).toPromise(); return response.data; }