Skip to content

Commit

Permalink
Remove Undertow dependency from Opentracing
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas committed Nov 18, 2019
1 parent 3035658 commit d5b4495
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -111,15 +114,23 @@ private void dispatch(RoutingContext routingContext, InputStream is, VertxOutput
} catch (Throwable ex) {
routingContext.fail(ex);
}

boolean suspended = vertxRequest.getAsyncContext().isSuspended();
currentVertxRequest.initialInvocationComplete(suspended);
boolean requestContextActive = requestContext.isActive();
if (requestContextActive) {
//it is possible that there was an async response, that then finished in the same thread
//the async response will have terminated the request context in this case
currentVertxRequest.initialInvocationComplete(suspended);
}
if (!suspended) {
try {
vertxResponse.finish();
} catch (IOException e) {
log.error("Unexpected failure", e);
} finally {
requestContext.terminate();
if (requestContextActive) {
requestContext.terminate();
}
}
} else {
//we need the request context to stick around
Expand All @@ -129,7 +140,9 @@ private void dispatch(RoutingContext routingContext, InputStream is, VertxOutput
try {
routingContext.fail(t);
} finally {
requestContext.terminate();
if (requestContext.isActive()) {
requestContext.terminate();
}
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions extensions/smallrye-opentracing/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-undertow-deployment</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-arc-deployment</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -33,21 +35,28 @@ ReflectiveMethodBuildItem registerMethod() throws Exception {
@BuildStep
void setupFilter(BuildProducer<ResteasyJaxrsProviderBuildItem> providers,
BuildProducer<FilterBuildItem> filterProducer,
BuildProducer<FeatureBuildItem> feature) {
BuildProducer<FeatureBuildItem> 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()));
}
}

}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ public static void afterAll() {
}

@Test
public void testSingleServerRequest() {
public void testSingleServerRequest() throws InterruptedException {
try {
RestAssured.defaultParser = Parser.TEXT;
RestAssured.when().get("/hello")
.then()
.statusCode(200);
Assertions.assertEquals(1, mockTracer.finishedSpans().size());
//inherently racy, tracer is completed after response is sent back to the client
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.until(() -> mockTracer.finishedSpans().size() == 1);
Assertions.assertEquals("GET:io.quarkus.smallrye.opentracing.deployment.TestResource.hello",
mockTracer.finishedSpans().get(0).operationName());
} finally {
Expand All @@ -61,12 +63,15 @@ public void testSingleServerRequest() {
}

@Test
public void testCDI() {
public void testCDI() throws InterruptedException {
try {
RestAssured.defaultParser = Parser.TEXT;
RestAssured.when().get("/cdi")
.then()
.statusCode(200);
//inherently racy, tracer is completed after response is sent back to the client
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.until(() -> mockTracer.finishedSpans().size() == 2);
Assertions.assertEquals(2, mockTracer.finishedSpans().size());
Assertions.assertEquals("io.quarkus.smallrye.opentracing.deployment.Service.foo",
mockTracer.finishedSpans().get(0).operationName());
Expand All @@ -78,16 +83,21 @@ public void testCDI() {
}

@Test
public void testMPRestClient() {
public void testMPRestClient() throws InterruptedException {
try {
RestAssured.defaultParser = Parser.TEXT;
RestAssured.when().get("/restClient")
.then()
.statusCode(200);
//inherently racy, tracer is completed after response is sent back to the client
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.until(() -> mockTracer.finishedSpans().size() == 3);
Assertions.assertEquals(3, mockTracer.finishedSpans().size());
Assertions.assertEquals("GET:io.quarkus.smallrye.opentracing.deployment.TestResource.hello",
mockTracer.finishedSpans().get(0).operationName());
Assertions.assertEquals("GET", mockTracer.finishedSpans().get(1).operationName());
//these can come in any order, as the 'hello' span is finished after the request is sent back.
//this means the client might have already dealt with the response before the hello span is finished
// Assertions.assertEquals("GET:io.quarkus.smallrye.opentracing.deployment.TestResource.hello",
// mockTracer.finishedSpans().get(0).operationName());
// Assertions.assertEquals("GET", mockTracer.finishedSpans().get(1).operationName());
Assertions.assertEquals("GET:io.quarkus.smallrye.opentracing.deployment.TestResource.restClient",
mockTracer.finishedSpans().get(2).operationName());
} finally {
Expand Down
2 changes: 1 addition & 1 deletion extensions/smallrye-opentracing/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-undertow</artifactId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, Object> errorLogs = new HashMap<>(2);
errorLogs.put("event", Tags.ERROR.getKey());
errorLogs.put("error.object", throwable);
span.log(errorLogs);
}
}
}
}

0 comments on commit d5b4495

Please sign in to comment.