From 0f350162a2c030b3a209b1e831a55a201dc09126 Mon Sep 17 00:00:00 2001 From: Photogrammer <81505228+JuneParkCode@users.noreply.github.com> Date: Fri, 23 Aug 2024 18:22:35 +0900 Subject: [PATCH] =?UTF-8?q?[FEAT]=20HTTP=20Request=20/=20Response=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20logging=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 결과 예시 ![image](https://github.com/user-attachments/assets/15a49bf0-4b69-40a8-b45e-d1cd4edbad6d) ## 작업 내용 - Logging Filter 추가 - OncePerRequestFilter 적용 (Filter 두번 타는 경우 방지) - 총 지연시간 ms 로 표현 - Security 보다 먼저 거치도록 가장 Order 를 높게 잡음. Closes #106 --- .../server/common/log/HttpLogMessage.java | 39 +++++++++++++++++ .../server/common/log/LoggingFilter.java | 43 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 server/src/main/java/com/talkka/server/common/log/HttpLogMessage.java create mode 100644 server/src/main/java/com/talkka/server/common/log/LoggingFilter.java diff --git a/server/src/main/java/com/talkka/server/common/log/HttpLogMessage.java b/server/src/main/java/com/talkka/server/common/log/HttpLogMessage.java new file mode 100644 index 00000000..f62d0204 --- /dev/null +++ b/server/src/main/java/com/talkka/server/common/log/HttpLogMessage.java @@ -0,0 +1,39 @@ +package com.talkka.server.common.log; + +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import lombok.Builder; + +@Builder +public record HttpLogMessage(String httpMethod, String requestUri, Integer httpStatus, String clientIp, + Long elapsedTimeMs, String requestParam, String requestBody, String responseBody) { + public static HttpLogMessage create(ContentCachingRequestWrapper request, ContentCachingResponseWrapper response, + Long elapsedTimeMs) { + return HttpLogMessage.builder() + .httpMethod(request.getMethod()) + .requestUri(request.getRequestURI()) + .httpStatus(response.getStatus()) + .clientIp(request.getRemoteAddr()) + .elapsedTimeMs(elapsedTimeMs) + .requestParam(request.getQueryString()) + .requestBody(new String(request.getContentAsByteArray())) + .responseBody(new String(response.getContentAsByteArray())) + .build(); + } + + public String beatify() { + String format = """ + HTTP REQUEST %s %s %s + | ClientIp: %s + | ElapsedTimeMs: %sms + | RequestParam: %s + | RequestBody: %s + | ResponseBody: %s + """; + + return String.format(format, httpMethod, requestUri, httpStatus, clientIp, elapsedTimeMs, requestParam, + requestBody, responseBody + ); + } +} diff --git a/server/src/main/java/com/talkka/server/common/log/LoggingFilter.java b/server/src/main/java/com/talkka/server/common/log/LoggingFilter.java new file mode 100644 index 00000000..92963bc8 --- /dev/null +++ b/server/src/main/java/com/talkka/server/common/log/LoggingFilter.java @@ -0,0 +1,43 @@ +package com.talkka.server.common.log; + +import java.io.IOException; + +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.ContentCachingRequestWrapper; +import org.springframework.web.util.ContentCachingResponseWrapper; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class LoggingFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + var cachingRequestWrapper = new ContentCachingRequestWrapper(request); + var cachingResponseWrapper = new ContentCachingResponseWrapper(response); + + var startTime = System.currentTimeMillis(); + filterChain.doFilter(cachingRequestWrapper, cachingResponseWrapper); + var endTime = System.currentTimeMillis(); + + try { + var logMessage = HttpLogMessage.create(cachingRequestWrapper, cachingResponseWrapper, + (endTime - startTime)) + .beatify(); + log.info(logMessage); + cachingResponseWrapper.copyBodyToResponse(); + } catch (Exception exception) { + log.error("Logging 실패"); + } + } +}