mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-09 20:57:23 +08:00
feat(log): 不记录日志也支持开启打印访问日志
This commit is contained in:
@@ -106,17 +106,6 @@ public class LogRecord {
|
|||||||
this.request = request;
|
this.request = request;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 结束日志记录
|
|
||||||
*
|
|
||||||
* @param response 响应信息
|
|
||||||
* @param includes 包含信息
|
|
||||||
* @return 日志记录
|
|
||||||
*/
|
|
||||||
public LogRecord finish(RecordableHttpResponse response, Set<Include> includes) {
|
|
||||||
return finish(Clock.systemUTC(), response, includes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 结束日志记录
|
* 结束日志记录
|
||||||
*
|
*
|
||||||
|
@@ -19,9 +19,9 @@ package top.continew.starter.log.interceptor.autoconfigure;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import top.continew.starter.core.constant.PropertiesConstants;
|
import top.continew.starter.core.constant.PropertiesConstants;
|
||||||
import top.continew.starter.log.core.enums.Include;
|
import top.continew.starter.log.core.enums.Include;
|
||||||
|
import top.continew.starter.web.util.SpringWebUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -41,6 +41,9 @@ public class LogProperties {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否打印日志,开启后可打印访问日志(类似于 Nginx access log)
|
* 是否打印日志,开启后可打印访问日志(类似于 Nginx access log)
|
||||||
|
* <p>
|
||||||
|
* 不记录日志也支持开启打印访问日志
|
||||||
|
* </p>
|
||||||
*/
|
*/
|
||||||
private Boolean isPrint = false;
|
private Boolean isPrint = false;
|
||||||
|
|
||||||
@@ -85,4 +88,14 @@ public class LogProperties {
|
|||||||
public void setExcludePatterns(List<String> excludePatterns) {
|
public void setExcludePatterns(List<String> excludePatterns) {
|
||||||
this.excludePatterns = excludePatterns;
|
this.excludePatterns = excludePatterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否匹配放行路由
|
||||||
|
*
|
||||||
|
* @param uri 请求 URI
|
||||||
|
* @return 是否匹配
|
||||||
|
*/
|
||||||
|
public boolean isMatch(String uri) {
|
||||||
|
return this.getExcludePatterns().stream().anyMatch(pattern -> SpringWebUtils.isMatch(pattern, uri));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,7 +30,6 @@ import org.springframework.web.util.ContentCachingResponseWrapper;
|
|||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
import top.continew.starter.log.core.enums.Include;
|
import top.continew.starter.log.core.enums.Include;
|
||||||
import top.continew.starter.log.interceptor.autoconfigure.LogProperties;
|
import top.continew.starter.log.interceptor.autoconfigure.LogProperties;
|
||||||
import top.continew.starter.web.util.SpringWebUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@@ -70,12 +69,13 @@ public class LogFilter extends OncePerRequestFilter implements Ordered {
|
|||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
boolean isMatch = logProperties.isMatch(request.getRequestURI());
|
||||||
// 包装输入流,可重复读取
|
// 包装输入流,可重复读取
|
||||||
if (this.isRequestWrapper(request)) {
|
if (!isMatch && this.isRequestWrapper(request)) {
|
||||||
request = new ContentCachingRequestWrapper(request);
|
request = new ContentCachingRequestWrapper(request);
|
||||||
}
|
}
|
||||||
// 包装输出流,可重复读取
|
// 包装输出流,可重复读取
|
||||||
boolean isResponseWrapper = this.isResponseWrapper(response);
|
boolean isResponseWrapper = !isMatch && this.isResponseWrapper(response);
|
||||||
if (isResponseWrapper) {
|
if (isResponseWrapper) {
|
||||||
response = new ContentCachingResponseWrapper(response);
|
response = new ContentCachingResponseWrapper(response);
|
||||||
}
|
}
|
||||||
@@ -98,14 +98,7 @@ public class LogFilter extends OncePerRequestFilter implements Ordered {
|
|||||||
}
|
}
|
||||||
// 不拦截 /error
|
// 不拦截 /error
|
||||||
ServerProperties serverProperties = SpringUtil.getBean(ServerProperties.class);
|
ServerProperties serverProperties = SpringUtil.getBean(ServerProperties.class);
|
||||||
if (request.getRequestURI().equals(serverProperties.getError().getPath())) {
|
return !request.getRequestURI().equals(serverProperties.getError().getPath());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 放行
|
|
||||||
boolean isMatch = logProperties.getExcludePatterns()
|
|
||||||
.stream()
|
|
||||||
.anyMatch(pattern -> SpringWebUtils.isMatch(pattern, request.getRequestURI()));
|
|
||||||
return !isMatch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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.dao.LogDao;
|
||||||
import top.continew.starter.log.core.enums.Include;
|
import top.continew.starter.log.core.enums.Include;
|
||||||
import top.continew.starter.log.core.model.LogRecord;
|
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 top.continew.starter.log.interceptor.autoconfigure.LogProperties;
|
||||||
|
|
||||||
import java.time.Clock;
|
import java.time.Clock;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -50,7 +51,8 @@ public class LogInterceptor implements HandlerInterceptor {
|
|||||||
private static final Logger log = LoggerFactory.getLogger(LogInterceptor.class);
|
private static final Logger log = LoggerFactory.getLogger(LogInterceptor.class);
|
||||||
private final LogDao logDao;
|
private final LogDao logDao;
|
||||||
private final LogProperties logProperties;
|
private final LogProperties logProperties;
|
||||||
private final TransmittableThreadLocal<LogRecord.Started> timestampTtl = new TransmittableThreadLocal<>();
|
private final TransmittableThreadLocal<Clock> timeTtl = new TransmittableThreadLocal<>();
|
||||||
|
private final TransmittableThreadLocal<LogRecord.Started> logTtl = new TransmittableThreadLocal<>();
|
||||||
|
|
||||||
public LogInterceptor(LogDao logDao, LogProperties logProperties) {
|
public LogInterceptor(LogDao logDao, LogProperties logProperties) {
|
||||||
this.logDao = logDao;
|
this.logDao = logDao;
|
||||||
@@ -61,13 +63,14 @@ public class LogInterceptor implements HandlerInterceptor {
|
|||||||
public boolean preHandle(@NonNull HttpServletRequest request,
|
public boolean preHandle(@NonNull HttpServletRequest request,
|
||||||
@NonNull HttpServletResponse response,
|
@NonNull HttpServletResponse response,
|
||||||
@NonNull Object handler) {
|
@NonNull Object handler) {
|
||||||
Clock timestamp = Clock.systemUTC();
|
Clock startTime = Clock.systemUTC();
|
||||||
if (this.isRequestRecord(handler)) {
|
if (Boolean.TRUE.equals(logProperties.getIsPrint())) {
|
||||||
if (Boolean.TRUE.equals(logProperties.getIsPrint())) {
|
log.info("[{}] {}", request.getMethod(), request.getRequestURI());
|
||||||
log.info("[{}] {}", request.getMethod(), request.getRequestURI());
|
timeTtl.set(startTime);
|
||||||
}
|
}
|
||||||
LogRecord.Started startedLogRecord = LogRecord.start(timestamp, new RecordableServletHttpRequest(request));
|
if (this.isRequestRecord(handler, request)) {
|
||||||
timestampTtl.set(startedLogRecord);
|
LogRecord.Started startedLogRecord = LogRecord.start(startTime, new RecordableServletHttpRequest(request));
|
||||||
|
logTtl.set(startedLogRecord);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -77,18 +80,23 @@ public class LogInterceptor implements HandlerInterceptor {
|
|||||||
@NonNull HttpServletResponse response,
|
@NonNull HttpServletResponse response,
|
||||||
@NonNull Object handler,
|
@NonNull Object handler,
|
||||||
Exception e) {
|
Exception e) {
|
||||||
LogRecord.Started startedLogRecord = timestampTtl.get();
|
|
||||||
if (null == startedLogRecord) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
timestampTtl.remove();
|
|
||||||
try {
|
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;
|
HandlerMethod handlerMethod = (HandlerMethod)handler;
|
||||||
Log methodLog = handlerMethod.getMethodAnnotation(Log.class);
|
Log methodLog = handlerMethod.getMethodAnnotation(Log.class);
|
||||||
Log classLog = handlerMethod.getBeanType().getDeclaredAnnotation(Log.class);
|
Log classLog = handlerMethod.getBeanType().getDeclaredAnnotation(Log.class);
|
||||||
Set<Include> includeSet = this.getIncludes(methodLog, classLog);
|
Set<Include> includeSet = this.getIncludes(methodLog, classLog);
|
||||||
LogRecord finishedLogRecord = startedLogRecord.finish(new RecordableServletHttpResponse(response, response
|
LogRecord finishedLogRecord = startedLogRecord
|
||||||
.getStatus()), includeSet);
|
.finish(endTime, new RecordableServletHttpResponse(response, response.getStatus()), includeSet);
|
||||||
// 记录日志描述
|
// 记录日志描述
|
||||||
if (includeSet.contains(Include.DESCRIPTION)) {
|
if (includeSet.contains(Include.DESCRIPTION)) {
|
||||||
this.logDescription(finishedLogRecord, methodLog, handlerMethod);
|
this.logDescription(finishedLogRecord, methodLog, handlerMethod);
|
||||||
@@ -97,14 +105,12 @@ public class LogInterceptor implements HandlerInterceptor {
|
|||||||
if (includeSet.contains(Include.MODULE)) {
|
if (includeSet.contains(Include.MODULE)) {
|
||||||
this.logModule(finishedLogRecord, methodLog, classLog, handlerMethod);
|
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);
|
logDao.add(finishedLogRecord);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.error("Logging http log occurred an error: {}.", ex.getMessage(), 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 日志包含信息
|
* @return 日志包含信息
|
||||||
*/
|
*/
|
||||||
private Set<Include> getIncludes(Log methodLog, Log classLog) {
|
private Set<Include> getIncludes(Log methodLog, Log classLog) {
|
||||||
Set<Include> oriIncludeSet = logProperties.getIncludes();
|
Set<Include> includeSet = new HashSet<>(logProperties.getIncludes());
|
||||||
Set<Include> includeSet = new HashSet<>(oriIncludeSet);
|
|
||||||
if (null != classLog) {
|
if (null != classLog) {
|
||||||
this.processInclude(includeSet, classLog);
|
this.processInclude(includeSet, classLog);
|
||||||
}
|
}
|
||||||
@@ -196,10 +201,14 @@ public class LogInterceptor implements HandlerInterceptor {
|
|||||||
* @param handler 处理器
|
* @param handler 处理器
|
||||||
* @return true:需要记录;false:不需要记录
|
* @return true:需要记录;false:不需要记录
|
||||||
*/
|
*/
|
||||||
private boolean isRequestRecord(Object handler) {
|
private boolean isRequestRecord(Object handler, HttpServletRequest request) {
|
||||||
if (!(handler instanceof HandlerMethod handlerMethod)) {
|
if (!(handler instanceof HandlerMethod handlerMethod)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// 如果接口匹配排除列表,不记录日志
|
||||||
|
if (logProperties.isMatch(request.getRequestURI())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// 如果接口被隐藏,不记录日志
|
// 如果接口被隐藏,不记录日志
|
||||||
Operation methodOperation = handlerMethod.getMethodAnnotation(Operation.class);
|
Operation methodOperation = handlerMethod.getMethodAnnotation(Operation.class);
|
||||||
if (null != methodOperation && methodOperation.hidden()) {
|
if (null != methodOperation && methodOperation.hidden()) {
|
||||||
|
Reference in New Issue
Block a user