feat: 添加traceId;记录请求和响应数据
This commit is contained in:
parent
64079598ef
commit
437787ca44
|
|
@ -0,0 +1,135 @@
|
|||
package com.nflg.mobilebroken.starter.filter;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nflg.mobilebroken.common.util.AdminUserUtil;
|
||||
import com.nflg.mobilebroken.common.util.AppUserUtil;
|
||||
import com.nflg.mobilebroken.common.util.SaTokenAdminUtil;
|
||||
import com.nflg.mobilebroken.common.util.SaTokenAppUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TraceIdFilter extends OncePerRequestFilter {
|
||||
|
||||
private static final String TRACE_ID_HEADER = "X-Trace-Id";
|
||||
private static final String MDC_TRACE_ID = "traceId";
|
||||
|
||||
// 需要跳过的二进制内容类型
|
||||
private static final List<String> BINARY_CONTENT_TYPES = Arrays.asList("image", "video", "audio", "stream", "pdf", "zip", "excel");
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
|
||||
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
|
||||
try {
|
||||
// 从请求头获取或生成Trace ID
|
||||
String traceId = requestWrapper.getHeader(TRACE_ID_HEADER);
|
||||
if (StrUtil.isBlank(traceId)) {
|
||||
traceId = IdUtil.getSnowflakeNextIdStr();
|
||||
}
|
||||
// 存入MDC和响应头
|
||||
MDC.put(MDC_TRACE_ID, traceId);
|
||||
responseWrapper.addHeader(TRACE_ID_HEADER, traceId);
|
||||
|
||||
filterChain.doFilter(requestWrapper, responseWrapper);
|
||||
} finally {
|
||||
logRequest(requestWrapper);
|
||||
logResponse(responseWrapper);
|
||||
responseWrapper.copyBodyToResponse();
|
||||
|
||||
// 请求结束时清除MDC
|
||||
MDC.remove(MDC_TRACE_ID);
|
||||
}
|
||||
}
|
||||
|
||||
private void logResponse(ContentCachingResponseWrapper response) {
|
||||
log.debug("【HTTP Response】");
|
||||
log.debug("STATUS : {}", response.getStatus());
|
||||
log.debug("BODY : {}", getResponseBody(response));
|
||||
}
|
||||
|
||||
private String getResponseBody(ContentCachingResponseWrapper response) {
|
||||
if (shouldSkipBodyLogging(response.getContentType())){
|
||||
return "[不记录]"+response.getContentType();
|
||||
}
|
||||
byte[] buf = response.getContentAsByteArray();
|
||||
if (buf.length > 0) {
|
||||
return new String(buf, StandardCharsets.UTF_8);
|
||||
}
|
||||
return "[无数据]";
|
||||
}
|
||||
|
||||
private void logRequest(ContentCachingRequestWrapper request) {
|
||||
log.debug("【HTTP Request】");
|
||||
log.debug("URL : {}", request.getRequestURL().toString());
|
||||
log.debug("METHOD : {}", request.getMethod());
|
||||
log.debug("HEADERS: {}", getHeadersAsString(request));
|
||||
log.debug("USER : {}", getUserInfo(request));
|
||||
log.debug("BODY : {}", getRequestBody(request));
|
||||
}
|
||||
|
||||
private String getUserInfo(ContentCachingRequestWrapper request) {
|
||||
String token=request.getHeader("authorization");
|
||||
if (StrUtil.isBlank(token)){
|
||||
return "未登录";
|
||||
}
|
||||
if (SaTokenAdminUtil.isLogin()) {
|
||||
return StrUtil.format("id:{},姓名:{},邮箱:{}"
|
||||
, AdminUserUtil.getUserId()
|
||||
, AdminUserUtil.getUserName()
|
||||
, AdminUserUtil.getEmail());
|
||||
}
|
||||
if (SaTokenAppUtil.isLogin()) {
|
||||
return StrUtil.format("id:{},姓名:{},邮箱:{},是否主账号:{}"
|
||||
, AppUserUtil.getUserId()
|
||||
, AppUserUtil.getUserName()
|
||||
, AppUserUtil.getEmail()
|
||||
, AppUserUtil.isPrimary());
|
||||
}
|
||||
return "无效token或已过期";
|
||||
}
|
||||
|
||||
private String getRequestBody(ContentCachingRequestWrapper request) {
|
||||
if (shouldSkipBodyLogging(request.getContentType())){
|
||||
return "[不记录]"+request.getContentType();
|
||||
}
|
||||
byte[] buf = request.getContentAsByteArray();
|
||||
if (buf.length > 0) {
|
||||
return new String(buf, StandardCharsets.UTF_8).replaceAll("\\s", "");
|
||||
}
|
||||
return "[无数据]";
|
||||
}
|
||||
|
||||
private String getHeadersAsString(HttpServletRequest request) {
|
||||
StringBuilder headers = new StringBuilder();
|
||||
request.getHeaderNames().asIterator().forEachRemaining(headerName ->
|
||||
headers.append(headerName)
|
||||
.append("=")
|
||||
.append(request.getHeader(headerName))
|
||||
.append("; ")
|
||||
);
|
||||
return headers.toString();
|
||||
}
|
||||
|
||||
private boolean shouldSkipBodyLogging(String contentType) {
|
||||
if (contentType == null) return false;
|
||||
|
||||
return BINARY_CONTENT_TYPES.stream().anyMatch(contentType::contains);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue