Java 如何在包含反应管道创建者堆栈跟踪的反应管道执行中引发异常?
如果我运行以下反应管道:Java 如何在包含反应管道创建者堆栈跟踪的反应管道执行中引发异常?,java,debugging,java-8,reactive-programming,spring-webflux,Java,Debugging,Java 8,Reactive Programming,Spring Webflux,如果我运行以下反应管道: Mono.empty() .switchIfEmpty(Mono.defer(()->Mono.error(new RuntimeException())) .block(); 我得到反应步骤的堆栈跟踪(switchIfEmpty);但我对管道创建者的堆栈跟踪感兴趣。反应堆栈跟踪部分是无用的,我实际上对调试触发管道创建的请求感兴趣(该请求是按子顺序执行的) 即使管道创建者的堆栈跟踪有时显示在反应性堆栈元素下面,也不能保证,因为我看到过有太多意外分支的管道在最坏的情况下
Mono.empty()
.switchIfEmpty(Mono.defer(()->Mono.error(new RuntimeException()))
.block();
我得到反应步骤的堆栈跟踪(switchIfEmpty
);但我对管道创建者的堆栈跟踪感兴趣。反应堆栈跟踪部分是无用的,我实际上对调试触发管道创建的请求感兴趣(该请求是按子顺序执行的)
即使管道创建者的堆栈跟踪有时显示在反应性堆栈元素下面,也不能保证,因为我看到过有太多意外分支的管道在最坏的情况下丢失了管道创建者堆栈跟踪。最好的情况是,感兴趣的堆栈跟踪被隐藏在堆栈元素之下,这使得调试几乎不可能
由于我正在创建的管道将用于通过网络执行往返请求,因此我同意一个解决方案,该解决方案要求支付的最高性能价格相当于比执行网络请求往返成本低1个数量级。该解决方案非常简单:
Mono.empty()
.switchIfEmpty(Mono.error(新的RuntimeException()))
.block();
该管道在性能方面将更加昂贵;但将尊重OP的要求,即不增加超过网络请求往返成本的一小部分
以下测试用例验证并说明(检查打印输出序列)此技术的有效性,以获得所需的堆栈跟踪:
import org.junit.jupiter.api.Test;
导入java.io.PrintWriter;
导入java.io.StringWriter;
导入reactor.core.publisher.Mono;
进口反应器、测试、步进校验器;
公共类MonoSwitchIfEmptyTest{
@试验
当通过预编译异常请求\u thenExpectDesiredStackTrace()时无效{
尝试使用DesiredStackTrace切换IfEmptyWithDesiredStackTrace(CreateApprovedSwitchIfEmptyNo(true),true);
}
@试验
当请求通过LiveException时无效\u thenExpectedUnderseedStackTrace(){
尝试使用DesiredStackTrace切换IfEmptyWithDesiredStackTrace(CreateApprovedSwitchIfEmptyNo(false),false);
}
//这里这样做是为了强制在堆栈跟踪中创建额外的堆栈元素。
//该堆栈元素是稍后将被检查以确定测试是否通过的元素。
私有Mono CreateApprovedSwitchIfEmptyNo(布尔desiredStackTrace){
返回desiredStackTrace?
Mono.error(新的LoggedRuntimeException()):
Mono.defer(()->Mono.error(新的LoggedRuntimeException());
}
私有void trySwitchIfEmptyWithDesiredStackTrace(Mono-SwitchifemptyNo,boolean-desiredStackTrace){
Mono loggedError=Mono.fromRunnable(()->System.out.println(“引发异常…”))
。然后(切换IFEMPTYMONO);
Mono testedPipeline=Mono.fromRunnable(()->loggedBusyWork(1000))
.switchIfEmpty(loggedError);
StepVerifier.create(testedPipeline)
.expectErrorMatches(e->((LoggedRuntimeException)e).isRelevantStackTrace()==desiredStackTrace)
.verify();
}
专用void loggedBusyWork(整数毫秒){
long startTime=System.currentTimeMillis();
System.out.println(“开始忙碌的工作@”+startTime+”);
而(System.currentTimeMillis()-startTime