使用切面逮捕慢接口
2022-10-19 本文已影响0人
祥哥去哪里
前言:
在我们后端开发过程中,打印日志,是最常见的排查问题的手段。但是每个接口里面去打印日志还是太麻烦,下面介绍下使用AOP打印接口日志的方法
初始化一个切面
首先我们对切面设计要求是,打印接口入参、出参、接口耗时等日志信息。出现异常时也顺手打印一个异常信息
@Slf4j
@Aspect
@Component
public class RequestInterceptor {
/**
* 切入点:包含所有的控制器
*/
@Pointcut("execution(public * com.spring.demo.javastudydemo.contrller.*.*(..))")
public void pointcut(){}
/**
* 切面实现
* @param proceedingJoinPoint
* @return
* @throws Throwable
*/
@Around("pointcut()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
try {
long s = System.currentTimeMillis();//开始时间
Object o = proceedingJoinPoint.proceed();//执行目标方法
if(System.currentTimeMillis()-s>2000L) {//结束时间-开始时间超过两秒的接口
log.info("调用接口 {} 耗时:{} 入参 {} {} 出参 {}", proceedingJoinPoint.getSignature().toShortString(),(System.currentTimeMillis()-s), JSONObject.toJSONString(proceedingJoinPoint.getArgs()),System.lineSeparator(),JSONObject.toJSONString(o));
}
return o;
}catch (Throwable e) {
Object [] args =proceedingJoinPoint.getArgs();
log.error("调用接口异常 {} 入参 {} {} 异常 {}", proceedingJoinPoint.getSignature().toShortString(),JSONObject.toJSONString(args),System.lineSeparator(), ExceptionUtil.exMassage(e));
throw e;
}
}
}
这里选择使用了@Around注解的原因是,我们需要打印出参还有执行时间。使用环绕可以自定义目标方法的执行时机,
之所以选择打印执行时间超过2秒的日志,主要是防止请求量较大的项目导致日志过多。如果日志数量没有压力的项目,可以放开限制
创建被代理类
切面设计好后,我们回到被代理的控制器,由于我们切入方式使用的execution匹配命名空间。所以我们的控制器不需要任何跟切面相关的代码。这也是我们做这个切面的目的
@RestController
@RequestMapping("hello")
public class HelloController {
@GetMapping("index")
public String index(@RequestParam("name") String name) {
try {
Thread.sleep(2000L);//人为制造慢接口
} catch (InterruptedException e) {
}
return "hello "+name;
}
}
检验执行结果
我们启动服务后,访问这个路由
访问接口
访问成功,在两秒后返回了结果
我们再看看控制台打印日志的结果
打印结果
符合我们设计预期,打印了方法名,入参,出参和执行时间。