diff --git a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java index 77f28738c2e7c..1828004e76b13 100644 --- a/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java +++ b/extensions/resteasy/runtime/src/main/java/io/quarkus/resteasy/runtime/standalone/VertxRequestHandler.java @@ -72,16 +72,19 @@ public void handle(RoutingContext request) { vertx.executeBlocking(event -> { dispatch(request, is, new VertxBlockingOutput(request.request())); }, false, event -> { + if (event.failed()) { + request.fail(event.cause()); + } }); } private void dispatch(RoutingContext routingContext, InputStream is, VertxOutput output) { + ManagedContext requestContext = beanContainer.requestContext(); + requestContext.activate(); QuarkusHttpUser user = (QuarkusHttpUser) routingContext.user(); if (user != null && association != null) { association.setIdentity(user.getSecurityIdentity()); } - ManagedContext requestContext = beanContainer.requestContext(); - requestContext.activate(); currentVertxRequest.setCurrent(routingContext); try { Context ctx = vertx.getOrCreateContext(); diff --git a/extensions/smallrye-opentracing/deployment/pom.xml b/extensions/smallrye-opentracing/deployment/pom.xml index f96c0923ac6bc..704196b321f8e 100644 --- a/extensions/smallrye-opentracing/deployment/pom.xml +++ b/extensions/smallrye-opentracing/deployment/pom.xml @@ -22,10 +22,6 @@ io.quarkus quarkus-resteasy-deployment - - io.quarkus - quarkus-undertow-deployment - io.quarkus quarkus-arc-deployment diff --git a/extensions/smallrye-opentracing/deployment/src/main/java/io/quarkus/smallrye/opentracing/deployment/SmallRyeOpenTracingProcessor.java b/extensions/smallrye-opentracing/deployment/src/main/java/io/quarkus/smallrye/opentracing/deployment/SmallRyeOpenTracingProcessor.java index 23ff2fd62f32b..26306b4c2b6ef 100644 --- a/extensions/smallrye-opentracing/deployment/src/main/java/io/quarkus/smallrye/opentracing/deployment/SmallRyeOpenTracingProcessor.java +++ b/extensions/smallrye-opentracing/deployment/src/main/java/io/quarkus/smallrye/opentracing/deployment/SmallRyeOpenTracingProcessor.java @@ -8,12 +8,14 @@ import io.opentracing.contrib.interceptors.OpenTracingInterceptor; import io.opentracing.contrib.jaxrs2.server.SpanFinishingFilter; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.deployment.Capabilities; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveMethodBuildItem; import io.quarkus.resteasy.common.spi.ResteasyJaxrsProviderBuildItem; import io.quarkus.smallrye.opentracing.runtime.QuarkusSmallRyeTracingDynamicFeature; +import io.quarkus.smallrye.opentracing.runtime.QuarkusSmallRyeTracingStandaloneVertxDynamicFeature; import io.quarkus.smallrye.opentracing.runtime.TracerProducer; import io.quarkus.undertow.deployment.FilterBuildItem; @@ -33,21 +35,28 @@ ReflectiveMethodBuildItem registerMethod() throws Exception { @BuildStep void setupFilter(BuildProducer providers, BuildProducer filterProducer, - BuildProducer feature) { + BuildProducer feature, + Capabilities capabilities) { feature.produce(new FeatureBuildItem(FeatureBuildItem.SMALLRYE_OPENTRACING)); providers.produce(new ResteasyJaxrsProviderBuildItem(QuarkusSmallRyeTracingDynamicFeature.class.getName())); - FilterBuildItem filterInfo = FilterBuildItem.builder("tracingFilter", SpanFinishingFilter.class.getName()) - .setAsyncSupported(true) - .addFilterUrlMapping("*", DispatcherType.FORWARD) - .addFilterUrlMapping("*", DispatcherType.INCLUDE) - .addFilterUrlMapping("*", DispatcherType.REQUEST) - .addFilterUrlMapping("*", DispatcherType.ASYNC) - .addFilterUrlMapping("*", DispatcherType.ERROR) - .build(); - filterProducer.produce(filterInfo); + if (capabilities.isCapabilityPresent(Capabilities.SERVLET)) { + FilterBuildItem filterInfo = FilterBuildItem.builder("tracingFilter", SpanFinishingFilter.class.getName()) + .setAsyncSupported(true) + .addFilterUrlMapping("*", DispatcherType.FORWARD) + .addFilterUrlMapping("*", DispatcherType.INCLUDE) + .addFilterUrlMapping("*", DispatcherType.REQUEST) + .addFilterUrlMapping("*", DispatcherType.ASYNC) + .addFilterUrlMapping("*", DispatcherType.ERROR) + .build(); + filterProducer.produce(filterInfo); + } else { + //otherwise we know we have RESTeasy on vert.x + providers.produce( + new ResteasyJaxrsProviderBuildItem(QuarkusSmallRyeTracingStandaloneVertxDynamicFeature.class.getName())); + } } } diff --git a/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracerRegistrar.java b/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracerRegistrar.java index 3e86ea8b8d216..2b8705eeca508 100644 --- a/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracerRegistrar.java +++ b/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracerRegistrar.java @@ -1,16 +1,15 @@ package io.quarkus.smallrye.opentracing.deployment; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.annotation.WebListener; +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; import io.opentracing.util.GlobalTracer; +import io.quarkus.runtime.StartupEvent; -@WebListener -public class TracerRegistrar implements ServletContextListener { +@ApplicationScoped +public class TracerRegistrar { - @Override - public void contextInitialized(ServletContextEvent sce) { + public void start(@Observes StartupEvent start) { GlobalTracer.register(TracingTest.mockTracer); } } diff --git a/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracingTest.java b/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracingTest.java index 9ab1d26d7b9ac..91efafa94af0c 100644 --- a/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracingTest.java +++ b/extensions/smallrye-opentracing/deployment/src/test/java/io/quarkus/smallrye/opentracing/deployment/TracingTest.java @@ -46,7 +46,7 @@ public static void afterAll() { } @Test - public void testSingleServerRequest() { + public void testSingleServerRequest() throws InterruptedException { try { RestAssured.defaultParser = Parser.TEXT; RestAssured.when().get("/hello") diff --git a/extensions/smallrye-opentracing/runtime/pom.xml b/extensions/smallrye-opentracing/runtime/pom.xml index f68c44a410a23..3b4b099c8491b 100644 --- a/extensions/smallrye-opentracing/runtime/pom.xml +++ b/extensions/smallrye-opentracing/runtime/pom.xml @@ -46,7 +46,7 @@ io.quarkus - quarkus-undertow + quarkus-resteasy io.quarkus diff --git a/extensions/smallrye-opentracing/runtime/src/main/java/io/quarkus/smallrye/opentracing/runtime/QuarkusSmallRyeTracingStandaloneVertxDynamicFeature.java b/extensions/smallrye-opentracing/runtime/src/main/java/io/quarkus/smallrye/opentracing/runtime/QuarkusSmallRyeTracingStandaloneVertxDynamicFeature.java new file mode 100644 index 0000000000000..2ce0f0b01aa9d --- /dev/null +++ b/extensions/smallrye-opentracing/runtime/src/main/java/io/quarkus/smallrye/opentracing/runtime/QuarkusSmallRyeTracingStandaloneVertxDynamicFeature.java @@ -0,0 +1,79 @@ +package io.quarkus.smallrye.opentracing.runtime; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.enterprise.inject.spi.CDI; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; +import javax.ws.rs.container.DynamicFeature; +import javax.ws.rs.container.ResourceInfo; +import javax.ws.rs.core.FeatureContext; +import javax.ws.rs.ext.Provider; + +import io.opentracing.Span; +import io.opentracing.contrib.jaxrs2.internal.SpanWrapper; +import io.opentracing.tag.Tags; +import io.quarkus.vertx.http.runtime.CurrentVertxRequest; +import io.vertx.ext.web.RoutingContext; + +@Provider +public class QuarkusSmallRyeTracingStandaloneVertxDynamicFeature implements DynamicFeature { + + @Override + public void configure(ResourceInfo resourceInfo, FeatureContext context) { + context.register(StandaloneFilter.class); + } + + public static class StandaloneFilter implements ContainerRequestFilter { + + volatile CurrentVertxRequest currentVertxRequest; + + CurrentVertxRequest request() { + if (currentVertxRequest == null) { + currentVertxRequest = CDI.current().select(CurrentVertxRequest.class).get(); + } + return currentVertxRequest; + } + + @Override + public void filter(ContainerRequestContext requestContext) throws IOException { + request().addRequestDoneListener(new CurrentVertxRequest.Listener() { + @Override + public void initialInvocationComplete(RoutingContext routingContext, boolean goingAsync) { + SpanWrapper wrapper = routingContext.get(SpanWrapper.PROPERTY_NAME); + if (wrapper != null) { + wrapper.getScope().close(); + } + } + + @Override + public void responseComplete(RoutingContext routingContext) { + SpanWrapper wrapper = routingContext.get(SpanWrapper.PROPERTY_NAME); + if (wrapper == null) { + return; + } + + Tags.HTTP_STATUS.set(wrapper.get(), routingContext.response().getStatusCode()); + if (routingContext.failure() != null) { + addExceptionLogs(wrapper.get(), routingContext.failure()); + } + wrapper.finish(); + + } + }); + + } + + private static void addExceptionLogs(Span span, Throwable throwable) { + Tags.ERROR.set(span, true); + if (throwable != null) { + Map errorLogs = new HashMap<>(2); + errorLogs.put("event", Tags.ERROR.getKey()); + errorLogs.put("error.object", throwable); + span.log(errorLogs); + } + } + } +}