From ceb85ab1014d4d4fb71c92c2a50e97c7316f0443 Mon Sep 17 00:00:00 2001 From: PicturePark1101 Date: Sat, 28 Jun 2025 18:31:42 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat=20:=20sql=20=EB=A1=9C=EA=B7=B8,=20?= =?UTF-8?q?=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B0=8D=ED=9E=88?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20logback=20=EC=84=A4=EC=A0=95=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20#425?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/logback-appender.xml | 181 +++++++++++++----------- src/main/resources/logback-dev.xml | 44 +++--- src/main/resources/logback-local.xml | 44 +++--- src/main/resources/logback-prod.xml | 42 +++--- 4 files changed, 182 insertions(+), 129 deletions(-) diff --git a/src/main/resources/logback-appender.xml b/src/main/resources/logback-appender.xml index 68ca4fdd..dac5dedd 100644 --- a/src/main/resources/logback-appender.xml +++ b/src/main/resources/logback-appender.xml @@ -1,92 +1,113 @@ - + - + - - - + - - + - - - ${CONSOLE_LOG_PATTERN} - - + + + ${CONSOLE_LOG_PATTERN} + + - - - ${API_CONSOLE_LOG_PATTERN} - - + + + ${CONSOLE_LOG_PATTERN} + + - - ${LOG_PATH}/console/info-${SERVER_INFO}-console.log - - INFO - ACCEPT - DENY - - - ${LOG_PATH}/console/info-${SERVER_INFO}-console-%d{yyyy-MM-dd}.%i.txt - 20MB - 7 - 100MB - - - ${INFO_LOG_PATTERN} - - + + + ${CONSOLE_LOG_PATTERN} + + - - ${LOG_PATH}/console/warn-${SERVER_INFO}-console.log - - WARN - ACCEPT - DENY - - - ${LOG_PATH}/console/warn-${SERVER_INFO}-console-%d{yyyy-MM-dd}.%i.txt - 20MB - 7 - 100MB - - - ${WARN_LOG_PATTERN} - - + + ${LOG_PATH}/console/info-${SERVER_INFO}-console.log + + INFO + ACCEPT + DENY + + + ${LOG_PATH}/console/info-${SERVER_INFO}-console-%d{yyyy-MM-dd}.%i.txt + 20MB + 7 + 100MB + + + ${BASE_LOG_PATTERN} + + - - ${LOG_PATH}/console/error-${SERVER_INFO}-console.log - - ERROR - ACCEPT - DENY - - - ${LOG_PATH}/console/error-${SERVER_INFO}-console-%d{yyyy-MM-dd}.%i.txt - 20MB - 7 - 100MB - - - ${ERROR_LOG_PATTERN} - - + + ${LOG_PATH}/console/warn-${SERVER_INFO}-console.log + + WARN + ACCEPT + DENY + + + ${LOG_PATH}/console/warn-${SERVER_INFO}-console-%d{yyyy-MM-dd}.%i.txt + 20MB + 7 + 100MB + + + ${BASE_LOG_PATTERN} + + + + + ${LOG_PATH}/console/error-${SERVER_INFO}-console.log + + ERROR + ACCEPT + DENY + + + ${LOG_PATH}/console/error-${SERVER_INFO}-console-%d{yyyy-MM-dd}.%i.txt + 20MB + 7 + 100MB + + + ${BASE_LOG_PATTERN} + + + + + ${LOG_PATH}/api/${SERVER_INFO}-api.log + + ${LOG_PATH}/api/${SERVER_INFO}-api-%d{yyyy-MM-dd}.%i.txt + 20MB + 7 + 100MB + + + ${FILE_LOG_PATTERN} + + + + + + ${LOG_PATH}/sql/sql-${SERVER_INFO}.log + + ${LOG_PATH}/sql/sql-${SERVER_INFO}-%d{yyyy-MM-dd}.%i.txt + 20MB + 7 + 100MB + + + ${FILE_LOG_PATTERN} + + - - ${LOG_PATH}/api/${SERVER_INFO}-api.log - - ${LOG_PATH}/api/${SERVER_INFO}-api-%d{yyyy-MM-dd}.%i.txt - 20MB - 7 - 100MB - - - ${API_FILE_LOG_PATTERN} - - \ No newline at end of file diff --git a/src/main/resources/logback-dev.xml b/src/main/resources/logback-dev.xml index dee5fd9b..3072ab04 100644 --- a/src/main/resources/logback-dev.xml +++ b/src/main/resources/logback-dev.xml @@ -1,22 +1,34 @@ - - - - + + + + - - - - - - + + + + + + - - - - + + + + + + + + + + + + + + + + + + - - \ No newline at end of file diff --git a/src/main/resources/logback-local.xml b/src/main/resources/logback-local.xml index 794a255e..d2830f05 100644 --- a/src/main/resources/logback-local.xml +++ b/src/main/resources/logback-local.xml @@ -1,23 +1,33 @@ - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/logback-prod.xml b/src/main/resources/logback-prod.xml index 7ce64d90..d80fa95d 100644 --- a/src/main/resources/logback-prod.xml +++ b/src/main/resources/logback-prod.xml @@ -1,22 +1,32 @@ - - - - + + + + - - - - - - + + + + + + - - - - + + + + - - + + + + + + + + + + + + \ No newline at end of file From 365872c69773c2f10cad94697efac864080832ae Mon Sep 17 00:00:00 2001 From: PicturePark1101 Date: Sat, 28 Jun 2025 18:32:10 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=20=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20=EC=89=BD=EB=8F=84=EB=A1=9D=20=EC=A4=84=EB=9D=84?= =?UTF-8?q?=EA=B8=B0,=20=EC=A0=9C=EC=99=B8=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=B6=94=EA=B0=80=20#425?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../juinjang/monitoring/ApiFilterConfig.java | 23 +++-- .../monitoring/ApiLogRequestLogGenerator.java | 91 ++++++++++--------- .../monitoring/ApiLogResponseGenerator.java | 70 +++++++------- .../juinjang/monitoring/ApiLoggerFilter.java | 76 ++++++++-------- 4 files changed, 139 insertions(+), 121 deletions(-) diff --git a/src/main/java/umc/th/juinjang/monitoring/ApiFilterConfig.java b/src/main/java/umc/th/juinjang/monitoring/ApiFilterConfig.java index 3f82e8df..3e7a1466 100644 --- a/src/main/java/umc/th/juinjang/monitoring/ApiFilterConfig.java +++ b/src/main/java/umc/th/juinjang/monitoring/ApiFilterConfig.java @@ -1,27 +1,30 @@ package umc.th.juinjang.monitoring; import java.util.List; + import lombok.extern.slf4j.Slf4j; + import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; + import umc.th.juinjang.monitoring.ApiLoggerFilter; @Configuration @Slf4j public class ApiFilterConfig { - @Value("${logging.api.excluded-paths}") - private List excludedUrls; + @Value("${logging.api.excluded-paths}") + private List excludedUrls; - @Bean - public FilterRegistrationBean loggingFilter() { - FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); - registrationBean.setFilter(new ApiLoggerFilter(excludedUrls)); - registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 순서 설정 - registrationBean.setUrlPatterns(List.of("/*")); - return registrationBean; - } + @Bean + public FilterRegistrationBean loggingFilter() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new ApiLoggerFilter(excludedUrls)); + registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 순서 설정 + registrationBean.setUrlPatterns(List.of("/*")); + return registrationBean; + } } diff --git a/src/main/java/umc/th/juinjang/monitoring/ApiLogRequestLogGenerator.java b/src/main/java/umc/th/juinjang/monitoring/ApiLogRequestLogGenerator.java index 2082d004..54642c43 100644 --- a/src/main/java/umc/th/juinjang/monitoring/ApiLogRequestLogGenerator.java +++ b/src/main/java/umc/th/juinjang/monitoring/ApiLogRequestLogGenerator.java @@ -1,52 +1,61 @@ package umc.th.juinjang.monitoring; import jakarta.servlet.http.HttpServletRequest; + import java.nio.charset.StandardCharsets; import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; + import org.springframework.web.util.ContentCachingRequestWrapper; public class ApiLogRequestLogGenerator extends ApiLogGenerator { - private final ContentCachingRequestWrapper request; - - public ApiLogRequestLogGenerator(ContentCachingRequestWrapper request) { - this.request = request; - } - - @Override - public String generateLog() { - StringBuilder logBuilder = new StringBuilder(); - - logBuilder.append("Request : ").append(" "); - logBuilder.append(getBaseLogInfo()); - logBuilder.append("[method] ").append(request.getMethod()).append(" "); - logBuilder.append("[uri] ").append(getQuery()).append(" "); - logBuilder.append("[headers] ").append(getHeadersAsString(request)).append(" "); - logBuilder.append("[requestBody] ").append(getBody(request.getContentAsByteArray())).append(" "); - - return logBuilder.toString(); - } - - private String getQuery() { - String uri = request.getRequestURI(); - String queryString = request.getQueryString(); - - if (queryString != null) { - uri += "?" + queryString; - } - return uri; - } - - private String getHeadersAsString(HttpServletRequest request) { - return Collections.list(request.getHeaderNames()).stream() - .filter(headerName -> !headerName.equalsIgnoreCase("Authorization")) - .filter(headerName -> !headerName.equalsIgnoreCase("refresh-token")) - .map(headerName -> headerName + "=" + request.getHeader(headerName)) - .collect(Collectors.joining(", ")); - } - - protected String getBody(byte[] info) { - return new String(info, StandardCharsets.UTF_8).replace("\n", "").replace("\r", ""); - } + private final ContentCachingRequestWrapper request; + private static final List ALLOWED_HEADERS = List.of( + "x-forwarded-for", "x-real-ip", "user-agent", "content-type", "accept", "host" + ); + + public ApiLogRequestLogGenerator(ContentCachingRequestWrapper request) { + this.request = request; + } + + @Override + public String generateLog() { + StringBuilder logBuilder = new StringBuilder(); + + logBuilder.append("Request : ").append(" "); + // logBuilder.append(getBaseLogInfo()); + logBuilder.append("[method] ").append(request.getMethod()).append(" "); + logBuilder.append("[uri] ").append(getQuery()).append("\n"); + logBuilder.append("[headers] ").append(getHeadersAsString(request)).append("\n"); + logBuilder.append("[requestBody] ").append(getBody(request.getContentAsByteArray())).append(" "); + + return logBuilder.toString(); + } + + private String getQuery() { + String uri = request.getRequestURI(); + String queryString = request.getQueryString(); + + if (queryString != null) { + uri += "?" + queryString; + } + return uri; + } + + private String getHeadersAsString(HttpServletRequest request) { + return ALLOWED_HEADERS.stream() + .map(header -> { + String value = request.getHeader(header); + return value != null ? header + "=" + value : null; + }) + .filter(Objects::nonNull) + .collect(Collectors.joining(", ")); + } + + protected String getBody(byte[] info) { + return new String(info, StandardCharsets.UTF_8).replace("\n", "").replace("\r", ""); + } } diff --git a/src/main/java/umc/th/juinjang/monitoring/ApiLogResponseGenerator.java b/src/main/java/umc/th/juinjang/monitoring/ApiLogResponseGenerator.java index 8a1856b9..91e23d60 100644 --- a/src/main/java/umc/th/juinjang/monitoring/ApiLogResponseGenerator.java +++ b/src/main/java/umc/th/juinjang/monitoring/ApiLogResponseGenerator.java @@ -2,42 +2,44 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; + import java.nio.charset.StandardCharsets; + import org.springframework.web.util.ContentCachingResponseWrapper; public class ApiLogResponseGenerator extends ApiLogGenerator { - private final ContentCachingResponseWrapper response; - - public ApiLogResponseGenerator(ContentCachingResponseWrapper response) { - this.response = response; - } - - @Override - public String generateLog() { - StringBuilder logBuilder = new StringBuilder(); - - logBuilder.append("Response : ").append(" "); - logBuilder.append(getBaseLogInfo()); - logBuilder.append("[status] ").append(response.getStatus()).append(" "); - logBuilder.append("[responseBody] ").append(getBody(response.getContentAsByteArray())).append(" "); - - return logBuilder.toString(); - } - - protected String getBody(byte[] info) { - String responseBody = ""; - try { - ObjectMapper objectMapper = new ObjectMapper(); - JsonNode rootNode = objectMapper.readTree(new String(info, StandardCharsets.UTF_8)); - responseBody = replaceToken(rootNode.path("message").asText("N/A")); - } catch (Exception e) { - logger.error("responseBody 추출 오류"); - } - return responseBody; - } - - private String replaceToken(String responseBody) { - return responseBody.replaceAll("\"accessToken\":\"[^\"]*\"", "\"accessToken\":\"[TOKEN]\"") - .replaceAll("\"refreshToken\":\"[^\"]*\"", "\"refreshToken\":\"[TOKEN]\""); - } + private final ContentCachingResponseWrapper response; + + public ApiLogResponseGenerator(ContentCachingResponseWrapper response) { + this.response = response; + } + + @Override + public String generateLog() { + StringBuilder logBuilder = new StringBuilder(); + + logBuilder.append("Response : ").append(" "); + // logBuilder.append(getBaseLogInfo()); + logBuilder.append("[status] ").append(response.getStatus()).append(" "); + logBuilder.append("[responseBody] ").append(getBody(response.getContentAsByteArray())).append(" "); + + return logBuilder.toString(); + } + + protected String getBody(byte[] info) { + String responseBody = ""; + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode rootNode = objectMapper.readTree(new String(info, StandardCharsets.UTF_8)); + responseBody = replaceToken(rootNode.path("message").asText("N/A")); + } catch (Exception e) { + logger.error("responseBody 추출 오류"); + } + return responseBody; + } + + private String replaceToken(String responseBody) { + return responseBody.replaceAll("\"accessToken\":\"[^\"]*\"", "\"accessToken\":\"[TOKEN]\"") + .replaceAll("\"refreshToken\":\"[^\"]*\"", "\"refreshToken\":\"[TOKEN]\""); + } } diff --git a/src/main/java/umc/th/juinjang/monitoring/ApiLoggerFilter.java b/src/main/java/umc/th/juinjang/monitoring/ApiLoggerFilter.java index 9a44943e..cc8a2145 100644 --- a/src/main/java/umc/th/juinjang/monitoring/ApiLoggerFilter.java +++ b/src/main/java/umc/th/juinjang/monitoring/ApiLoggerFilter.java @@ -6,9 +6,12 @@ import jakarta.servlet.FilterChain; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + import java.util.List; import java.util.UUID; + import lombok.extern.slf4j.Slf4j; + import org.slf4j.Logger; import org.slf4j.MDC; import org.springframework.util.AntPathMatcher; @@ -18,40 +21,41 @@ @Slf4j public class ApiLoggerFilter extends OncePerRequestFilter { - private static final Logger logger = getLogger(ApiLoggerFilter.class); - private final ApiLoggerFactory apiLoggerFactory; - private final List EXCLUDED_URLS; - - public ApiLoggerFilter(List EXCLUDED_URLS) { - this.EXCLUDED_URLS = EXCLUDED_URLS; - this.apiLoggerFactory = new ApiLoggerFactory(); - } - - @Override - protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, FilterChain chain) { - ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(servletRequest); - ContentCachingResponseWrapper response = new ContentCachingResponseWrapper(servletResponse); - registerRequestId(UUID.randomUUID().toString()); - - try { - if (shouldNotFilter(request)) { - chain.doFilter(request, response); - return; - } - chain.doFilter(request, response); - apiLoggerFactory.createRequestLogger(request); - apiLoggerFactory.createResponseLogger(response); - response.copyBodyToResponse(); - } catch (Exception e) { - logger.error("APILogger 필터 오류"); - } finally { - MDC.clear(); - } - } - - @Override - protected boolean shouldNotFilter(HttpServletRequest request) { - AntPathMatcher pathMatcher = new AntPathMatcher(); - return EXCLUDED_URLS.stream().anyMatch(pattern -> pathMatcher.match(pattern, request.getRequestURI())); - } + private static final Logger logger = getLogger(ApiLoggerFilter.class); + private final ApiLoggerFactory apiLoggerFactory; + private final List EXCLUDED_URLS; + + public ApiLoggerFilter(List EXCLUDED_URLS) { + this.EXCLUDED_URLS = EXCLUDED_URLS; + this.apiLoggerFactory = new ApiLoggerFactory(); + } + + @Override + protected void doFilterInternal(HttpServletRequest servletRequest, HttpServletResponse servletResponse, + FilterChain chain) { + ContentCachingRequestWrapper request = new ContentCachingRequestWrapper(servletRequest); + ContentCachingResponseWrapper response = new ContentCachingResponseWrapper(servletResponse); + registerRequestId(UUID.randomUUID().toString()); + + try { + if (shouldNotFilter(request)) { + chain.doFilter(request, response); + return; + } + chain.doFilter(request, response); + apiLoggerFactory.createRequestLogger(request); + apiLoggerFactory.createResponseLogger(response); + response.copyBodyToResponse(); + } catch (Exception e) { + logger.error("APILogger 필터 오류, message : {} ", e.getMessage()); + } finally { + MDC.clear(); + } + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + AntPathMatcher pathMatcher = new AntPathMatcher(); + return EXCLUDED_URLS.stream().anyMatch(pattern -> pathMatcher.match(pattern, request.getRequestURI())); + } } From 9030769d083308fbf126e6419587f37dc991b9e1 Mon Sep 17 00:00:00 2001 From: PicturePark1101 Date: Sat, 28 Jun 2025 18:56:19 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat=20:=20=EC=BD=98=EC=86=94=EC=97=90?= =?UTF-8?q?=EB=8A=94=20=EC=BF=BC=EB=A6=AC=EB=AC=B8=20=EB=9C=A8=EC=A7=80=20?= =?UTF-8?q?=EC=95=8A=EB=8F=84=EB=A1=9D=20fix=20#425?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/logback-appender.xml | 6 ------ src/main/resources/logback-dev.xml | 2 -- src/main/resources/logback-local.xml | 2 -- src/main/resources/logback-prod.xml | 2 -- 4 files changed, 12 deletions(-) diff --git a/src/main/resources/logback-appender.xml b/src/main/resources/logback-appender.xml index dac5dedd..43647c9f 100644 --- a/src/main/resources/logback-appender.xml +++ b/src/main/resources/logback-appender.xml @@ -23,12 +23,6 @@ - - - ${CONSOLE_LOG_PATTERN} - - - ${LOG_PATH}/console/info-${SERVER_INFO}-console.log diff --git a/src/main/resources/logback-dev.xml b/src/main/resources/logback-dev.xml index 3072ab04..f3f6f6fe 100644 --- a/src/main/resources/logback-dev.xml +++ b/src/main/resources/logback-dev.xml @@ -19,12 +19,10 @@ - - diff --git a/src/main/resources/logback-local.xml b/src/main/resources/logback-local.xml index d2830f05..53df0253 100644 --- a/src/main/resources/logback-local.xml +++ b/src/main/resources/logback-local.xml @@ -19,12 +19,10 @@ - - diff --git a/src/main/resources/logback-prod.xml b/src/main/resources/logback-prod.xml index d80fa95d..e7f28785 100644 --- a/src/main/resources/logback-prod.xml +++ b/src/main/resources/logback-prod.xml @@ -19,12 +19,10 @@ - -