From 049f5acb64761eaeaa69e9e1db12450fb8f8489c Mon Sep 17 00:00:00 2001 From: yun-zhi-ztl <15071461069@163.com> Date: Thu, 19 Mar 2026 14:13:39 +0800 Subject: [PATCH] refactor(server): slim down request logging to core parameters only --- .../skillhub/filter/RequestLoggingFilter.java | 83 +++++++++---------- .../src/main/resources/application-local.yml | 4 +- .../filter/RequestLoggingFilterTest.java | 48 +++++++++-- 3 files changed, 83 insertions(+), 52 deletions(-) diff --git a/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestLoggingFilter.java b/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestLoggingFilter.java index 7ea50453..cda766ff 100644 --- a/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestLoggingFilter.java +++ b/server/skillhub-app/src/main/java/com/iflytek/skillhub/filter/RequestLoggingFilter.java @@ -15,24 +15,32 @@ import org.springframework.web.util.ContentCachingResponseWrapper; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; +import java.util.Set; /** - * Logs inbound HTTP requests and responses with truncation suitable for operational debugging. + * Logs inbound HTTP requests with only core parameters to keep log files compact. */ @Component @Order(Ordered.HIGHEST_PRECEDENCE + 1) public class RequestLoggingFilter extends OncePerRequestFilter { private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class); - private static final int MAX_LOG_BODY_LENGTH = 512; + private static final int MAX_LOG_BODY_LENGTH = 200; + + private static final Set SKIP_PREFIXES = Set.of( + "/actuator", "/favicon.ico", "/assets/" + ); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String uri = request.getRequestURI(); + if (shouldSkip(uri)) { + filterChain.doFilter(request, response); + return; + } + ContentCachingRequestWrapper cachedRequest = new ContentCachingRequestWrapper(request); ContentCachingResponseWrapper cachedResponse = new ContentCachingResponseWrapper(response); @@ -52,45 +60,43 @@ public class RequestLoggingFilter extends OncePerRequestFilter { String queryString = request.getQueryString(); String fullUrl = queryString != null ? requestUri + "?" + queryString : requestUri; + String contentType = request.getContentType(); + String userAgent = request.getHeader("User-Agent"); + StringBuilder sb = new StringBuilder(); - sb.append("\n========== HTTP Request ==========\n"); - sb.append("URL: ").append(request.getMethod()).append(" ").append(fullUrl).append("\n"); - sb.append("Remote Address: ").append(request.getRemoteAddr()).append("\n"); - sb.append("Headers: ").append(getHeaders(request)).append("\n"); + sb.append(request.getMethod()).append(" ").append(fullUrl); + sb.append(" | ").append(response.getStatus()); + sb.append(" | ").append(duration).append("ms"); + sb.append(" | ").append(request.getRemoteAddr()); + if (contentType != null) { + sb.append(" | Content-Type: ").append(contentType); + } + if (userAgent != null) { + sb.append(" | UA: ").append(truncate(userAgent, 80)); + } String requestBody = getRequestBody(request); if (requestBody != null && !requestBody.isBlank()) { - sb.append("Request Body: ").append(requestBody).append("\n"); + sb.append(" | Body: ").append(requestBody); } - sb.append("Response Status: ").append(response.getStatus()).append("\n"); - - String responseBody = getResponseBody(response); - if (responseBody != null && !responseBody.isBlank()) { - sb.append("Response Body: ").append(responseBody).append("\n"); - } - - sb.append("Duration: ").append(duration).append("ms\n"); - sb.append("==================================="); - log.info(sb.toString()); } - private Map getHeaders(HttpServletRequest request) { - Map headers = new HashMap<>(); - Enumeration headerNames = request.getHeaderNames(); - while (headerNames.hasMoreElements()) { - String headerName = headerNames.nextElement(); - headers.put(headerName, request.getHeader(headerName)); + private boolean shouldSkip(String uri) { + for (String prefix : SKIP_PREFIXES) { + if (uri.startsWith(prefix)) { + return true; + } } - return headers; + return false; } private String getRequestBody(ContentCachingRequestWrapper request) { byte[] buf = request.getContentAsByteArray(); if (buf.length > 0) { try { - return truncateBody(new String(buf, request.getCharacterEncoding())); + return truncate(new String(buf, request.getCharacterEncoding()), MAX_LOG_BODY_LENGTH); } catch (UnsupportedEncodingException e) { return "[unknown encoding]"; } @@ -98,23 +104,10 @@ public class RequestLoggingFilter extends OncePerRequestFilter { return null; } - private String getResponseBody(ContentCachingResponseWrapper response) { - byte[] buf = response.getContentAsByteArray(); - if (buf.length > 0) { - try { - return truncateBody(new String(buf, response.getCharacterEncoding())); - } catch (UnsupportedEncodingException e) { - return "[unknown encoding]"; - } + private String truncate(String value, int maxLength) { + if (value == null || value.length() <= maxLength) { + return value; } - return null; - } - - private String truncateBody(String body) { - if (body == null || body.length() <= MAX_LOG_BODY_LENGTH) { - return body; - } - return body.substring(0, MAX_LOG_BODY_LENGTH) - + "... [truncated, original length=" + body.length() + "]"; + return value.substring(0, maxLength) + "...[truncated]"; } } diff --git a/server/skillhub-app/src/main/resources/application-local.yml b/server/skillhub-app/src/main/resources/application-local.yml index 705cedd1..c879825d 100644 --- a/server/skillhub-app/src/main/resources/application-local.yml +++ b/server/skillhub-app/src/main/resources/application-local.yml @@ -30,5 +30,5 @@ skillhub: logging: level: - com.iflytek.skillhub: DEBUG - org.springframework.security: DEBUG + com.iflytek.skillhub: INFO + org.springframework.security: WARN diff --git a/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestLoggingFilterTest.java b/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestLoggingFilterTest.java index 7d74d3ff..de158226 100644 --- a/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestLoggingFilterTest.java +++ b/server/skillhub-app/src/test/java/com/iflytek/skillhub/filter/RequestLoggingFilterTest.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; class RequestLoggingFilterTest { @Test - void doFilterInternal_truncatesLongRequestAndResponseBodiesInLogs(CapturedOutput output) + void doFilterInternal_truncatesLongRequestBodyAndOmitsResponseBody(CapturedOutput output) throws ServletException, IOException { RequestLoggingFilter filter = new RequestLoggingFilter(); String longBody = "x".repeat(5_000); @@ -39,10 +39,48 @@ class RequestLoggingFilterTest { filter.doFilter(request, response, filterChain); - assertThat(output).contains("Request Body: " + "x".repeat(512) + "... [truncated, original length=5000]"); - assertThat(output).contains("Response Body: " + "x".repeat(512) + "... [truncated, original length=5000]"); - assertThat(output).doesNotContain("Request Body: " + longBody); - assertThat(output).doesNotContain("Response Body: " + longBody); + // Request body should be truncated at 200 chars + assertThat(output).contains("Body: " + "x".repeat(200) + "...[truncated]"); + assertThat(output).doesNotContain("Body: " + longBody); + // Response body should not be logged at all + assertThat(output).doesNotContain("Response Body:"); + // Original response should still be intact assertThat(response.getContentAsString()).isEqualTo(longBody); } + + @Test + void doFilterInternal_skipsActuatorEndpoints(CapturedOutput output) + throws ServletException, IOException { + RequestLoggingFilter filter = new RequestLoggingFilter(); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/actuator/health"); + MockHttpServletResponse response = new MockHttpServletResponse(); + + FilterChain filterChain = (req, res) -> {}; + + filter.doFilter(request, response, filterChain); + + assertThat(output).doesNotContain("/actuator/health"); + } + + @Test + void doFilterInternal_logsCoreSummaryFields(CapturedOutput output) + throws ServletException, IOException { + RequestLoggingFilter filter = new RequestLoggingFilter(); + + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/api/v1/skills"); + request.setRemoteAddr("127.0.0.1"); + MockHttpServletResponse response = new MockHttpServletResponse(); + + FilterChain filterChain = (req, res) -> {}; + + filter.doFilter(request, response, filterChain); + + assertThat(output).contains("GET /api/v1/skills"); + assertThat(output).contains("200"); + assertThat(output).contains("127.0.0.1"); + assertThat(output).contains("ms"); + // Should not contain full headers dump + assertThat(output).doesNotContain("Headers: {"); + } }