[Solutions] <RequestLogFilter> 请求日志统一拦截器

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.Ordered;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
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.UUID;

@Component
@Slf4j
public class RequestLogFilter extends OncePerRequestFilter implements Ordered {
    private static final String TID = "TID";
    @Value(value = "${method.cost.time.threshold:1000}")
    private String methodCostTimeThreshold;

    private static final String HEALTH_CHECK_URL = "/api/health-check/status";

    @Override
    public int getOrder() {
        return 20;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
            FilterChain filterChain) throws ServletException, IOException {
        try {
            if(!request.getRequestURI().contains(HEALTH_CHECK_URL)) {
                long begin = System.currentTimeMillis();
                String requestId = UUID.randomUUID().toString().replace("-", "");
                MDC.put(TID, requestId);
                ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
                filterChain.doFilter(wrappedRequest, response);
                String body = getBody(wrappedRequest);
                String username = SecurityContextHolder.getContext().getAuthentication().getName();
                long end = System.currentTimeMillis();
                long cost = end - begin;
                if (StringUtils.isNotEmpty(methodCostTimeThreshold) && cost > Long.parseLong(methodCostTimeThreshold)) {
                    log.info("Method time cost exceeds threshold[{}],tid: [{}], method:[{}], path:[{}],status:[{}]", cost,
                            requestId, request.getMethod(), request.getRequestURI(), response.getStatus());
                }
                log.info("tid: {}, method: {}, path: {}, status: {}, user: {}, userAgent: {}, query: {}, body: {}",
                        requestId, request.getMethod(), request.getRequestURI(), response.getStatus(),
                        username, request.getHeader("User-Agent"), request.getQueryString(), body);
            }else{
                filterChain.doFilter(request, response);
            }
        } finally {
            if(!request.getRequestURI().contains(HEALTH_CHECK_URL)) {
                MDC.remove(TID);
            }
        }
    }

    private String getBody(ContentCachingRequestWrapper request) {
        ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request,
                ContentCachingRequestWrapper.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 ex) {
                    payload = "[unknown]";
                }
                return payload;
            }
        }

        return null;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值