From a4334c224fa2767af6b394f22ea3aa00a466b311 Mon Sep 17 00:00:00 2001 From: pricelees Date: Tue, 9 Sep 2025 09:08:16 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EB=A1=9C=EA=B7=B8=20=EA=B0=80?= =?UTF-8?q?=EB=8F=85=EC=84=B1=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EB=A1=9C=EA=B7=B8=EC=97=90=20=EC=97=94=EB=93=9C?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/ExceptionControllerAdvice.kt | 22 ++++++++++++++++--- .../common/log/ApiLogMessageConverter.kt | 4 ++++ .../common/log/ControllerLoggingAspect.kt | 9 +++++--- .../common/log/ApiLogMessageConverterTest.kt | 4 +++- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/roomescape/common/exception/ExceptionControllerAdvice.kt b/src/main/kotlin/roomescape/common/exception/ExceptionControllerAdvice.kt index 25b83831..b7f0d101 100644 --- a/src/main/kotlin/roomescape/common/exception/ExceptionControllerAdvice.kt +++ b/src/main/kotlin/roomescape/common/exception/ExceptionControllerAdvice.kt @@ -2,6 +2,7 @@ package roomescape.common.exception import io.github.oshai.kotlinlogging.KLogger import io.github.oshai.kotlinlogging.KotlinLogging +import jakarta.servlet.http.HttpServletRequest import org.slf4j.MDC import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity @@ -14,6 +15,7 @@ import roomescape.common.dto.response.CommonErrorResponse import roomescape.common.log.ApiLogMessageConverter import roomescape.common.log.ConvertResponseMessageRequest import roomescape.common.log.LogType +import roomescape.common.log.getEndpoint private val log: KLogger = KotlinLogging.logger {} @@ -22,7 +24,10 @@ class ExceptionControllerAdvice( private val messageConverter: ApiLogMessageConverter ) { @ExceptionHandler(value = [RoomescapeException::class]) - fun handleRoomException(e: RoomescapeException): ResponseEntity { + fun handleRoomException( + servletRequest: HttpServletRequest, + e: RoomescapeException + ): ResponseEntity { val errorCode: ErrorCode = e.errorCode val httpStatus: HttpStatus = errorCode.httpStatus val errorResponse = CommonErrorResponse(errorCode) @@ -30,6 +35,7 @@ class ExceptionControllerAdvice( val type = if (e is AuthException) LogType.AUTHENTICATION_FAILURE else LogType.APPLICATION_FAILURE logException( type = type, + servletRequest = servletRequest, httpStatus = httpStatus.value(), errorResponse = errorResponse, exception = e @@ -41,7 +47,10 @@ class ExceptionControllerAdvice( } @ExceptionHandler(value = [MethodArgumentNotValidException::class, HttpMessageNotReadableException::class]) - fun handleInvalidRequestValueException(e: Exception): ResponseEntity { + fun handleInvalidRequestValueException( + servletRequest: HttpServletRequest, + e: Exception + ): ResponseEntity { val message: String = if (e is MethodArgumentNotValidException) { e.bindingResult.allErrors .mapNotNull { it.defaultMessage } @@ -57,6 +66,7 @@ class ExceptionControllerAdvice( logException( type = LogType.APPLICATION_FAILURE, + servletRequest = servletRequest, httpStatus = httpStatus.value(), errorResponse = errorResponse, exception = e @@ -68,7 +78,10 @@ class ExceptionControllerAdvice( } @ExceptionHandler(value = [Exception::class]) - fun handleException(e: Exception): ResponseEntity { + fun handleException( + servletRequest: HttpServletRequest, + e: Exception + ): ResponseEntity { log.error(e) { "[ExceptionControllerAdvice] Unexpected exception occurred: ${e.message}" } val errorCode: ErrorCode = CommonErrorCode.UNEXPECTED_SERVER_ERROR @@ -77,6 +90,7 @@ class ExceptionControllerAdvice( logException( type = LogType.UNHANDLED_EXCEPTION, + servletRequest = servletRequest, httpStatus = httpStatus.value(), errorResponse = errorResponse, exception = e @@ -89,12 +103,14 @@ class ExceptionControllerAdvice( private fun logException( type: LogType, + servletRequest: HttpServletRequest, httpStatus: Int, errorResponse: CommonErrorResponse, exception: Exception ) { val commonRequest = ConvertResponseMessageRequest( type = type, + endpoint = servletRequest.getEndpoint(), httpStatus = httpStatus, startTime = MDC.get("startTime")?.toLongOrNull(), body = errorResponse, diff --git a/src/main/kotlin/roomescape/common/log/ApiLogMessageConverter.kt b/src/main/kotlin/roomescape/common/log/ApiLogMessageConverter.kt index ff3cec66..dd41a26e 100644 --- a/src/main/kotlin/roomescape/common/log/ApiLogMessageConverter.kt +++ b/src/main/kotlin/roomescape/common/log/ApiLogMessageConverter.kt @@ -45,6 +45,7 @@ class ApiLogMessageConverter( fun convertToResponseMessage(request: ConvertResponseMessageRequest): String { val payload: MutableMap = mutableMapOf() payload["type"] = request.type + payload["endpoint"] = request.endpoint payload["status_code"] = request.httpStatus MDC.get(MDC_MEMBER_ID_KEY)?.toLongOrNull() @@ -75,8 +76,11 @@ class ApiLogMessageConverter( data class ConvertResponseMessageRequest( val type: LogType, + val endpoint: String, val httpStatus: Int = 200, val startTime: Long? = null, val body: Any? = null, val exception: Exception? = null ) + +fun HttpServletRequest.getEndpoint(): String = "${this.method} ${this.requestURI}" diff --git a/src/main/kotlin/roomescape/common/log/ControllerLoggingAspect.kt b/src/main/kotlin/roomescape/common/log/ControllerLoggingAspect.kt index 5ed3f8a6..6f31ac55 100644 --- a/src/main/kotlin/roomescape/common/log/ControllerLoggingAspect.kt +++ b/src/main/kotlin/roomescape/common/log/ControllerLoggingAspect.kt @@ -33,22 +33,25 @@ class ControllerLoggingAspect( val startTime: Long = MDC.get("startTime").toLongOrNull() ?: System.currentTimeMillis() val controllerPayload: Map = parsePayload(joinPoint) + val servletRequest: HttpServletRequest = servletRequest() + log.info { - messageConverter.convertToControllerInvokedMessage(servletRequest(), controllerPayload) + messageConverter.convertToControllerInvokedMessage(servletRequest, controllerPayload) } try { return joinPoint.proceed() - .also { logSuccess(startTime, it) } + .also { logSuccess(servletRequest.getEndpoint(), startTime, it) } } catch (e: Exception) { throw e } } - private fun logSuccess(startTime: Long, result: Any) { + private fun logSuccess(endpoint: String, startTime: Long, result: Any) { val responseEntity = result as ResponseEntity<*> var convertResponseMessageRequest = ConvertResponseMessageRequest( type = LogType.CONTROLLER_SUCCESS, + endpoint = endpoint, httpStatus = responseEntity.statusCode.value(), startTime = startTime, ) diff --git a/src/test/kotlin/roomescape/common/log/ApiLogMessageConverterTest.kt b/src/test/kotlin/roomescape/common/log/ApiLogMessageConverterTest.kt index 62eea129..eb12d955 100644 --- a/src/test/kotlin/roomescape/common/log/ApiLogMessageConverterTest.kt +++ b/src/test/kotlin/roomescape/common/log/ApiLogMessageConverterTest.kt @@ -50,14 +50,16 @@ class ApiLogMessageConverterTest : StringSpec({ } "Controller 응답 메시지를 반환한다." { + val endpoint = "POST /test/sangdol" val request = ConvertResponseMessageRequest( type = LogType.CONTROLLER_SUCCESS, + endpoint = endpoint, httpStatus = 200, exception = AuthException(AuthErrorCode.MEMBER_NOT_FOUND, "테스트 메시지!") ) converter.convertToResponseMessage(request) shouldBe """ - {"type":"CONTROLLER_SUCCESS","status_code":200,"member_id":1,"exception":{"class":"AuthException","message":"테스트 메시지!"}} + {"type":"CONTROLLER_SUCCESS","endpoint":"$endpoint","status_code":200,"member_id":1,"exception":{"class":"AuthException","message":"테스트 메시지!"}} """.trimIndent() } })