Skip to content

Commit

Permalink
feat : custom logger 구현 #35
Browse files Browse the repository at this point in the history
- interceptor를 활용하여 request, response logging.
- client ip, status , method, url, delay time logging.
- winston모듈을 이용하여 custome logger 구현.

Co-authored-by: LeeTH916 <[email protected]>
  • Loading branch information
GeunH and LeeTH916 committed Nov 20, 2023
1 parent 077ee57 commit 88e7fa9
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
12 changes: 11 additions & 1 deletion be/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ import { UserModule } from "./user/user.module";
import { TypeOrmModule } from "@nestjs/typeorm";
import { typeORMConfig } from "./configs/typeorm.config";
import { AuthModule } from "./auth/auth.module";
import { CustomLoggerService } from "./custom.logger";
import { APP_INTERCEPTOR } from '@nestjs/core';
import { LoggingInterceptor } from "./logger.interceptor";

@Module({
imports: [UserModule, TypeOrmModule.forRoot(typeORMConfig), AuthModule],
providers: [
CustomLoggerService,
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
],
})
export class AppModule {}
export class AppModule { }
55 changes: 55 additions & 0 deletions be/src/custom.logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { Injectable, LoggerService } from '@nestjs/common';
import * as winston from 'winston';

@Injectable()
export class CustomLoggerService implements LoggerService {
private logger: winston.Logger;

constructor() {
this.logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.printf(({ level, message, timestamp, stack = '' }) => {
return `${timestamp} ${level}: ${message} ${stack} `;
}),
),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],

});

if (process.env.NODE_ENV !== 'production') {
this.logger.add(new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
winston.format.printf(({ level, message, timestamp }) => {
return `${timestamp} ${level}: ${message}`;
})
),
}));
}
}

log(message: string) {
this.logger.info(message);
}

error(message: string, trace: string) {
this.logger.error({ message, stack: trace });
}

warn(message: string) {
this.logger.warn(message);
}

debug(message: string) {
this.logger.debug(message);
}

verbose(message: string) {
this.logger.verbose(message);
}
}
41 changes: 41 additions & 0 deletions be/src/logger.interceptor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// logging.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
HttpStatus
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { CustomLoggerService } from './custom.logger';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
constructor(private logger: CustomLoggerService) { }

intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const now = Date.now();
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
const { method, url } = request;
const clientIp = request.ip || request.headers['x-forwarded-for'];

return next
.handle()
.pipe(
tap(() => {
const { statusCode } = response;
const delay = Date.now() - now;
this.logger.log(`[Success] ${clientIp} ${method} ${url} ${statusCode} ${delay}ms`);
}),
catchError((error) => {
const status = error.status || HttpStatus.INTERNAL_SERVER_ERROR;
this.logger.error(`[Error] ${clientIp} ${method} ${url} ${status} ${error.message}`, error.stack);

return throwError(error);
}),
);
}

}

0 comments on commit 88e7fa9

Please sign in to comment.