Skip to content

Commit 235737f

Browse files
authored
Vertx: wrap internal routes to let the context propagate for blocking handlers (#7563)
* Vertx: wrap internal routes to let the context propagate for blocking handlers * Extend the wrapping advices
1 parent 86d01e6 commit 235737f

File tree

6 files changed

+53
-50
lines changed

6 files changed

+53
-50
lines changed

dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerInstrumentation.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.vertx_3_4.server;
22

33
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
4+
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.namedOneOf;
45
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
56
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
67
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@@ -35,7 +36,7 @@ public String instrumentedType() {
3536
public void methodAdvice(MethodTransformer transformer) {
3637
transformer.applyAdvice(
3738
isMethod()
38-
.and(named("handler"))
39+
.and(namedOneOf("handler", "blockingHandler"))
3940
.and(isPublic())
4041
.and(takesArgument(0, named("io.vertx.core.Handler"))),
4142
packageName + ".RouteHandlerWrapperAdvice");

dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerWrapper.java

+26-15
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,54 @@
99
import datadog.trace.api.gateway.Flow;
1010
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
1111
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
12+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
1213
import datadog.trace.bootstrap.instrumentation.api.Tags;
1314
import io.vertx.core.Handler;
1415
import io.vertx.ext.web.RoutingContext;
15-
import org.slf4j.Logger;
16-
import org.slf4j.LoggerFactory;
16+
import io.vertx.ext.web.impl.RouteImpl;
17+
import io.vertx.ext.web.impl.RouterImpl;
1718

1819
public class RouteHandlerWrapper implements Handler<RoutingContext> {
19-
private static final Logger log = LoggerFactory.getLogger(RouteHandlerWrapper.class);
2020
static final String PARENT_SPAN_CONTEXT_KEY = AgentSpan.class.getName() + ".parent";
2121
static final String HANDLER_SPAN_CONTEXT_KEY = AgentSpan.class.getName() + ".handler";
2222
static final String ROUTE_CONTEXT_KEY = "dd." + Tags.HTTP_ROUTE;
2323

2424
private final Handler<RoutingContext> actual;
25+
private final boolean spanStarter;
2526

2627
public RouteHandlerWrapper(final Handler<RoutingContext> handler) {
2728
actual = handler;
29+
// When mounting a sub router, the handler is a lambda in either RouterImpl or RouteImpl, so
30+
// this skips that. This prevents routers from creating a span during handling. In the event
31+
// a route is not found, without this code, a span would be created for the router when it
32+
// shouldn't
33+
String name = handler.getClass().getName();
34+
spanStarter =
35+
!(name.startsWith(RouterImpl.class.getName())
36+
|| name.startsWith(RouteImpl.class.getName()));
2837
}
2938

3039
@Override
3140
public void handle(final RoutingContext routingContext) {
3241
AgentSpan span = routingContext.get(HANDLER_SPAN_CONTEXT_KEY);
3342
Flow.Action.RequestBlockingAction rba = null;
34-
if (span == null) {
35-
AgentSpan parentSpan = activeSpan();
36-
routingContext.put(PARENT_SPAN_CONTEXT_KEY, parentSpan);
43+
if (spanStarter) {
44+
if (span == null) {
45+
AgentSpan parentSpan = activeSpan();
46+
routingContext.put(PARENT_SPAN_CONTEXT_KEY, parentSpan);
3747

38-
span = startSpan(INSTRUMENTATION_NAME);
39-
routingContext.put(HANDLER_SPAN_CONTEXT_KEY, span);
48+
span = startSpan(INSTRUMENTATION_NAME);
49+
routingContext.put(HANDLER_SPAN_CONTEXT_KEY, span);
4050

41-
routingContext.response().endHandler(new EndHandlerWrapper(routingContext));
42-
DECORATE.afterStart(span);
43-
span.setResourceName(DECORATE.className(actual.getClass()));
44-
}
45-
46-
updateRoutingContextWithRoute(routingContext);
51+
routingContext.response().endHandler(new EndHandlerWrapper(routingContext));
52+
DECORATE.afterStart(span);
53+
span.setResourceName(DECORATE.className(actual.getClass()));
54+
}
4755

48-
try (final AgentScope scope = activateSpan(span)) {
56+
updateRoutingContextWithRoute(routingContext);
57+
}
58+
try (final AgentScope scope =
59+
span != null ? activateSpan(span) : AgentTracer.NoopAgentScope.INSTANCE) {
4960
scope.setAsyncPropagation(true);
5061
try {
5162
actual.handle(routingContext);

dd-java-agent/instrumentation/vertx-web-3.4/src/main/java/datadog/trace/instrumentation/vertx_3_4/server/RouteHandlerWrapperAdvice.java

+1-11
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,12 @@
22

33
import io.vertx.core.Handler;
44
import io.vertx.ext.web.RoutingContext;
5-
import io.vertx.ext.web.impl.RouteImpl;
6-
import io.vertx.ext.web.impl.RouterImpl;
75
import net.bytebuddy.asm.Advice;
86

97
public class RouteHandlerWrapperAdvice {
108
@Advice.OnMethodEnter(suppress = Throwable.class)
119
public static void wrapHandler(
1210
@Advice.Argument(value = 0, readOnly = false) Handler<RoutingContext> handler) {
13-
// When mounting a sub router, the handler is a lambda in either RouterImpl or RouteImpl, so
14-
// this skips that. This prevents routers from creating a span during handling. In the event
15-
// a route is not found, without this code, a span would be created for the router when it
16-
// shouldn't
17-
String name = handler.getClass().getName();
18-
if (!(name.startsWith(RouterImpl.class.getName())
19-
|| name.startsWith(RouteImpl.class.getName()))) {
20-
handler = new RouteHandlerWrapper(handler);
21-
}
11+
handler = new RouteHandlerWrapper(handler);
2212
}
2313
}

dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerInstrumentation.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package datadog.trace.instrumentation.vertx_4_0.server;
22

33
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
4+
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.namedOneOf;
45
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
56
import static net.bytebuddy.matcher.ElementMatchers.isPublic;
67
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@@ -41,7 +42,7 @@ public String instrumentedType() {
4142
public void methodAdvice(MethodTransformer transformer) {
4243
transformer.applyAdvice(
4344
isMethod()
44-
.and(named("handler"))
45+
.and(namedOneOf("handler", "blockingHandler"))
4546
.and(isPublic())
4647
.and(takesArgument(0, named("io.vertx.core.Handler"))),
4748
packageName + ".RouteHandlerWrapperAdvice");

dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerWrapper.java

+21-14
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,49 @@
88

99
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
1010
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
11+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
1112
import datadog.trace.bootstrap.instrumentation.api.Tags;
1213
import io.vertx.core.Handler;
1314
import io.vertx.ext.web.RoutingContext;
14-
import org.slf4j.Logger;
15-
import org.slf4j.LoggerFactory;
15+
import io.vertx.ext.web.impl.RouteImpl;
1616

1717
public class RouteHandlerWrapper implements Handler<RoutingContext> {
18-
private static final Logger log = LoggerFactory.getLogger(RouteHandlerWrapper.class);
1918
static final String PARENT_SPAN_CONTEXT_KEY = AgentSpan.class.getName() + ".parent";
2019
static final String HANDLER_SPAN_CONTEXT_KEY = AgentSpan.class.getName() + ".handler";
2120
static final String ROUTE_CONTEXT_KEY = "dd." + Tags.HTTP_ROUTE;
2221

2322
private final Handler<RoutingContext> actual;
23+
private final boolean spanStarter;
2424

2525
public RouteHandlerWrapper(final Handler<RoutingContext> handler) {
2626
actual = handler;
27+
// When mounting a sub router, the handler is a method reference to the routers handleContext
28+
// method this skips that. This prevents routers from creating a span during handling. In the
29+
// event a route is not found, without this code, a span would be created for the router when
30+
// it shouldn't
31+
spanStarter = !handler.getClass().getName().startsWith(RouteImpl.class.getName());
2732
}
2833

2934
@Override
3035
public void handle(final RoutingContext routingContext) {
3136
AgentSpan span = routingContext.get(HANDLER_SPAN_CONTEXT_KEY);
32-
if (span == null) {
33-
AgentSpan parentSpan = activeSpan();
34-
routingContext.put(PARENT_SPAN_CONTEXT_KEY, parentSpan);
37+
if (spanStarter) {
38+
if (span == null) {
39+
AgentSpan parentSpan = activeSpan();
40+
routingContext.put(PARENT_SPAN_CONTEXT_KEY, parentSpan);
3541

36-
span = startSpan(INSTRUMENTATION_NAME);
37-
routingContext.put(HANDLER_SPAN_CONTEXT_KEY, span);
42+
span = startSpan(INSTRUMENTATION_NAME);
43+
routingContext.put(HANDLER_SPAN_CONTEXT_KEY, span);
3844

39-
routingContext.response().endHandler(new EndHandlerWrapper(routingContext));
40-
DECORATE.afterStart(span);
41-
span.setResourceName(DECORATE.className(actual.getClass()));
45+
routingContext.response().endHandler(new EndHandlerWrapper(routingContext));
46+
DECORATE.afterStart(span);
47+
span.setResourceName(DECORATE.className(actual.getClass()));
48+
}
49+
updateRoutingContextWithRoute(routingContext);
4250
}
4351

44-
updateRoutingContextWithRoute(routingContext);
45-
46-
try (final AgentScope scope = activateSpan(span)) {
52+
try (final AgentScope scope =
53+
span != null ? activateSpan(span) : AgentTracer.NoopAgentScope.INSTANCE) {
4754
scope.setAsyncPropagation(true);
4855
try {
4956
actual.handle(routingContext);

dd-java-agent/instrumentation/vertx-web-4.0/src/main/java/datadog/trace/instrumentation/vertx_4_0/server/RouteHandlerWrapperAdvice.java

+1-8
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,12 @@
22

33
import io.vertx.core.Handler;
44
import io.vertx.ext.web.RoutingContext;
5-
import io.vertx.ext.web.impl.RouteImpl;
65
import net.bytebuddy.asm.Advice;
76

87
public class RouteHandlerWrapperAdvice {
98
@Advice.OnMethodEnter(suppress = Throwable.class)
109
public static void wrapHandler(
1110
@Advice.Argument(value = 0, readOnly = false) Handler<RoutingContext> handler) {
12-
// When mounting a sub router, the handler is a method reference to the routers handleContext
13-
// method this skips that. This prevents routers from creating a span during handling. In the
14-
// event a route is not found, without this code, a span would be created for the router when
15-
// it shouldn't
16-
if (!handler.getClass().getName().startsWith(RouteImpl.class.getName())) {
17-
handler = new RouteHandlerWrapper(handler);
18-
}
11+
handler = new RouteHandlerWrapper(handler);
1912
}
2013
}

0 commit comments

Comments
 (0)