使用springboot+aop+log4j2进行全局接口请求监控,记录请求耗时

1在pom.xml中引入aop、log4j2依赖



	org.springframework.boot
	spring-boot-starter-aop



	com.google.code.gson
	gson
	2.8.5



   org.springframework.boot
   spring-boot-starter
   
	   
		   org.springframework.boot
		   spring-boot-starter-logging
	  
   
     

 
   org.springframework.boot
   spring-boot-starter-log4j2

2配置log4j2.xml到classpath下

  
  
      
          
          
              
                [%-5p] %d %c - %m%n  
              
          
          
          
              
                [%-5p] %d %c - %m%n  
              
          
      
      
          
              
          
    	
            
              
        
            
              
        
      

然后在业务代码中:

private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

即可用logger打印日志

3配置切面编程监控接口请求

(1)首先创建自定义注解类(哪个接口需要被监控再加注解,不需要监控的不加即可)

package com.goldcard.data_innovation.aop;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)//什么时候使用该注解,我们定义为运行时
@Target({ElementType.METHOD})//注解用于什么地方,我们定义为作用于方法上
@Documented//注解是否将包含在 JavaDoc 中
public @interface WebLog {
	/**
	 * 日志描述信息
	 */
	String description() default "";//定义一个属性,默认为空字符串
}

(2)接下来配置AOP,首先先了解下aspectj相关注解的作用

@Aspect:声明该类为一个注解类;
@Pointcut:定义一个切点,后面跟随一个表达式,表达式可以定义为切某个注解,也可以切某个 package 下的方法;

切点定义好后,就是围绕这个切点做文章了:

@Before: 在切点之前,织入相关代码;
@After: 在切点之后,织入相关代码;
@AfterReturning: 在切点返回内容后,织入相关代码,一般用于对返回值做些加工处理的场景;
@AfterThrowing: 用来处理当织入的代码抛出异常后的逻辑处理;
@Around: 环绕,可以在切入点前后织入代码,并且可以自由的控制何时执行切点;

使用springboot+aop+log4j2进行全局接口请求监控,记录请求耗时_第1张图片

具体代码:

package com.goldcard.data_innovation.aop;

import com.google.gson.Gson;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


/**
 * 切面类
 * @author 3897
 */
@Aspect
@Component
@Profile({"dev","test"})
public class WebLogAspect {
	private final static Logger logger = LoggerFactory.getLogger(WebLogAspect.class);
	//换行符
	private final static String LINE_SEPARATOR = System.lineSeparator();
	
	/**
	 * 声明自定义@WebLog注解为切点
	 */
	@Pointcut("@annotation(com.goldcard.data_innovation.aop.WebLog)")
	public void webLog(){}
	
	/**
	 * 环绕
	 */
	@Around("webLog()")
	public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
		long startTime = System.currentTimeMillis();
		Object result = proceedingJoinPoint.proceed();
		//打印出参
		logger.info("Response Args : {}",new Gson().toJson(result));
		//执行耗时
		logger.info("Time-Consuming : {} ms",System.currentTimeMillis()-startTime);
		return result;
	}
	
	/**
	 * 在切点前织入
	 */
	@Before("webLog()")
	public void doBefore(JoinPoint joinPoint) throws Throwable{
		//开始打印请求日志
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();
		
		//获取@WebLog注解的描述信息
		String methodDescription = getAspectLogDescription(joinPoint);
		
		//打印相关请求参数
		logger.info("=============== Start ===============");
		// 打印请求 url
        logger.info("URL            : {}", request.getRequestURL().toString());
        // 打印描述信息
        logger.info("Description    : 请求了[{}]接口", methodDescription);
        // 打印 Http method
        logger.info("HTTP Method    : {}", request.getMethod());
        // 打印调用 controller 的全路径以及执行方法
        logger.info("Class Method   : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        // 打印请求的 IP
        logger.info("IP             : {}", request.getRemoteAddr());
        // 打印请求入参
        logger.info("Request Args   : {}", new Gson().toJson(joinPoint.getArgs()));
	}
	
	/**
	 * 在切点之后织入
	 */
	@After("webLog()")
	public void doAfter() throws Throwable{
		//接口结束后换行,方便分割查看
		logger.info("=============== End ===============" + LINE_SEPARATOR);
	}
	
	/**
	 * 获取切面注解的描述
	 */
	public String getAspectLogDescription(JoinPoint joinpoint) throws Exception{
		String targetName = joinpoint.getTarget().getClass().getName();
		String methodName = joinpoint.getSignature().getName();
		Object[] arguments = joinpoint.getArgs();
		Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        StringBuilder description = new StringBuilder("");
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description.append(method.getAnnotation(WebLog.class).description());
                    break;
                }
            }
        }
        return description.toString();
	}
}

使用方法:

使用springboot+aop+log4j2进行全局接口请求监控,记录请求耗时_第2张图片

日志打印情况:

=============== Start ===============                                                            
URL            : http://10.30.2.49:8089/abnormalTile/gasMonitoList                               
Description    : 请求了[用气页面列表]接口                                                                   
HTTP Method    : GET                                                                             
Class Method   : com.goldcard.data_innovation.controller.AbnormalTileController.gasMonitoList    
IP             : 10.30.2.132                                                                     
Request Args   : ["cust_id","","0",1,10]                                                         
Response Args : {"sum":4,"list":[{"cust_id":"001","cust_name":"金卡","meter_addr":"金桥街","cust_phone
Time-Consuming : 101 ms                                                                          
=============== End ===============  

 

若只想在开发环境(dev)、测试环境(test)使用,而不在生产环境(prod)使用,加此注解,并配置框架的环境

使用springboot+aop+log4j2进行全局接口请求监控,记录请求耗时_第3张图片

你可能感兴趣的:(使用springboot+aop+log4j2进行全局接口请求监控,记录请求耗时)