package roomescape.common.log import com.fasterxml.jackson.databind.ObjectMapper import jakarta.servlet.http.HttpServletRequest import org.slf4j.MDC enum class LogType { INCOMING_HTTP_REQUEST, CONTROLLER_INVOKED, CONTROLLER_SUCCESS, AUTHENTICATION_FAILURE, APPLICATION_FAILURE, UNHANDLED_EXCEPTION } class ApiLogMessageConverter( private val objectMapper: ObjectMapper ) { fun convertToHttpRequestMessage( request: HttpServletRequest ): String { val payload: MutableMap = commonRequestPayload(LogType.INCOMING_HTTP_REQUEST, request) request.queryString?.let { payload["query_params"] = it } payload["client_ip"] = request.remoteAddr payload["user_agent"] = request.getHeader("User-Agent") return objectMapper.writeValueAsString(payload) } fun convertToControllerInvokedMessage( request: HttpServletRequest, controllerPayload: Map, ): String { val payload: MutableMap = commonRequestPayload(LogType.CONTROLLER_INVOKED, request) val memberId: Long? = MDC.get("member_id")?.toLong() if (memberId != null) payload["member_id"] = memberId else payload["member_id"] = "NONE" payload.putAll(controllerPayload) return objectMapper.writeValueAsString(payload) } fun convertToResponseMessage(request: ConvertResponseMessageRequest): String { val payload: MutableMap = mutableMapOf() payload["type"] = request.type payload["status_code"] = request.httpStatus MDC.get("member_id")?.toLongOrNull() ?.let { payload["member_id"] = it } ?: run { payload["member_id"] = "NONE" } request.startTime?.let { payload["duration_ms"] = System.currentTimeMillis() - it } request.body?.let { payload["response_body"] = it } request.exception?.let { payload["exception"] = mapOf( "class" to it.javaClass.simpleName, "message" to it.message ) } return objectMapper.writeValueAsString(payload) } private fun commonRequestPayload( logType: LogType, request: HttpServletRequest ): MutableMap = mutableMapOf( "type" to logType, "method" to request.method, "uri" to request.requestURI ) } data class ConvertResponseMessageRequest( val type: LogType, val httpStatus: Int = 200, val startTime: Long? = null, val body: Any? = null, val exception: Exception? = null )