Skip to content

Instantly share code, notes, and snippets.

@codersidprogrammer
Last active January 30, 2023 03:22
Show Gist options
  • Save codersidprogrammer/7d5d7c46e75c8982d4be3e301943d9cd to your computer and use it in GitHub Desktop.
Save codersidprogrammer/7d5d7c46e75c8982d4be3e301943d9cd to your computer and use it in GitHub Desktop.
Penambahan interceptor untuk logging
export enum ActivityLogsType {
// This was use as index in logs database
INDEX = 'activity-logs',
HISTORICAL = 'historical-activity-logs',
// This was use as name of instance from interceptor
REQUEST = 'request',
INFO = 'activity:information',
ERROR = 'activity:error',
NOTFOUND_ERROR = 'activity:notfound-error',
SERVICE_ERROR = 'activity:service-error',
ADD = 'activity:add',
DELETE = 'activity:delete',
UPDATE = 'activity:update',
READ = 'activity:read',
HISTORY = 'activity:history',
}
import { IsNotEmpty } from 'class-validator';
import { ActivityLogsType } from '../constants/activity-log.constant';
export class ActivityLogDTO {
date?: Date;
@IsNotEmpty()
logName: string;
@IsNotEmpty()
logDetails: any;
additionalInfo?: AdditionalInfoDTO | AdditionalHistoricalDTO;
}
export interface AdditionalInfoDTO {
logType?: ActivityLogsType;
personalNumber?: number;
personalDetails?: any;
domain?: string;
durationMs?: number;
context?: any;
}
export interface AdditionalHistoricalDTO extends AdditionalInfoDTO {
historicalData: any;
}
import { Observable } from 'rxjs';
import { ActivityLogDTO } from '../dtos/activity-log.dto';
export interface ActivityLogServiceInterface {
/**
* Create activity log for every actions
*
* @param domain instance name. Usually it is class name
* @param log
*/
createActivityLog(domain: string, log: ActivityLogDTO): Observable<any>;
}
import {
CallHandler,
ExecutionContext,
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { PATH_METADATA } from '@nestjs/common/constants';
import { Reflector } from '@nestjs/core';
import { Observable, tap } from 'rxjs';
import { ActivityLogsType } from '../constants/activity-log.constant';
import { LogsService } from '../services/logs.service';
@Injectable()
export class ActivityLogsInterceptor implements NestInterceptor {
constructor(
private readonly logService: LogsService,
private readonly reflector: Reflector,
) {}
intercept(
context: ExecutionContext,
next: CallHandler<any>,
): Observable<any> | Promise<Observable<any>> {
const now = Date.now();
return next.handle().pipe(
tap(() =>
this.logService.createActivityLog(ActivityLogsType.REQUEST, {
logName: 'Request Interceptor',
logDetails: 'incoming request to API',
additionalInfo: {
durationMs: Date.now() - now,
context: {
path: this.reflector.get<string[]>(
PATH_METADATA,
context.getHandler(),
),
},
},
}),
),
);
}
}
// Penambahan di setiap modul
ClientsModule.register([
{
name: LogsServiceType.SERVICE_NAME,
transport: Transport.REDIS,
options: {
host: `${process.env.REDIS_HOST}`,
port: Number(process.env.REDIS_PORT),
},
},
]),
import { IsNotEmpty, IsString } from 'class-validator';
export default class LogsDTO<T> {
@IsString()
@IsNotEmpty()
index: string;
@IsNotEmpty()
document: T;
}
import { Observable } from 'rxjs';
export interface LogsServiceInterface<T, U> {
/**
* Creating log driver by using type of T
*
* @param data
*/
createLog(data: T): Observable<U>;
}
export enum LogsServiceType {
SERVICE_NAME = 'LOGS_SERVICE',
LOG_PATTERN = 'create-logs',
LOG_AUTH = 'auth-logs',
}
import { Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { Observable } from 'rxjs';
import { ActivityLogsType } from '../constants/activity-log.constant';
import {
ActivityLogDTO,
AdditionalHistoricalDTO,
} from '../dtos/activity-log.dto';
import LogsDTO from '../dtos/logs.dto';
import { ActivityLogServiceInterface } from '../interfaces/activity-log.service.interface';
import {
LogsServiceInterface,
LogsServiceType,
} from '../interfaces/logs.service.interface';
export class LogsService
implements
LogsServiceInterface<LogsDTO<any>, any>,
ActivityLogServiceInterface
{
constructor(
@Inject(LogsServiceType.SERVICE_NAME)
private readonly client: ClientProxy,
) {}
createActivityLog(
domain: string,
log: ActivityLogDTO,
logType: ActivityLogsType = ActivityLogsType.INFO,
): Observable<any> {
const _date = new Date();
const _input: LogsDTO<ActivityLogDTO> = {
index: ActivityLogsType.INDEX,
document: {
...log,
date: _date,
additionalInfo: {
...log.additionalInfo,
domain: domain,
logType: logType,
},
},
};
return this.createLog(_input);
}
createHistoricalLog(domain: string, log: ActivityLogDTO): Observable<any> {
const _date = new Date();
const _input: LogsDTO<ActivityLogDTO> = {
index: ActivityLogsType.HISTORICAL,
document: {
...log,
date: _date,
additionalInfo: {
personalNumber: log.additionalInfo.personalNumber,
personalDetails: log.additionalInfo.personalDetails,
domain: domain,
logType: ActivityLogsType.HISTORY,
historicalData: (log.additionalInfo as AdditionalHistoricalDTO)
.historicalData,
},
},
};
return this.createLog(_input);
}
createLog(data: LogsDTO<any>): Observable<any> {
return this.client.emit(LogsServiceType.LOG_PATTERN, data);
}
createAuthLog(data: LogsDTO<any>): Observable<any> {
return this.client.emit(LogsServiceType.LOG_AUTH, data);
}
}
//...
// Connection for Pub/Sub via redis
app.connectMicroservice<MicroserviceOptions>({
transport: Transport.REDIS,
options: {
host: `${process.env.REDIS_HOST}`,
port: Number(process.env.REDIS_PORT),
},
});
await app.startAllMicroservices();
await app.listen(PORT);
@Controller({
path: 'api/transaction',
version: '3',
})
@UseInterceptors(ActivityLogsInterceptor) // Tambahkan ini
export class TransactionTzController
extends BaseController
implements TransactionControllerInterface
{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment