使用切面逮捕慢接口

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

检验执行结果

我们启动服务后,访问这个路由


访问接口

访问成功,在两秒后返回了结果
我们再看看控制台打印日志的结果


打印结果

符合我们设计预期,打印了方法名,入参,出参和执行时间。

上一篇下一篇

猜你喜欢

热点阅读