Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SpringWebFlux端点性能记录器_Spring_Spring Webflux_Spring Aop_Project Reactor - Fatal编程技术网

SpringWebFlux端点性能记录器

SpringWebFlux端点性能记录器,spring,spring-webflux,spring-aop,project-reactor,Spring,Spring Webflux,Spring Aop,Project Reactor,您知道记录SpringWebFlux控制器端点性能以保持反应性的良好实践吗?似乎以下原则不起作用,因为它会阻止IO,因为ProceedingJoinPoint不返回Publisher,它只返回一个对象 @Aspect @Component @Slf4j public class LoggingAspect { //AOP expression for which methods shall be intercepted @Around("execution(* com

您知道记录SpringWebFlux控制器端点性能以保持反应性的良好实践吗?似乎以下原则不起作用,因为它会阻止IO,因为ProceedingJoinPoint不返回Publisher,它只返回一个对象

@Aspect
@Component
@Slf4j
public class LoggingAspect
{

    //AOP expression for which methods shall be intercepted
    @Around("execution(* com.company.service..*(..)))")
    public Object profileAllMethods(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
    {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();

        //Get intercepted method details
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();

        final StopWatch stopWatch = new StopWatch();

        //Measure method execution time
        stopWatch.start();
        Object result = proceedingJoinPoint.proceed();
        stopWatch.stop();

        //Log method execution time
        log.info("Execution time of " + className + "." + methodName + " :: " + stopWatch.getTotalTimeMillis() + " ms");

        return result;
    }
}

实际上,正如@Toerktumlare在注释
proceedingJoinPoint.procedure()
返回对象的类型,无论控制器端点返回类型是什么,因此可以保持反应性。注意
.subscribeOn(Schedulers.parallel())
在这里是可选的,即我的后台代码支持并行性。为此发布解决方案:

@Aspect
@Component
@Slf4j
public class LoggingAspect
{

    //AOP expression for which methods shall be intercepted
    @Around("execution(* com.company.service..*(..)))")
    public Object logEndpointPerformance(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
    {
        MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();

        //Get intercepted method details
        String className = methodSignature.getDeclaringType().getSimpleName();
        String methodName = methodSignature.getName();

        final StopWatch stopWatch = new StopWatch();

        //Measure method execution time
        stopWatch.start();
        Object result = proceedingJoinPoint.proceed();

        if(result instanceof Mono){
            return ((Mono)result).subscribeOn(Schedulers.parallel()).flatMap(r -> {
                logExecutionTime(className, methodName, stopWatch);
                return Mono.just(r);
            });
        }
        else if(result instanceof Flux){
            return ((Flux<Object>)result).subscribeOn(Schedulers.parallel()).collectList().flatMapMany(r -> {
                logExecutionTime(className, methodName, stopWatch);
                return Flux.fromIterable(r);
            });
        }
        else{
            logExecutionTime(className, methodName, stopWatch);
            return result;
        }
    }

    private void logExecutionTime(final String className, final String methodName, final StopWatch stopWatch){
        stopWatch.stop();
        //Log method execution time
        log.debug("[ " + stopWatch.getTotalTimeMillis() + " mls ] lasted execution of" + className + "." + methodName );
    }
}
@方面
@组成部分
@Slf4j
公共类日志方面
{
//应截取哪些方法的AOP表达式
@关于(“执行(*com.company.service.*(…))”)
公共对象logEndpointPerformance(ProceedingJoinPoint ProceedingJoinPoint)抛出可丢弃
{
MethodSignature MethodSignature=(MethodSignature)proceedingJoinPoint.getSignature();
//获取截获的方法详细信息
String className=methodSignature.getDeclaringType().getSimpleName();
字符串methodName=methodSignature.getName();
最终秒表秒表=新秒表();
//度量方法执行时间
秒表。开始();
对象结果=proceedingJoinPoint.procedure();
如果(单声道的结果实例){
return((Mono)result).subscribeOn(Schedulers.parallel()).flatMap(r->{
日志执行时间(类名、方法名、秒表);
返回Mono.just(r);
});
}
else if(通量的结果实例){
返回((通量)结果).subscribeOn(Schedulers.parallel()).collectList().flatMapMany(r->{
日志执行时间(类名、方法名、秒表);
返回通量。可计算(r);
});
}
否则{
日志执行时间(类名、方法名、秒表);
返回结果;
}
}
私有void logExecutionTime(最终字符串类名称、最终字符串方法名称、最终秒表秒表){
秒表;
//日志方法执行时间
log.debug(“[”+stopWatch.getTotalItemillis()+“mls]持续执行“+className+”+methodName”);
}
}

您可以使用
instanceof
进行检查,并将其转换为mono或flux。一个对象没有阻塞,这取决于什么类型的对象决定它是否阻塞。@Toerktumlare真的吗?我会检查一下,谢谢。但另一方面,你不能像以前那样对函数计时,因为Mono/Flux会立即返回(很像未来)。如果你想给一个函数计时,你需要得到一个开始时间,并将它放入反应式上下文中,然后在链的后面,得到另一个时间,从上下文中检索第一个时间,然后计算经过的时间。@Toerktumlare Yep做了类似的事情,与上下文一起传递,它算得上是正确的。在我看来,它不包括事务打开、R2dbc连接释放时间,因为对于执行,我接收到例如1秒,但postman显示1.5秒。谢谢大家!@Toerktumlare发布了我拥有的最终代码不要忘记接受你自己的答案以结束问题。非常感谢。