generated from pricelees/issue-pr-template
[#48] Tosspay mocking 서버 구현을 위한 멀티모듈 전환 #49
@ -14,6 +14,10 @@ enum class HttpStatus(
|
||||
INTERNAL_SERVER_ERROR(500)
|
||||
;
|
||||
|
||||
fun isClientError(): Boolean {
|
||||
return code in 400..<500
|
||||
}
|
||||
|
||||
fun value(): Int {
|
||||
return code
|
||||
}
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
package com.sangdol.common.log.web
|
||||
package com.sangdol.common.web.asepct
|
||||
|
||||
import com.sangdol.common.log.config.LogType
|
||||
import com.sangdol.common.log.message.ApiLogMessageConverter
|
||||
import com.sangdol.common.log.message.ConvertResponseMessageRequest
|
||||
import com.sangdol.common.log.message.getEndpoint
|
||||
import com.sangdol.common.log.constant.LogType
|
||||
import com.sangdol.common.web.support.log.WebLogMessageConverter
|
||||
import io.github.oshai.kotlinlogging.KLogger
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
@ -13,7 +11,6 @@ import org.aspectj.lang.annotation.Around
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Pointcut
|
||||
import org.aspectj.lang.reflect.MethodSignature
|
||||
import org.slf4j.MDC
|
||||
import org.springframework.http.ResponseEntity
|
||||
import org.springframework.web.bind.annotation.PathVariable
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
@ -25,7 +22,7 @@ private val log: KLogger = KotlinLogging.logger {}
|
||||
|
||||
@Aspect
|
||||
class ControllerLoggingAspect(
|
||||
private val messageConverter: ApiLogMessageConverter,
|
||||
private val messageConverter: WebLogMessageConverter,
|
||||
) {
|
||||
|
||||
@Pointcut("execution(* com.sangdol..web..*Controller*.*(..))")
|
||||
@ -34,10 +31,8 @@ class ControllerLoggingAspect(
|
||||
|
||||
@Around("allController()")
|
||||
fun logAPICalls(joinPoint: ProceedingJoinPoint): Any? {
|
||||
val startTime: Long = MDC.get("startTime").toLongOrNull() ?: System.currentTimeMillis()
|
||||
val controllerPayload: Map<String, Any> = parsePayload(joinPoint)
|
||||
|
||||
val servletRequest: HttpServletRequest = servletRequest()
|
||||
val controllerPayload: Map<String, Any> = parseControllerPayload(joinPoint)
|
||||
|
||||
log.info {
|
||||
messageConverter.convertToControllerInvokedMessage(servletRequest, controllerPayload)
|
||||
@ -45,29 +40,22 @@ class ControllerLoggingAspect(
|
||||
|
||||
try {
|
||||
return joinPoint.proceed()
|
||||
.also { logSuccess(servletRequest.getEndpoint(), startTime, it) }
|
||||
.also { logSuccess(servletRequest, it as ResponseEntity<*>) }
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
private fun logSuccess(servletRequest: HttpServletRequest, result: ResponseEntity<*>) {
|
||||
val body: Any? = if (log.isDebugEnabled()) result.body else null
|
||||
|
||||
val logMessage = messageConverter.convertToResponseMessage(
|
||||
type = LogType.SUCCEED,
|
||||
servletRequest = servletRequest,
|
||||
httpStatusCode = result.statusCode.value(),
|
||||
responseBody = body,
|
||||
)
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
convertResponseMessageRequest = convertResponseMessageRequest.copy(
|
||||
body = responseEntity.body
|
||||
)
|
||||
}
|
||||
|
||||
val logMessage = messageConverter.convertToResponseMessage(convertResponseMessageRequest)
|
||||
|
||||
log.info { logMessage }
|
||||
}
|
||||
|
||||
@ -75,14 +63,16 @@ class ControllerLoggingAspect(
|
||||
return (RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes).request
|
||||
}
|
||||
|
||||
private fun parsePayload(joinPoint: JoinPoint): Map<String, Any> {
|
||||
private fun parseControllerPayload(joinPoint: JoinPoint): Map<String, Any> {
|
||||
val signature = joinPoint.signature as MethodSignature
|
||||
val args = joinPoint.args
|
||||
val payload = mutableMapOf<String, Any>()
|
||||
payload["controller_method"] = joinPoint.signature.toShortString()
|
||||
val payload = mutableMapOf<String, Any>(
|
||||
"controller_method" to joinPoint.signature.toShortString()
|
||||
)
|
||||
|
||||
val requestParams: MutableMap<String, Any> = mutableMapOf()
|
||||
val pathVariables: MutableMap<String, Any> = mutableMapOf()
|
||||
|
||||
signature.method.parameters.forEachIndexed { index, parameter ->
|
||||
val arg = args[index]
|
||||
|
||||
@ -97,9 +87,10 @@ class ControllerLoggingAspect(
|
||||
parameter.getAnnotation(RequestParam::class.java)?.let {
|
||||
requestParams[parameter.name] = arg
|
||||
}
|
||||
}.also {
|
||||
if (pathVariables.isNotEmpty()) payload["path_variable"] = pathVariables
|
||||
if (requestParams.isNotEmpty()) payload["request_param"] = requestParams
|
||||
}
|
||||
if (pathVariables.isNotEmpty()) payload["path_variable"] = pathVariables
|
||||
if (requestParams.isNotEmpty()) payload["request_param"] = requestParams
|
||||
|
||||
return payload
|
||||
}
|
||||
@ -1,19 +1,15 @@
|
||||
package com.sangdol.roomescape.common.exception
|
||||
package com.sangdol.common.web.exception
|
||||
|
||||
import com.sangdol.common.log.constant.LogType
|
||||
import com.sangdol.common.types.exception.CommonErrorCode
|
||||
import com.sangdol.common.types.exception.ErrorCode
|
||||
import com.sangdol.common.types.exception.RoomescapeException
|
||||
import com.sangdol.common.types.web.CommonErrorResponse
|
||||
import com.sangdol.common.types.web.HttpStatus
|
||||
import com.sangdol.roomescape.auth.exception.AuthException
|
||||
import com.sangdol.roomescape.common.log.ApiLogMessageConverter
|
||||
import com.sangdol.roomescape.common.log.ConvertResponseMessageRequest
|
||||
import com.sangdol.roomescape.common.log.LogType
|
||||
import com.sangdol.roomescape.common.log.getEndpoint
|
||||
import com.sangdol.common.web.support.log.WebLogMessageConverter
|
||||
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.ResponseEntity
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException
|
||||
@ -23,8 +19,8 @@ import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||
private val log: KLogger = KotlinLogging.logger {}
|
||||
|
||||
@RestControllerAdvice
|
||||
class ExceptionControllerAdvice(
|
||||
private val messageConverter: ApiLogMessageConverter
|
||||
class GlobalExceptionHandler(
|
||||
private val messageConverter: WebLogMessageConverter
|
||||
) {
|
||||
@ExceptionHandler(value = [RoomescapeException::class])
|
||||
fun handleRoomException(
|
||||
@ -35,14 +31,7 @@ class ExceptionControllerAdvice(
|
||||
val httpStatus: HttpStatus = errorCode.httpStatus
|
||||
val errorResponse = CommonErrorResponse(errorCode)
|
||||
|
||||
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
|
||||
)
|
||||
logException(servletRequest, httpStatus, errorResponse, e)
|
||||
|
||||
return ResponseEntity
|
||||
.status(httpStatus.value())
|
||||
@ -54,26 +43,21 @@ class ExceptionControllerAdvice(
|
||||
servletRequest: HttpServletRequest,
|
||||
e: Exception
|
||||
): ResponseEntity<CommonErrorResponse> {
|
||||
val message: String = if (e is MethodArgumentNotValidException) {
|
||||
if (e is MethodArgumentNotValidException) {
|
||||
e.bindingResult.allErrors
|
||||
.mapNotNull { it.defaultMessage }
|
||||
.joinToString(", ")
|
||||
} else {
|
||||
e.message!!
|
||||
}.also {
|
||||
log.warn { "[ExceptionControllerAdvice] Invalid Request Value Exception occurred: $it" }
|
||||
}
|
||||
log.debug { "[ExceptionControllerAdvice] Invalid Request Value Exception occurred: $message" }
|
||||
|
||||
val errorCode: ErrorCode = CommonErrorCode.INVALID_INPUT_VALUE
|
||||
val httpStatus: HttpStatus = errorCode.httpStatus
|
||||
val errorResponse = CommonErrorResponse(errorCode)
|
||||
|
||||
logException(
|
||||
type = LogType.APPLICATION_FAILURE,
|
||||
servletRequest = servletRequest,
|
||||
httpStatus = httpStatus.value(),
|
||||
errorResponse = errorResponse,
|
||||
exception = e
|
||||
)
|
||||
logException(servletRequest, httpStatus, errorResponse, e)
|
||||
|
||||
return ResponseEntity
|
||||
.status(httpStatus.value())
|
||||
@ -91,13 +75,7 @@ class ExceptionControllerAdvice(
|
||||
val httpStatus: HttpStatus = errorCode.httpStatus
|
||||
val errorResponse = CommonErrorResponse(errorCode)
|
||||
|
||||
logException(
|
||||
type = LogType.UNHANDLED_EXCEPTION,
|
||||
servletRequest = servletRequest,
|
||||
httpStatus = httpStatus.value(),
|
||||
errorResponse = errorResponse,
|
||||
exception = e
|
||||
)
|
||||
logException(servletRequest, httpStatus, errorResponse, e)
|
||||
|
||||
return ResponseEntity
|
||||
.status(httpStatus.value())
|
||||
@ -105,25 +83,21 @@ class ExceptionControllerAdvice(
|
||||
}
|
||||
|
||||
private fun logException(
|
||||
type: LogType,
|
||||
servletRequest: HttpServletRequest,
|
||||
httpStatus: Int,
|
||||
httpStatus: HttpStatus,
|
||||
errorResponse: CommonErrorResponse,
|
||||
exception: Exception
|
||||
) {
|
||||
val commonRequest = ConvertResponseMessageRequest(
|
||||
type = type,
|
||||
endpoint = servletRequest.getEndpoint(),
|
||||
httpStatus = httpStatus,
|
||||
startTime = MDC.get("startTime")?.toLongOrNull(),
|
||||
body = errorResponse,
|
||||
)
|
||||
val type = if (httpStatus.isClientError()) LogType.APPLICATION_FAILURE else LogType.UNHANDLED_EXCEPTION
|
||||
val actualException: Exception? = if (errorResponse.message == exception.message) null else exception
|
||||
|
||||
val logMessage = if (errorResponse.message == exception.message) {
|
||||
messageConverter.convertToResponseMessage(commonRequest)
|
||||
} else {
|
||||
messageConverter.convertToResponseMessage(commonRequest.copy(exception = exception))
|
||||
}
|
||||
val logMessage = messageConverter.convertToResponseMessage(
|
||||
type = type,
|
||||
servletRequest = servletRequest,
|
||||
httpStatusCode = httpStatus.value(),
|
||||
responseBody = errorResponse,
|
||||
exception = actualException
|
||||
)
|
||||
|
||||
log.warn { logMessage }
|
||||
}
|
||||
@ -1,13 +1,13 @@
|
||||
package com.sangdol.common.log.web
|
||||
package com.sangdol.common.web.servlet
|
||||
|
||||
import com.sangdol.common.log.message.ApiLogMessageConverter
|
||||
import com.sangdol.common.utils.MdcPrincipalIdUtil
|
||||
import com.sangdol.common.utils.MdcStartTimeUtil
|
||||
import com.sangdol.common.web.support.log.WebLogMessageConverter
|
||||
import io.github.oshai.kotlinlogging.KLogger
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import jakarta.servlet.FilterChain
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.slf4j.MDC
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper
|
||||
@ -15,7 +15,7 @@ import org.springframework.web.util.ContentCachingResponseWrapper
|
||||
private val log: KLogger = KotlinLogging.logger {}
|
||||
|
||||
class HttpRequestLoggingFilter(
|
||||
private val messageConverter: ApiLogMessageConverter
|
||||
private val messageConverter: WebLogMessageConverter
|
||||
) : OncePerRequestFilter() {
|
||||
override fun doFilterInternal(
|
||||
request: HttpServletRequest,
|
||||
@ -27,14 +27,13 @@ class HttpRequestLoggingFilter(
|
||||
val cachedRequest = ContentCachingRequestWrapper(request)
|
||||
val cachedResponse = ContentCachingResponseWrapper(response)
|
||||
|
||||
val startTime = System.currentTimeMillis()
|
||||
MDC.put("startTime", startTime.toString())
|
||||
MdcStartTimeUtil.setCurrentTime()
|
||||
|
||||
try {
|
||||
filterChain.doFilter(cachedRequest, cachedResponse)
|
||||
cachedResponse.copyBodyToResponse()
|
||||
} finally {
|
||||
MDC.remove("startTime")
|
||||
MdcStartTimeUtil.clear()
|
||||
MdcPrincipalIdUtil.clear()
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user