springboot web 加过滤器 TraceLogFilter ,增加traceId

義往昔 7月前 ⋅ 966 阅读
package com.xxx.xxx.filter;

import com.xxx.xxx.util.CommonUtils;
import com.xxx.xxx.util.RequestUtils;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
* @author langhsu on 2015/7/10.
* https://blog.csdn.net/panyongcsd/article/details/80990397
* https://github.com/ancin/springsample/blob/70c7d533dfa84b42af61f7fcbe7942e4ee9de3d2/src/main/java/com/springapp/mvc/web/TraceLogFilter.java
* https://github.com/xukh630/jcs
*/
@Slf4j
public class TraceLogFilter extends OncePerRequestFilter {
private static final Set<String> EXCLUDE_URI = new HashSet<>(32);
private static final Set<String> SENSITIVITY_URI = new HashSet<>(16);

static {

// EXCLUDE_URI.add("/dist");
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
long startTime = System.currentTimeMillis();
if (!(request instanceof ContentCachingRequestWrapper)) {
request = new ContentCachingRequestWrapper(request);
}
if (!(response instanceof ContentCachingResponseWrapper)) {
response = new ContentCachingResponseWrapper(response);
}
int status = HttpStatus.INTERNAL_SERVER_ERROR.value();
String uri = request.getRequestURI();
ThreadContext.put("logid", CommonUtils.getLogId());
try {
chain.doFilter(request, response);
} catch (Exception e) {
log.error("request " + uri , e);
}
String responseBody = getResponseBody(response);

status = response.getStatus();
if (isPrintLog(uri)) {
// String ip = RequestUtils.getRealIP(request);
String url = request.getRequestURL().toString();
// String method = request.getMethod();
long usedTime = System.currentTimeMillis() - startTime;
String header = "header";
String param = null;
try {
param = getRequestBody(request);
if (isSensitivityUri(request.getRequestURI())) {
header = RequestUtils.getHeadersJson(request);
}
} catch (Exception e) {
log.error("", e);
}
// String ret = getResponseBody(responseWrapper);
TraceLog traceLog = TraceLog.builder()
// .ip(ip) //todo 无意义,都是nginx 本机
.url(url.substring(22))
// .method(method)
.usedTime(usedTime)
.status(status)
.header(header)
.param(param)
.responseBody(responseBody)
.build();
log.info(traceLog.toString());
}
updateResponse(response);
ThreadContext.clearAll();
}

private String getRequestBody(HttpServletRequest request) throws Exception {
ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
//return new String(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding());
return getRequestString(wrapper);
}

private String getRequestString(ContentCachingRequestWrapper request) {
String payload = "{}";
if (request != null) {
if (request.getMethod().equalsIgnoreCase(HttpMethod.POST.name())) {
byte[] buf = request.getContentAsByteArray();
if (buf.length > 0 && buf.length < 1024 * 64) {
try {
payload = new String(buf, 0, buf.length, request.getCharacterEncoding());
} catch (UnsupportedEncodingException ex) {
payload = "[unknown]";
}
} else if (buf.length >= 1024 * 64) {
return String.format("[too long content, length = %s]", buf.length);
}
} else {
payload = request.getQueryString() == null ? "{}" : request.getQueryString();
}
}
return payload;
}

private String getResponseBody(HttpServletResponse response) {
ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
if (null != wrapper) {
try {
return new String(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding());
} catch (IOException e) {
log.error("getResponseBody Exception >>> ", e);
}
}
return "";
}
private void updateResponse(HttpServletResponse response) throws IOException {
ContentCachingResponseWrapper responseWrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
Objects.requireNonNull(responseWrapper).copyBodyToResponse();
}
// private String getResponseBody(ContentCachingResponseWrapper response) {
// ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
// if (wrapper != null) {
// byte[] buf = wrapper.getContentAsByteArray();
// if (buf.length > 0) {
// String payload;
// try {
// payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
// } catch (UnsupportedEncodingException e) {
// payload = "[unknown]";
// }
// return payload;
// }
// }
// return "";
// }

private static boolean isSensitivityUri(String uri) {
boolean result = true;
for (String suri : SENSITIVITY_URI) {
if (uri.equals(suri)) {
result = false;
break;
}
}
return result;
}

private static boolean isPrintLog(String uri) {
boolean result = true;
for (String euri : EXCLUDE_URI) {
if (uri.startsWith(euri)) {
result = false;
break;
}
}
return result;
}

@Builder
private final static class TraceLog {
private String ip;
private String url;
private String method;
private Long usedTime;
private Integer status;
private String header;
private String param;
private String responseBody;

@Override
public String toString() {
return
// "|" + ip +
"|\'" + url +
// "\'|" + method +
"\'|" + status +
"|" + usedTime +
"|" + param +
"|" + header +
"|" + responseBody ;
}
}

}

对应log4j2
<!-- 打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
<RollingRandomAccessFile name="infoLog" fileName="${logDir}/info.log" immediateFlush="false"
filePattern="${logDir}/info.log.%d{yyyyMMddHH}"
append="true">
<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss.SSS} [%t] [%-5level] [%logger{36} %L %M] - [LOGID: %X{logid}] %msg%xEx%n"/>
<Policies>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<Filters>
<!-- 只记录info和warn级别信息 -->
<ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</Filters>
<!-- 指定每天的最大压缩包个数,默认7个,超过了会覆盖之前的 -->
<DefaultRolloverStrategy max="50"/>
</RollingRandomAccessFile>

全部评论: 0

    我有话说: