为什么默认配置的 spring webflux 中没有异常堆栈跟踪?
Why there is no exception stack trace in spring webflux with default configuration?
问题
我按照 Webflux functional programming 构建了一个服务器,并在我的路由器中添加了以下代码:route(GET("/test/{Id}"), request -> throw new RuntimeException("123"))
.
但是当我调用 /test/{Id}
时,控制台中唯一的错误日志是:
TRACE 153036 --- [ctor-http-nio-7] o.s.w.r.function.server.RouterFunctions : [fc7e809d] Matched org.springframework.web.reactive.function.server.RequestPredicates$$Lambda7/1369035321@9d8c274
DEBUG 153036 --- [ctor-http-nio-7] org.springframework.web.HttpLogging : [fc7e809d] Resolved [RuntimeException: 123] for HTTP GET /test/job
TRACE 153036 --- [ctor-http-nio-7] org.springframework.web.HttpLogging : [fc7e809d] Encoding [{timestamp=Mon Dec 17 15:34:43 CST 2018, path=/test/123, status=500, error=Internal Server Error, message=123}]
TRACE 153036 --- [ctor-http-nio-7] o.s.w.s.adapter.HttpWebHandlerAdapter : [fc7e809d] Completed 500 INTERNAL_SERVER_ERROR, headers={masked}
TRACE 153036 --- [ctor-http-nio-7] org.springframework.web.HttpLogging : [fc7e809d] Handling completed
没有stack trace,但是为什么呢?应该是spring或者netty处理的,不是我自定义的代码吧?设置 logging.level.org.springframework.web: trace
不是解决方案,日志太多。
这是我目前的发现,但仍然很困惑:
我检查了为什么spring mvc 有stack trace,因为tomcat里面有一个log.error in try-catch 并且调试证明了。
然后我想Netty也有这些逻辑吗?居然是has!但让我感到困惑的是,我无法使用任何断点暂停此 try-catch 中的代码。
这意味着可能存在一些 Mono.onErrorResume
吞噬异常,所以 netty 无法捕捉到任何东西。但我不知道如何调试大型 Mono 来检查根本原因。为什么要吞下它?
选项 1A:设置应用程序属性如下:
server.error.includeStacktrace=ALWAYS
选项 1B:设置应用程序属性如下:
server.error.includeStacktrace=ON_TRACE_PARAM
和,指定请求参数trace
为true
.
选项 2:添加自定义的 WebExceptionHandler,并确保它在组件扫描范围内。
@Component
@Order(-2)
public class LoggingErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(LoggingErrorWebExceptionHandler.class);
public LoggingErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
ServerProperties serverProperties, ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, resourceProperties, serverProperties.getError(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
}
@Override
protected void logError(ServerRequest request, HttpStatus errorStatus) {
Throwable ex = getError(request);
logger.error("Error Occurred:", ex);
super.logError(request, errorStatus);
}
}
有关详细信息,请参阅 https://www.baeldung.com/spring-webflux-errors。
问题
我按照 Webflux functional programming 构建了一个服务器,并在我的路由器中添加了以下代码:route(GET("/test/{Id}"), request -> throw new RuntimeException("123"))
.
但是当我调用 /test/{Id}
时,控制台中唯一的错误日志是:
TRACE 153036 --- [ctor-http-nio-7] o.s.w.r.function.server.RouterFunctions : [fc7e809d] Matched org.springframework.web.reactive.function.server.RequestPredicates$$Lambda7/1369035321@9d8c274
DEBUG 153036 --- [ctor-http-nio-7] org.springframework.web.HttpLogging : [fc7e809d] Resolved [RuntimeException: 123] for HTTP GET /test/job
TRACE 153036 --- [ctor-http-nio-7] org.springframework.web.HttpLogging : [fc7e809d] Encoding [{timestamp=Mon Dec 17 15:34:43 CST 2018, path=/test/123, status=500, error=Internal Server Error, message=123}]
TRACE 153036 --- [ctor-http-nio-7] o.s.w.s.adapter.HttpWebHandlerAdapter : [fc7e809d] Completed 500 INTERNAL_SERVER_ERROR, headers={masked}
TRACE 153036 --- [ctor-http-nio-7] org.springframework.web.HttpLogging : [fc7e809d] Handling completed
没有stack trace,但是为什么呢?应该是spring或者netty处理的,不是我自定义的代码吧?设置 logging.level.org.springframework.web: trace
不是解决方案,日志太多。
这是我目前的发现,但仍然很困惑:
我检查了为什么spring mvc 有stack trace,因为tomcat里面有一个log.error in try-catch 并且调试证明了。
然后我想Netty也有这些逻辑吗?居然是has!但让我感到困惑的是,我无法使用任何断点暂停此 try-catch 中的代码。
这意味着可能存在一些 Mono.onErrorResume
吞噬异常,所以 netty 无法捕捉到任何东西。但我不知道如何调试大型 Mono 来检查根本原因。为什么要吞下它?
选项 1A:设置应用程序属性如下:
server.error.includeStacktrace=ALWAYS
选项 1B:设置应用程序属性如下:
server.error.includeStacktrace=ON_TRACE_PARAM
和,指定请求参数trace
为true
.
选项 2:添加自定义的 WebExceptionHandler,并确保它在组件扫描范围内。
@Component
@Order(-2)
public class LoggingErrorWebExceptionHandler extends DefaultErrorWebExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(LoggingErrorWebExceptionHandler.class);
public LoggingErrorWebExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
ServerProperties serverProperties, ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, resourceProperties, serverProperties.getError(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
}
@Override
protected void logError(ServerRequest request, HttpStatus errorStatus) {
Throwable ex = getError(request);
logger.error("Error Occurred:", ex);
super.logError(request, errorStatus);
}
}
有关详细信息,请参阅 https://www.baeldung.com/spring-webflux-errors。