MDC+aop实现请求的日志追踪

MDC 

使用MDC.put(key, val)写入需要打印的参数。

MDC.clear();  进行日志的清理

 案例

可以记录每次请求的参数、时间、url、token、响应时间

注意:由于每次打印日志很多,建议在开发和测试时候使用,生产环境关闭

package com.xihongshi.common.interceptor;

import com.xihongshi.common.constants.LogConstant;
import com.xihongshi.utils.IpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @Description: Controller LOG AOP
 */
@Slf4j
@Aspect
public class ApiLogAspect {

    @Value("${api.log.enabled:true}")
    private boolean enabled = true;

    @Value("${api.log.logReqEnabled:true}")
    private boolean logReqEnabled = true;

    @Value("${api.log.logReqParamEnabled:true}")
    private boolean logReqParamEnabled = true;

    @Value("${api.log.logRespEnabled:true}")
    private boolean logRespEnabled = true;

    @Value("${api.log.logRespResultEnabled:true}")
    private boolean logRespResultEnabled = true;

    @Value("${api.log.printRespResultLimit:1024}")
    private Integer printRespResultLimit = 1024;

    @Value("${api.log.respCostTimeLimit:1000}")
    private Long respCostTimeLimit = 1000L;

    @Value("${api.log.logTokenEnabled:true}")
    private boolean logTokenEnabled = true;

    @Value("${api.log.reqeust.tokenName:token}")
    private String tokenName = "token";

    public ApiLogAspect() {
        log.info("[Api接口日志切面]初始化{}", this);
    }

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && execution(public * com..controller..*.*(..))")
    public void controllerPointcut() {
    }

    @Around("controllerPointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String traceId = null;
        String requestUri = null;
        String requestUrl = null;
        String clientIp = null;
        String token = null;
        String param = null;
        Long startTime = 0L;

        if (isEnabled()) {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();

            startTime = (Long) request.getAttribute(LogConstant.REQUEST_START_TIME_ATTR);
            startTime = (null == startTime ? System.currentTimeMillis() : startTime);
            traceId = getRequestTraceId(request);
            requestUrl = request.getRequestURL().toString();
            requestUri = request.getRequestURI();
            clientIp = IpUtil.getClientIp(request);
            token = isLogTokenEnabled() ? request.getHeader(tokenName) : null;
            param = getParams(joinPoint);

            MDC.put(LogConstant.LOG_MDC_REQUEST_URI, requestUri);
            if (StringUtils.isNotEmpty(traceId)) {
                MDC.put(getRequestTraceFlagName(), traceId);
            }
            //logReuqest
            if (isLogReqEnabled()) {
                StringBuilder logReuqest = new StringBuilder("logRequest -> token={} ,clientIp={} ,url={}");
                List<Object> logParams = new ArrayList(Arrays.asList(new Object[]{token, clientIp, requestUri}));
                if (isLogReqParamEnabled()) {
                    logReuqest.append(" ,param={}");
                    logParams.add(param);
                }
                log.info(logReuqest.toString(), logParams.toArray(new Object[]{}));
            }

        }

        Object obj = joinPoint.proceed();

        if (isEnabled()) {
            long costTime = (System.currentTimeMillis() - startTime);
            //logResponse
            if (isLogRespEnabled()) {
                StringBuilder logResponse = new StringBuilder("logResponse -> token={} ,clientIp={} ,url={} ,costTime={} ,{}={}");
                List<Object> logParams = new ArrayList(Arrays.asList(new Object[]{token, clientIp, requestUrl, costTime, getRequestTraceFlagName(), traceId}));
                if (isLogReqParamEnabled()) {
                    logResponse.append(" ,param={}");
                    logParams.add(param);
                }
                if (isLogRespResultEnabled()) {
                    String respStr = obj == null ? "" : obj.toString();
                    if (null != getPrintRespResultLimit() && getPrintRespResultLimit() > 0 && respStr.length() > getPrintRespResultLimit()) {
                        respStr = respStr.substring(0, getPrintRespResultLimit());
                    }
                    logResponse.append(" -> respStr={}");
                    logParams.add(respStr);
                }
                log.info(logResponse.toString(), logParams.toArray(new Object[]{}));
            }
            //costTimeLong
            if (costTime > getRespCostTimeLimit()) {
                MDC.put(LogConstant.LOG_RESPONSE_COST_TIME, String.valueOf(costTime));
                log.warn("costTimeLong -> clientIp={} ,url={} ,costTime={} ,{}={} ,param={}", clientIp, requestUrl, costTime, getRequestTraceFlagName(), traceId, param);
            }
        }

        return obj;
    }

    private String getParams(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        if (null != args && args.length > 0) {
            List<Object> argList = new ArrayList<>(args.length);
            for (Object arg : args) {
                if (arg instanceof HttpServletRequest || arg instanceof HttpServletResponse) {
                    continue;
                }
                argList.add(arg);
            }
            return argList.toString();
        }
        return null;
    }

    protected String getRequestTraceId(HttpServletRequest request) {
        return request.getHeader(getRequestTraceFlagName());
    }

    protected String getRequestTraceFlagName() {
        return LogConstant.REQUEST_HEADER_TRACEID;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public boolean isLogReqEnabled() {
        return logReqEnabled;
    }

    public boolean isLogReqParamEnabled() {
        return logReqParamEnabled;
    }

    public boolean isLogRespEnabled() {
        return logRespEnabled;
    }

    public boolean isLogRespResultEnabled() {
        return logRespResultEnabled;
    }

    public Integer getPrintRespResultLimit() {
        return printRespResultLimit;
    }

    public long getRespCostTimeLimit() {
        return respCostTimeLimit;
    }

    public boolean isLogTokenEnabled() {
        return logTokenEnabled;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39564710/article/details/115308894