From c92c1c247007d67162510e9b95c174ad54d92403 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Tue, 17 Jun 2025 17:32:16 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20logger=20=EC=97=90=EB=9F=AC?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80,=20prod=EB=AA=A8?= =?UTF-8?q?=EB=93=9C=EA=B0=80=20=EC=95=84=EB=8B=8C=20=EA=B2=BD=EC=9A=B0=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=83=9D=EC=84=B1=ED=95=98=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/logger.ts | 67 +++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/src/libs/logger.ts b/src/libs/logger.ts index ab73450..480d408 100644 --- a/src/libs/logger.ts +++ b/src/libs/logger.ts @@ -15,9 +15,14 @@ interface ApiLogData { body: string | undefined } +/* 현재 날짜 반환 함수 (YYYY-MM-DD 형식) */ +const getCurrentDate = (): string => { + return new Date().toISOString().split('T')[0] +} + /* 날짜별 로그 파일 경로 생성 함수 */ const getLogFilePath = (): string => { - const today = new Date().toISOString().split('T')[0] // YYYY-MM-DD 형식 + const today: string = getCurrentDate() return join(process.cwd(), 'logs', `onsite-survey-${today}.log`) } @@ -25,15 +30,10 @@ const getLogFilePath = (): string => { class DailyLogger { private currentDate: string private logger: pino.Logger - private destination: ReturnType + private destination?: ReturnType constructor() { - this.currentDate = new Date().toISOString().split('T')[0] - this.destination = pino.destination({ - dest: getLogFilePath(), - mkdir: true, - sync: false, - }) + this.currentDate = getCurrentDate() this.logger = this.createLogger() /* kill signal 핸들러 등록 */ @@ -42,14 +42,31 @@ class DailyLogger { } private async handleShutdown(): Promise { - this.destination.flushSync() - this.destination.end() + if (isProduction && this.destination) { + this.destination.flushSync() + this.destination.end() + } + this.logger.flush() } private createLogger(): pino.Logger { + if (!isProduction) return pino({ level: 'silent' }) + + /* 기존 destination 종료 */ + if (this.destination) { + this.destination.flushSync() + this.destination.end() + } + /* 새로운 destination 생성 */ + this.destination = pino.destination({ + dest: getLogFilePath(), + mkdir: true, + sync: false, + }) + return pino( { - level: isProduction ? 'info' : 'silent', + level: 'info', timestamp: pino.stdTimeFunctions.isoTime, }, this.destination, @@ -57,24 +74,16 @@ class DailyLogger { } public info(obj: any, msg?: string): void { - const today = new Date().toISOString().split('T')[0] - - if (today !== this.currentDate) { - /* 기존 destination 종료 */ - this.destination.flushSync() - this.destination.end() - - /* 새로운 destination 생성 */ - this.destination = pino.destination({ - dest: getLogFilePath(), - mkdir: true, - sync: false, - }) - this.currentDate = today - this.logger = this.createLogger() + try { + const today: string = getCurrentDate() + if (today !== this.currentDate) { + this.currentDate = today + this.logger = this.createLogger() + } + this.logger.info(obj, msg) + } catch (error) { + console.error(`[DailyLogger] Failed to write log: ${error}`) } - - this.logger.info(obj, msg) } } @@ -83,6 +92,8 @@ const dailyLogger = new DailyLogger() /* API 로그 기록 함수 */ export const writeApiLog = async (request: NextRequest, responseStatus: number): Promise => { + if (!isProduction) return + const logData: ApiLogData = { responseStatus: responseStatus, method: request.method, From 94da4f3452f69ddef0336de9c07e4b68a235babe Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Wed, 18 Jun 2025 12:21:03 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20log=20write=EC=8B=9C=20=EC=9D=B8?= =?UTF-8?q?=EC=BD=94=EB=94=A9=20=EA=B9=A8=EC=A7=80=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/logger.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libs/logger.ts b/src/libs/logger.ts index 480d408..54c46fd 100644 --- a/src/libs/logger.ts +++ b/src/libs/logger.ts @@ -94,13 +94,24 @@ const dailyLogger = new DailyLogger() export const writeApiLog = async (request: NextRequest, responseStatus: number): Promise => { if (!isProduction) return + let bodyString: string | undefined + if ( + request.method === 'POST' && + (request.headers.get('content-type') === 'multipart/form-data' || request.headers.get('content-type') === 'application/x-www-form-urlencoded') + ) { + const formData = await request.formData() + bodyString = JSON.stringify(Object.fromEntries(formData)) + } else { + bodyString = await request.text() + } + const logData: ApiLogData = { responseStatus: responseStatus, method: request.method, url: request.url, // headers: Object.fromEntries(request.headers), query: Object.fromEntries(new URL(request.url).searchParams), - body: request.body ? await request.text() : undefined, + body: bodyString, } dailyLogger.info(logData, 'API Request') }