更新时间:

#springboot web 加过滤器 TraceLogFilter ,增加traceId

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

<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>