From a0a9dde8bdfa5921c69f35d198c7197b982d415b Mon Sep 17 00:00:00 2001 From: Jnnsu Date: Thu, 25 Apr 2024 16:46:51 +0900 Subject: [PATCH] =?UTF-8?q?Fix:=20=EB=A1=9C=EA=B7=B8=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/logger/logger.config.ts | 4 +-- src/common/logger/logger.middleware.ts | 35 ++++++++++++++++++++------ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/common/logger/logger.config.ts b/src/common/logger/logger.config.ts index 7c88444..f84d210 100644 --- a/src/common/logger/logger.config.ts +++ b/src/common/logger/logger.config.ts @@ -1,6 +1,6 @@ import * as winston from 'winston'; import moment from 'moment-timezone'; -import appRoot from 'app-root-path'; +import appRootPath from 'app-root-path'; export const appendTimestamp = winston.format((info, opts) => { if (opts.tz) { @@ -14,7 +14,7 @@ export const dailyOptions = (level: string) => { return { level: 'info', datePattern: 'YYYY-MM-DD', // 날짜 포맷 - dirname: `${appRoot.path}/logs` + `/${level}`, // 저장할 URL: 여기서는 루트에 logs라는 폴더가 생기고 그 아래에 level 폴더 + dirname: `${appRootPath.path}/logs` + `/${level}`, // 저장할 URL: 여기서는 루트에 logs라는 폴더가 생기고 그 아래에 level 폴더 filename: `%DATE%.${level}.log`, maxFiles: 20, // 보관할 최대 로그 수 zippedArchive: true, // 로그가 쌓였을 때 압축 diff --git a/src/common/logger/logger.middleware.ts b/src/common/logger/logger.middleware.ts index 49e07c1..3731419 100644 --- a/src/common/logger/logger.middleware.ts +++ b/src/common/logger/logger.middleware.ts @@ -3,19 +3,40 @@ import { Request, Response, NextFunction } from 'express'; @Injectable() export class LoggingMiddleware implements NestMiddleware { - private logger = new Logger('HTTP'); //HTTP 로그를 기록하는 logger 프로퍼티를 선언 + private logger = new Logger('HTTP'); + use(req: Request, res: Response, next: NextFunction) { - //미들웨어 로직을 정의 - const { ip, method, originalUrl } = req; //IP 주소, HTTP 메서드 및 원본 URL을 추출 + const { ip, method, originalUrl } = req; const userAgent = req.get('user-agent') || ''; - res.on('finish', () => { - //로깅 상세설정 + const reqHeaders = JSON.stringify(req.headers); + const reqBody = JSON.stringify(req.body); + + const chunks: Buffer[] = []; + + const originalWrite = res.write.bind(res); + res.write = (...args: any[]) => { + chunks.push(Buffer.from(args[0])); + return originalWrite(...args); + }; + + const originalEnd = res.end.bind(res); + res.end = (...args: any[]) => { + if (args[0]) { + chunks.push(Buffer.from(args[0])); + } + const responseBody = Buffer.concat(chunks).toString('utf-8'); + const resHeaders = JSON.stringify(res.getHeaders()); + const { statusCode, statusMessage } = res; const logLevel = statusCode >= 400 ? 'error' : 'log'; + this.logger[logLevel]( - `Request from ${ip} to ${method} ${originalUrl} - ${statusCode} ${statusMessage} - ${userAgent}`, + `Request from ${ip} to ${method} ${originalUrl} - ${statusCode} ${statusMessage} - ${userAgent} \nReq Headers: ${reqHeaders} \nReq Body: ${reqBody} \nRes Headers: ${resHeaders} \nRes Body: ${responseBody}`, ); - }); + + return originalEnd(...args); + }; + next(); } }