From b0438497beb2eea67200d307319493a2bb9cf6ec Mon Sep 17 00:00:00 2001 From: Phillip Kruger Date: Thu, 18 Jul 2024 12:59:14 +1000 Subject: [PATCH] Only decorate in Dev Mode Signed-off-by: Phillip Kruger --- .../vertx/http/runtime/HttpConfiguration.java | 8 ++++++++ .../vertx/http/runtime/QuarkusErrorHandler.java | 9 +++++++-- .../vertx/http/runtime/VertxHttpRecorder.java | 12 ++++++++++-- .../http/runtime/QuarkusErrorHandlerTest.java | 16 ++++++++++------ 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java index 8a5465f671650..1925f0f0f9bde 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/HttpConfiguration.java @@ -289,6 +289,14 @@ public class HttpConfiguration { @ConfigItem public Map filter; + /** + * This will decorate the stacktrace to show the line in the code that cause the exception + * By default, this is enabled in Dev Mode and disabled in all other modes. Making this true will enable it in all mode + * and making this false will disable this in all modes. + */ + @ConfigItem + public Optional decorateStacktraces; + public ProxyConfig proxy; public int determinePort(LaunchMode launchMode) { diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java index 939578d216584..20c10be2eb202 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandler.java @@ -41,10 +41,13 @@ public class QuarkusErrorHandler implements Handler { private static final AtomicLong ERROR_COUNT = new AtomicLong(); private final boolean showStack; + private final boolean decorateStack; private final Optional contentTypeDefault; - public QuarkusErrorHandler(boolean showStack, Optional contentTypeDefault) { + public QuarkusErrorHandler(boolean showStack, boolean decorateStack, + Optional contentTypeDefault) { this.showStack = showStack; + this.decorateStack = decorateStack; this.contentTypeDefault = contentTypeDefault; } @@ -129,7 +132,9 @@ public void accept(Throwable throwable) { exception.addSuppressed(e); } if (showStack && exception != null) { - exception = new DecoratedAssertionError(exception); + if (decorateStack) { + exception = new DecoratedAssertionError(exception); + } details = generateHeaderMessage(exception, uuid); stack = generateStackTrace(exception); } else { diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java index 0b91740c6100b..3a3581eb3ee5e 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/vertx/http/runtime/VertxHttpRecorder.java @@ -414,7 +414,8 @@ public void finalizeRouter(BeanContainer container, Consumer defaultRoute applyCompression(httpBuildTimeConfig.enableCompression, httpRouteRouter); httpRouteRouter.route().last().failureHandler( - new QuarkusErrorHandler(launchMode.isDevOrTest(), httpConfiguration.unhandledErrorContentTypeDefault)); + new QuarkusErrorHandler(launchMode.isDevOrTest(), decorateStacktrace(launchMode, httpConfiguration), + httpConfiguration.unhandledErrorContentTypeDefault)); for (BooleanSupplier requireBodyHandlerCondition : requireBodyHandlerConditions) { if (requireBodyHandlerCondition.getAsBoolean()) { @@ -533,7 +534,8 @@ public void handle(RoutingContext event) { addHotReplacementHandlerIfNeeded(mr); mr.route().last().failureHandler( - new QuarkusErrorHandler(launchMode.isDevOrTest(), httpConfiguration.unhandledErrorContentTypeDefault)); + new QuarkusErrorHandler(launchMode.isDevOrTest(), decorateStacktrace(launchMode, httpConfiguration), + httpConfiguration.unhandledErrorContentTypeDefault)); mr.route().order(RouteConstants.ROUTE_ORDER_BODY_HANDLER_MANAGEMENT) .handler(createBodyHandlerForManagementInterface()); @@ -574,6 +576,12 @@ public void handle(HttpServerRequest event) { } } + private boolean decorateStacktrace(LaunchMode launchMode, HttpConfiguration httpConfiguration) { + return httpConfiguration.decorateStacktraces.orElseGet(() -> { + return launchMode.equals(LaunchMode.DEVELOPMENT); + }); + } + private void addHotReplacementHandlerIfNeeded(Router router) { if (hotReplacementHandler != null) { //recorders are always executed in the current CL diff --git a/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java b/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java index f1634fee29f5f..53de4ac0c9723 100644 --- a/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java +++ b/extensions/vertx-http/runtime/src/test/java/io/quarkus/vertx/http/runtime/QuarkusErrorHandlerTest.java @@ -51,7 +51,8 @@ public void string_with_quotes_should_be_correctly_escaped() { @Test public void json_content_type_hint_should_be_respected_if_not_accepted() { - QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.JSON)); + QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, false, + Optional.of(HttpConfiguration.PayloadHint.JSON)); Mockito.when(routingContext.failure()).thenReturn(testError); Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any())) .thenReturn(new ParsableMIMEValue("application/foo+json").forceParse()); @@ -62,7 +63,8 @@ public void json_content_type_hint_should_be_respected_if_not_accepted() { @Test public void json_content_type_hint_should_be_ignored_if_accepted() { - QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.JSON)); + QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, false, + Optional.of(HttpConfiguration.PayloadHint.JSON)); Mockito.when(routingContext.failure()).thenReturn(testError); Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any())) .thenReturn(new ParsableMIMEValue("text/html").forceParse()); @@ -73,7 +75,7 @@ public void json_content_type_hint_should_be_ignored_if_accepted() { @Test public void content_type_should_default_to_json_if_accepted() { - QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.empty()); + QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, false, Optional.empty()); Mockito.when(routingContext.failure()).thenReturn(testError); Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any())) .thenReturn(new ParsableMIMEValue("application/json").forceParse()); @@ -84,7 +86,8 @@ public void content_type_should_default_to_json_if_accepted() { @Test public void html_content_type_hint_should_be_respected_if_not_accepted() { - QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.HTML)); + QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, false, + Optional.of(HttpConfiguration.PayloadHint.HTML)); Mockito.when(routingContext.failure()).thenReturn(testError); Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any())) .thenReturn(new ParsableMIMEValue("application/foo+json").forceParse()); @@ -94,7 +97,8 @@ public void html_content_type_hint_should_be_respected_if_not_accepted() { @Test public void html_content_type_hint_should_be_ignored_if_accepted() { - QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.of(HttpConfiguration.PayloadHint.HTML)); + QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, false, + Optional.of(HttpConfiguration.PayloadHint.HTML)); Mockito.when(routingContext.failure()).thenReturn(testError); Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any())) .thenReturn(new ParsableMIMEValue("application/json").forceParse()); @@ -105,7 +109,7 @@ public void html_content_type_hint_should_be_ignored_if_accepted() { @Test public void content_type_should_default_to_html_if_accepted() { - QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, Optional.empty()); + QuarkusErrorHandler errorHandler = new QuarkusErrorHandler(false, false, Optional.empty()); Mockito.when(routingContext.failure()).thenReturn(testError); Mockito.when(routingContext.parsedHeaders().findBestUserAcceptedIn(any(), any())) .thenReturn(new ParsableMIMEValue("text/html").forceParse());