From 66e2a39664f617a468f2580858344ce728f0f06d Mon Sep 17 00:00:00 2001 From: Valentin Laurin Date: Tue, 18 Mar 2025 09:41:05 +0000 Subject: [PATCH 1/3] Shorten access logs KVP keys Context is provided by logger name. In this context repeating the word `request` is redundant and keys can be simplified and shortened to reduce log volume. --- .../app/quickcase/sdk/spring/logging/AccessLogFilter.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java b/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java index 779da82..82c9fc1 100644 --- a/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java +++ b/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java @@ -16,12 +16,13 @@ import org.slf4j.event.Level; import org.slf4j.spi.LoggingEventBuilder; import org.springframework.http.HttpMethod; +import org.springframework.web.servlet.HandlerMapping; @Slf4j public class AccessLogFilter implements Filter { - private static final String KEY_METHOD = "requestMethod"; - private static final String KEY_URI = "requestUri"; - private static final String KEY_STATUS = "responseCode"; + private static final String KEY_METHOD = "method"; + private static final String KEY_URI = "uri"; + private static final String KEY_STATUS = "status"; private static final String KEY_DURATION = "duration"; private final static Clock clock = Clock.systemDefaultZone(); From 5dafce414f92579975f6ae4ab2f7696fb2cbee28 Mon Sep 17 00:00:00 2001 From: Valentin Laurin Date: Tue, 18 Mar 2025 10:21:31 +0000 Subject: [PATCH 2/3] Log access URI match To allow for grouping of access logs per endpoint, add the matched URI pattern to the access log KVP. The path variables are NOT included in the KVP as they would duplicate the MDC content most of the time. --- .../sdk/spring/logging/AccessLogFilter.java | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java b/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java index 82c9fc1..252c92c 100644 --- a/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java +++ b/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java @@ -13,7 +13,6 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; -import org.slf4j.event.Level; import org.slf4j.spi.LoggingEventBuilder; import org.springframework.http.HttpMethod; import org.springframework.web.servlet.HandlerMapping; @@ -24,6 +23,7 @@ public class AccessLogFilter implements Filter { private static final String KEY_URI = "uri"; private static final String KEY_STATUS = "status"; private static final String KEY_DURATION = "duration"; + private static final String KEY_MATCH = "match"; private final static Clock clock = Clock.systemDefaultZone(); private final AccessLogLevelStrategy logLevelStrategy; @@ -59,26 +59,47 @@ public void doFilter(ServletRequest request, final Duration duration = Duration.between(start, clock.instant()); final int status = httpResponse.getStatus(); - log.atLevel(logLevelStrategy.onCompleted(method, requestURI, status)) - .addKeyValue(KEY_METHOD, method) - .addKeyValue(KEY_URI, requestURI) - .addKeyValue(KEY_STATUS, status) - .addKeyValue(KEY_DURATION, duration.toMillis()) - .log("Request processed ({}) in {}ms: {} {}", status, duration.toMillis(), method, requestURI); + var completedLogBuilder = log.atLevel(logLevelStrategy.onCompleted(method, requestURI, status)) + .addKeyValue(KEY_METHOD, method) + .addKeyValue(KEY_URI, requestURI) + .addKeyValue(KEY_STATUS, status) + .addKeyValue(KEY_DURATION, duration.toMillis()); + + addPatternMatch(httpRequest, completedLogBuilder); + + completedLogBuilder.log("Request processed ({}) in {}ms: {} {}", status, duration.toMillis(), method, requestURI); } catch (Exception exception) { final Duration duration = Duration.between(start, clock.instant()); - log.atLevel(logLevelStrategy.onException(method, requestURI, exception)) - .addKeyValue(KEY_METHOD, method) - .addKeyValue(KEY_URI, requestURI) - .addKeyValue(KEY_DURATION, duration.toMillis()) - .log("Request failed in {}ms: {} {} ", duration.toMillis(), method, requestURI); + var errorLogBuilder = log.atLevel(logLevelStrategy.onException(method, requestURI, exception)) + .addKeyValue(KEY_METHOD, method) + .addKeyValue(KEY_URI, requestURI) + .addKeyValue(KEY_DURATION, duration.toMillis()); + + addPatternMatch(httpRequest, errorLogBuilder); + + errorLogBuilder.log("Request failed in {}ms: {} {} ", duration.toMillis(), method, requestURI); throw exception; } } + /** + * Extract and populate the matching URI pattern, if available, in the access log KVP. + * The matrix of variable for that matching pattern is ignored as it would duplicate the MDC in most cases. + * + * @param httpRequest Request from which to extract the matched pattern + * @param logBuilder Logging event builder to which the pattern KVP should be added + */ + private void addPatternMatch(HttpServletRequest httpRequest, LoggingEventBuilder logBuilder) { + var pattern = (String) httpRequest.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); + + if (pattern != null) { + logBuilder.addKeyValue(KEY_MATCH, pattern); + } + } + private LoggingEventBuilder successLogBuilder (String httpMethod) { if (HttpMethod.OPTIONS.matches(httpMethod)) { return log.atDebug(); From da52f784b8e51698c63d05074ddd8e2a3fcfaf2a Mon Sep 17 00:00:00 2001 From: Valentin Laurin Date: Tue, 18 Mar 2025 10:41:15 +0000 Subject: [PATCH 3/3] Clean up unused method Left over from access log level strategy abstraction --- .../app/quickcase/sdk/spring/logging/AccessLogFilter.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java b/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java index 252c92c..aa980bb 100644 --- a/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java +++ b/src/main/java/app/quickcase/sdk/spring/logging/AccessLogFilter.java @@ -14,7 +14,6 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.slf4j.spi.LoggingEventBuilder; -import org.springframework.http.HttpMethod; import org.springframework.web.servlet.HandlerMapping; @Slf4j @@ -99,11 +98,4 @@ private void addPatternMatch(HttpServletRequest httpRequest, LoggingEventBuilder logBuilder.addKeyValue(KEY_MATCH, pattern); } } - - private LoggingEventBuilder successLogBuilder (String httpMethod) { - if (HttpMethod.OPTIONS.matches(httpMethod)) { - return log.atDebug(); - } - return log.atInfo(); - } }