From 16b6e9b466578d935ab9a8a85a5eac4d09025dee Mon Sep 17 00:00:00 2001 From: Charles7c Date: Fri, 30 Aug 2024 20:40:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(log):=20=E4=B8=8D=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=B9=9F=E6=94=AF=E6=8C=81=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E8=AE=BF=E9=97=AE=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../starter/log/core/model/LogRecord.java | 11 ---- .../autoconfigure/LogProperties.java | 15 ++++- .../log/interceptor/handler/LogFilter.java | 15 ++--- .../interceptor/handler/LogInterceptor.java | 57 +++++++++++-------- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/core/model/LogRecord.java b/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/core/model/LogRecord.java index e1955b7e..93197d77 100644 --- a/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/core/model/LogRecord.java +++ b/continew-starter-log/continew-starter-log-core/src/main/java/top/continew/starter/log/core/model/LogRecord.java @@ -106,17 +106,6 @@ public class LogRecord { this.request = request; } - /** - * 结束日志记录 - * - * @param response 响应信息 - * @param includes 包含信息 - * @return 日志记录 - */ - public LogRecord finish(RecordableHttpResponse response, Set includes) { - return finish(Clock.systemUTC(), response, includes); - } - /** * 结束日志记录 * diff --git a/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/autoconfigure/LogProperties.java b/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/autoconfigure/LogProperties.java index d1d320bd..c821a7f4 100644 --- a/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/autoconfigure/LogProperties.java +++ b/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/autoconfigure/LogProperties.java @@ -19,9 +19,9 @@ package top.continew.starter.log.interceptor.autoconfigure; import org.springframework.boot.context.properties.ConfigurationProperties; import top.continew.starter.core.constant.PropertiesConstants; import top.continew.starter.log.core.enums.Include; +import top.continew.starter.web.util.SpringWebUtils; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; @@ -41,6 +41,9 @@ public class LogProperties { /** * 是否打印日志,开启后可打印访问日志(类似于 Nginx access log) + *

+ * 不记录日志也支持开启打印访问日志 + *

*/ private Boolean isPrint = false; @@ -85,4 +88,14 @@ public class LogProperties { public void setExcludePatterns(List excludePatterns) { this.excludePatterns = excludePatterns; } + + /** + * 是否匹配放行路由 + * + * @param uri 请求 URI + * @return 是否匹配 + */ + public boolean isMatch(String uri) { + return this.getExcludePatterns().stream().anyMatch(pattern -> SpringWebUtils.isMatch(pattern, uri)); + } } diff --git a/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogFilter.java b/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogFilter.java index b85ef9f5..7fea14c7 100644 --- a/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogFilter.java +++ b/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogFilter.java @@ -30,7 +30,6 @@ import org.springframework.web.util.ContentCachingResponseWrapper; import org.springframework.web.util.WebUtils; import top.continew.starter.log.core.enums.Include; import top.continew.starter.log.interceptor.autoconfigure.LogProperties; -import top.continew.starter.web.util.SpringWebUtils; import java.io.IOException; import java.net.URI; @@ -70,12 +69,13 @@ public class LogFilter extends OncePerRequestFilter implements Ordered { filterChain.doFilter(request, response); return; } + boolean isMatch = logProperties.isMatch(request.getRequestURI()); // 包装输入流,可重复读取 - if (this.isRequestWrapper(request)) { + if (!isMatch && this.isRequestWrapper(request)) { request = new ContentCachingRequestWrapper(request); } // 包装输出流,可重复读取 - boolean isResponseWrapper = this.isResponseWrapper(response); + boolean isResponseWrapper = !isMatch && this.isResponseWrapper(response); if (isResponseWrapper) { response = new ContentCachingResponseWrapper(response); } @@ -98,14 +98,7 @@ public class LogFilter extends OncePerRequestFilter implements Ordered { } // 不拦截 /error ServerProperties serverProperties = SpringUtil.getBean(ServerProperties.class); - if (request.getRequestURI().equals(serverProperties.getError().getPath())) { - return false; - } - // 放行 - boolean isMatch = logProperties.getExcludePatterns() - .stream() - .anyMatch(pattern -> SpringWebUtils.isMatch(pattern, request.getRequestURI())); - return !isMatch; + return !request.getRequestURI().equals(serverProperties.getError().getPath()); } /** diff --git a/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogInterceptor.java b/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogInterceptor.java index bd3e29ad..a63d151d 100644 --- a/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogInterceptor.java +++ b/continew-starter-log/continew-starter-log-interceptor/src/main/java/top/continew/starter/log/interceptor/handler/LogInterceptor.java @@ -32,10 +32,11 @@ import top.continew.starter.log.core.annotation.Log; import top.continew.starter.log.core.dao.LogDao; import top.continew.starter.log.core.enums.Include; import top.continew.starter.log.core.model.LogRecord; -import top.continew.starter.log.core.model.LogResponse; import top.continew.starter.log.interceptor.autoconfigure.LogProperties; import java.time.Clock; +import java.time.Duration; +import java.time.Instant; import java.util.HashSet; import java.util.Set; @@ -50,7 +51,8 @@ public class LogInterceptor implements HandlerInterceptor { private static final Logger log = LoggerFactory.getLogger(LogInterceptor.class); private final LogDao logDao; private final LogProperties logProperties; - private final TransmittableThreadLocal timestampTtl = new TransmittableThreadLocal<>(); + private final TransmittableThreadLocal timeTtl = new TransmittableThreadLocal<>(); + private final TransmittableThreadLocal logTtl = new TransmittableThreadLocal<>(); public LogInterceptor(LogDao logDao, LogProperties logProperties) { this.logDao = logDao; @@ -61,13 +63,14 @@ public class LogInterceptor implements HandlerInterceptor { public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) { - Clock timestamp = Clock.systemUTC(); - if (this.isRequestRecord(handler)) { - if (Boolean.TRUE.equals(logProperties.getIsPrint())) { - log.info("[{}] {}", request.getMethod(), request.getRequestURI()); - } - LogRecord.Started startedLogRecord = LogRecord.start(timestamp, new RecordableServletHttpRequest(request)); - timestampTtl.set(startedLogRecord); + Clock startTime = Clock.systemUTC(); + if (Boolean.TRUE.equals(logProperties.getIsPrint())) { + log.info("[{}] {}", request.getMethod(), request.getRequestURI()); + timeTtl.set(startTime); + } + if (this.isRequestRecord(handler, request)) { + LogRecord.Started startedLogRecord = LogRecord.start(startTime, new RecordableServletHttpRequest(request)); + logTtl.set(startedLogRecord); } return true; } @@ -77,18 +80,23 @@ public class LogInterceptor implements HandlerInterceptor { @NonNull HttpServletResponse response, @NonNull Object handler, Exception e) { - LogRecord.Started startedLogRecord = timestampTtl.get(); - if (null == startedLogRecord) { - return; - } - timestampTtl.remove(); try { + Clock endTime = Clock.systemUTC(); + if (Boolean.TRUE.equals(logProperties.getIsPrint())) { + Duration timeTaken = Duration.between(Instant.now(timeTtl.get()), Instant.now(endTime)); + log.info("[{}] {} {} {}ms", request.getMethod(), request.getRequestURI(), response + .getStatus(), timeTaken.toMillis()); + } + LogRecord.Started startedLogRecord = logTtl.get(); + if (null == startedLogRecord) { + return; + } HandlerMethod handlerMethod = (HandlerMethod)handler; Log methodLog = handlerMethod.getMethodAnnotation(Log.class); Log classLog = handlerMethod.getBeanType().getDeclaredAnnotation(Log.class); Set includeSet = this.getIncludes(methodLog, classLog); - LogRecord finishedLogRecord = startedLogRecord.finish(new RecordableServletHttpResponse(response, response - .getStatus()), includeSet); + LogRecord finishedLogRecord = startedLogRecord + .finish(endTime, new RecordableServletHttpResponse(response, response.getStatus()), includeSet); // 记录日志描述 if (includeSet.contains(Include.DESCRIPTION)) { this.logDescription(finishedLogRecord, methodLog, handlerMethod); @@ -97,14 +105,12 @@ public class LogInterceptor implements HandlerInterceptor { if (includeSet.contains(Include.MODULE)) { this.logModule(finishedLogRecord, methodLog, classLog, handlerMethod); } - if (Boolean.TRUE.equals(logProperties.getIsPrint())) { - LogResponse logResponse = finishedLogRecord.getResponse(); - log.info("[{}] {} {} {}ms", request.getMethod(), request.getRequestURI(), logResponse - .getStatus(), finishedLogRecord.getTimeTaken().toMillis()); - } logDao.add(finishedLogRecord); } catch (Exception ex) { log.error("Logging http log occurred an error: {}.", ex.getMessage(), ex); + } finally { + timeTtl.remove(); + logTtl.remove(); } } @@ -116,8 +122,7 @@ public class LogInterceptor implements HandlerInterceptor { * @return 日志包含信息 */ private Set getIncludes(Log methodLog, Log classLog) { - Set oriIncludeSet = logProperties.getIncludes(); - Set includeSet = new HashSet<>(oriIncludeSet); + Set includeSet = new HashSet<>(logProperties.getIncludes()); if (null != classLog) { this.processInclude(includeSet, classLog); } @@ -196,10 +201,14 @@ public class LogInterceptor implements HandlerInterceptor { * @param handler 处理器 * @return true:需要记录;false:不需要记录 */ - private boolean isRequestRecord(Object handler) { + private boolean isRequestRecord(Object handler, HttpServletRequest request) { if (!(handler instanceof HandlerMethod handlerMethod)) { return false; } + // 如果接口匹配排除列表,不记录日志 + if (logProperties.isMatch(request.getRequestURI())) { + return false; + } // 如果接口被隐藏,不记录日志 Operation methodOperation = handlerMethod.getMethodAnnotation(Operation.class); if (null != methodOperation && methodOperation.hidden()) {