generated from pricelees/issue-pr-template
feat: 컨트롤러 요청 / 응답을 기록하는 AOP
This commit is contained in:
parent
a2fea10f50
commit
660ac5ebc9
@ -0,0 +1,94 @@
|
||||
package roomescape.common.log
|
||||
|
||||
import io.github.oshai.kotlinlogging.KLogger
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.aspectj.lang.JoinPoint
|
||||
import org.aspectj.lang.ProceedingJoinPoint
|
||||
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
|
||||
import org.springframework.web.bind.annotation.RequestParam
|
||||
import org.springframework.web.context.request.RequestContextHolder
|
||||
import org.springframework.web.context.request.ServletRequestAttributes
|
||||
|
||||
private val log: KLogger = KotlinLogging.logger {}
|
||||
|
||||
@Aspect
|
||||
class ControllerLoggingAspect(
|
||||
private val messageConverter: ApiLogMessageConverter,
|
||||
) {
|
||||
|
||||
@Pointcut("execution(* roomescape..web..*Controller.*(..))")
|
||||
fun allController() {
|
||||
}
|
||||
|
||||
@Around("allController()")
|
||||
fun logAPICalls(joinPoint: ProceedingJoinPoint): Any? {
|
||||
val startTime: Long = MDC.get("startTime").toLongOrNull() ?: System.currentTimeMillis()
|
||||
val controllerPayload: Map<String, Any> = parsePayload(joinPoint)
|
||||
|
||||
log.info {
|
||||
messageConverter.convertToControllerInvokedMessage(servletRequest(), controllerPayload)
|
||||
}
|
||||
|
||||
try {
|
||||
return joinPoint.proceed()
|
||||
.also { logSuccess(startTime, it) }
|
||||
} catch (e: Exception) {
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
private fun logSuccess(startTime: Long, result: Any) {
|
||||
val responseEntity = result as ResponseEntity<*>
|
||||
val logMessage = messageConverter.convertToResponseMessage(
|
||||
ConvertResponseMessageRequest(
|
||||
type = LogType.CONTROLLER_SUCCESS,
|
||||
httpStatus = responseEntity.statusCode.value(),
|
||||
startTime = startTime,
|
||||
body = responseEntity.body
|
||||
)
|
||||
)
|
||||
|
||||
log.info { logMessage }
|
||||
}
|
||||
|
||||
private fun servletRequest(): HttpServletRequest {
|
||||
return (RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes).request
|
||||
}
|
||||
|
||||
private fun parsePayload(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 requestParams: MutableMap<String, Any> = mutableMapOf()
|
||||
val pathVariables: MutableMap<String, Any> = mutableMapOf()
|
||||
signature.method.parameters.forEachIndexed { index, parameter ->
|
||||
val arg = args[index]
|
||||
|
||||
parameter.getAnnotation(RequestBody::class.java)?.let {
|
||||
payload["request_body"] = arg
|
||||
}
|
||||
|
||||
parameter.getAnnotation(PathVariable::class.java)?.let {
|
||||
pathVariables[parameter.name] = arg
|
||||
}
|
||||
|
||||
parameter.getAnnotation(RequestParam::class.java)?.let {
|
||||
requestParams[parameter.name] = arg
|
||||
}
|
||||
}
|
||||
if (pathVariables.isNotEmpty()) payload["path_variable"] = pathVariables
|
||||
if (requestParams.isNotEmpty()) payload["request_param"] = requestParams
|
||||
|
||||
return payload
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user