From 14edff839f691722f167068940990ccc8cc9e709 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Tue, 4 Jul 2023 15:32:13 +0300 Subject: [PATCH] Track exceptions thrown during JAX-RS processing in the current span Fixes: #30462 Fixes: #27384 --- ...penTelemetryResteasyReactiveProcessor.java | 7 ++++ .../runtime/AttachExceptionHandler.java | 16 ++++++++ .../opentelemetry-reactive/pom.xml | 5 +++ .../reactive/ReactiveResource.java | 14 +++++++ .../reactive/OpenTelemetryReactiveTest.java | 41 +++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 extensions/opentelemetry-resteasy-reactive/runtime/src/main/java/io/quarkus/opentelemetry/resteasy/reactive/runtime/AttachExceptionHandler.java diff --git a/extensions/opentelemetry-resteasy-reactive/deployment/src/main/java/io/quarkus/opentelemetry/resteasy/reactive/deployment/OpenTelemetryResteasyReactiveProcessor.java b/extensions/opentelemetry-resteasy-reactive/deployment/src/main/java/io/quarkus/opentelemetry/resteasy/reactive/deployment/OpenTelemetryResteasyReactiveProcessor.java index fb3527753bb20..a969cdbd088a3 100644 --- a/extensions/opentelemetry-resteasy-reactive/deployment/src/main/java/io/quarkus/opentelemetry/resteasy/reactive/deployment/OpenTelemetryResteasyReactiveProcessor.java +++ b/extensions/opentelemetry-resteasy-reactive/deployment/src/main/java/io/quarkus/opentelemetry/resteasy/reactive/deployment/OpenTelemetryResteasyReactiveProcessor.java @@ -5,7 +5,9 @@ import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.opentelemetry.deployment.spi.OpenTelemetryTracerEnabledBuildItem; +import io.quarkus.opentelemetry.resteasy.reactive.runtime.AttachExceptionHandler; import io.quarkus.opentelemetry.resteasy.reactive.runtime.OpenTelemetryReactiveServerFilter; +import io.quarkus.resteasy.reactive.server.deployment.PreExceptionMapperHandlerBuildItem; import io.quarkus.resteasy.reactive.spi.CustomContainerRequestFilterBuildItem; public class OpenTelemetryResteasyReactiveProcessor { @@ -21,4 +23,9 @@ void registerResteasyReactiveProvider(Optionalwiremock-jre8-standalone test + + org.assertj + assertj-core + test + diff --git a/integration-tests/opentelemetry-reactive/src/main/java/io/quarkus/it/opentelemetry/reactive/ReactiveResource.java b/integration-tests/opentelemetry-reactive/src/main/java/io/quarkus/it/opentelemetry/reactive/ReactiveResource.java index a08c9f3fbaffc..02f94b5493f59 100644 --- a/integration-tests/opentelemetry-reactive/src/main/java/io/quarkus/it/opentelemetry/reactive/ReactiveResource.java +++ b/integration-tests/opentelemetry-reactive/src/main/java/io/quarkus/it/opentelemetry/reactive/ReactiveResource.java @@ -51,4 +51,18 @@ public Uni helloPost(String body) { return Uni.createFrom().item("Hello " + body).onItem().delayIt().by(Duration.ofSeconds(2)) .eventually((Runnable) span::end); } + + @Path("blockingException") + @GET + public String blockingException() { + throw new RuntimeException("dummy"); + } + + @Path("reactiveException") + @GET + public Uni reactiveException() { + return Uni.createFrom().item(() -> { + throw new RuntimeException("dummy2"); + }); + } } diff --git a/integration-tests/opentelemetry-reactive/src/test/java/io/quarkus/it/opentelemetry/reactive/OpenTelemetryReactiveTest.java b/integration-tests/opentelemetry-reactive/src/test/java/io/quarkus/it/opentelemetry/reactive/OpenTelemetryReactiveTest.java index 0f899d27bc4b8..c239e6b2984cf 100644 --- a/integration-tests/opentelemetry-reactive/src/test/java/io/quarkus/it/opentelemetry/reactive/OpenTelemetryReactiveTest.java +++ b/integration-tests/opentelemetry-reactive/src/test/java/io/quarkus/it/opentelemetry/reactive/OpenTelemetryReactiveTest.java @@ -11,6 +11,7 @@ import static io.restassured.RestAssured.given; import static java.net.HttpURLConnection.HTTP_OK; import static java.util.stream.Collectors.toSet; +import static org.assertj.core.api.Assertions.*; import static org.awaitility.Awaitility.await; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -53,6 +54,46 @@ void get() { assertEquals(spans.get(0).get("traceId"), spans.get(1).get("traceId")); } + @Test + void blockingException() { + given() + .when() + .get("/reactive/blockingException") + .then() + .statusCode(500); + + assertExceptionRecorded(); + } + + @Test + void reactiveException() { + given() + .when() + .get("/reactive/reactiveException") + .then() + .statusCode(500); + + assertExceptionRecorded(); + } + + private static void assertExceptionRecorded() { + await().atMost(5, TimeUnit.SECONDS).until(() -> getSpans().size() == 1); + List> spans = getSpans(); + assertThat(spans).singleElement().satisfies(span -> { + assertThat(span).containsKey("events").extractingByKey("events").isInstanceOfSatisfying(List.class, (ev) -> { + assertThat((List>) ev).singleElement().isInstanceOfSatisfying(Map.class, e -> { + assertThat(e).containsKey("exception").extractingByKey("exception").isInstanceOfSatisfying(Map.class, + ex -> { + assertThat((Map) ex).containsKey("stackTrace").extractingByKey("stackTrace") + .isInstanceOfSatisfying(List.class, st -> { + assertThat(st).hasSizeGreaterThan(5); + }); + }); + }); + }); + }); + } + @Test void post() { given()