Skip to content

Commit d5e870e

Browse files
amarzialidevflow.devflow-routing-intake
andauthored
Separate context tracking from tracing on http client instrumentations (#10782)
phase 1 migrate jetty and akka http clients wip more clients migrate httpclient5 spotless fix bad ai stuff Fix compile spotless Use blackhole for grpc ignored methods final fixes fix jetty client add nullcheck Co-authored-by: devflow.devflow-routing-intake <devflow.devflow-routing-intake@kubernetes.us1.ddbuild.io>
1 parent 13ced73 commit d5e870e

File tree

34 files changed

+495
-154
lines changed

34 files changed

+495
-154
lines changed

dd-java-agent/instrumentation/akka/akka-http/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpSingleRequestInstrumentation.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.instrumentation.akkahttp;
22

3+
import static datadog.trace.agent.tooling.InstrumenterModule.TargetSystem.CONTEXT_TRACKING;
34
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
45
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan;
56
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
@@ -16,6 +17,7 @@
1617
import com.google.auto.service.AutoService;
1718
import datadog.trace.agent.tooling.Instrumenter;
1819
import datadog.trace.agent.tooling.InstrumenterModule;
20+
import datadog.trace.agent.tooling.annotation.AppliesOn;
1921
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
2022
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
2123
import net.bytebuddy.asm.Advice;
@@ -47,20 +49,23 @@ public String[] helperClassNames() {
4749
@Override
4850
public void methodAdvice(MethodTransformer transformer) {
4951
// This is mainly for compatibility with 10.0
50-
transformer.applyAdvice(
52+
transformer.applyAdvices(
5153
named("singleRequest").and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))),
52-
AkkaHttpSingleRequestInstrumentation.class.getName() + "$SingleRequestAdvice");
54+
AkkaHttpSingleRequestInstrumentation.class.getName() + "$SingleRequestAdvice",
55+
AkkaHttpSingleRequestInstrumentation.class.getName()
56+
+ "$SingleRequestContextPropagationAdvice");
5357
// This is for 10.1+
54-
transformer.applyAdvice(
58+
transformer.applyAdvices(
5559
named("singleRequestImpl")
5660
.and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))),
57-
AkkaHttpSingleRequestInstrumentation.class.getName() + "$SingleRequestAdvice");
61+
AkkaHttpSingleRequestInstrumentation.class.getName() + "$SingleRequestAdvice",
62+
AkkaHttpSingleRequestInstrumentation.class.getName()
63+
+ "$SingleRequestContextPropagationAdvice");
5864
}
5965

6066
public static class SingleRequestAdvice {
6167
@Advice.OnMethodEnter(suppress = Throwable.class)
62-
public static AgentScope methodEnter(
63-
@Advice.Argument(value = 0, readOnly = false) HttpRequest request) {
68+
public static AgentScope methodEnter(@Advice.Argument(value = 0) final HttpRequest request) {
6469
/*
6570
Versions 10.0 and 10.1 have slightly different structure that is hard to distinguish so here
6671
we cast 'wider net' and avoid instrumenting twice.
@@ -75,12 +80,6 @@ public static AgentScope methodEnter(
7580
final AgentSpan span = startSpan("akka-http", AKKA_CLIENT_REQUEST);
7681
DECORATE.afterStart(span);
7782
DECORATE.onRequest(span, request);
78-
79-
if (request != null) {
80-
DECORATE.injectContext(getCurrentContext().with(span), request, headers);
81-
// Request is immutable, so we have to assign new value once we update headers
82-
request = headers.getRequest();
83-
}
8483
return activateSpan(span);
8584
}
8685

@@ -106,4 +105,18 @@ public static void methodExit(
106105
scope.close();
107106
}
108107
}
108+
109+
@AppliesOn(CONTEXT_TRACKING)
110+
public static class SingleRequestContextPropagationAdvice {
111+
@Advice.OnMethodEnter(suppress = Throwable.class)
112+
public static void methodEnter(
113+
@Advice.Argument(value = 0, readOnly = false) HttpRequest request) {
114+
if (request == null) {
115+
return;
116+
}
117+
final AkkaHttpHeaders headers = new AkkaHttpHeaders(request);
118+
DECORATE.injectContext(getCurrentContext(), request, headers);
119+
request = headers.getRequest();
120+
}
121+
}
109122
}

dd-java-agent/instrumentation/akka/akka-http/akka-http-10.6/src/main/java/datadog/trace/instrumentation/akkahttp106/AkkaHttpSingleRequestInstrumentation.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ public String[] helperClassNames() {
3232

3333
@Override
3434
public void methodAdvice(MethodTransformer transformer) {
35-
transformer.applyAdvice(
35+
transformer.applyAdvices(
3636
named("singleRequest").and(takesArgument(0, named("akka.http.scaladsl.model.HttpRequest"))),
37-
packageName + ".SingleRequestAdvice");
37+
packageName + ".SingleRequestAdvice",
38+
packageName + ".SingleRequestContextPropagationAdvice");
3839
}
3940
}

dd-java-agent/instrumentation/akka/akka-http/akka-http-10.6/src/main/java11/datadog/trace/instrumentation/akkahttp106/SingleRequestAdvice.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activateSpan;
44
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.startSpan;
5-
import static datadog.trace.bootstrap.instrumentation.api.Java8BytecodeBridge.getCurrentContext;
65
import static datadog.trace.instrumentation.akkahttp106.AkkaHttpClientDecorator.AKKA_CLIENT_REQUEST;
76
import static datadog.trace.instrumentation.akkahttp106.AkkaHttpClientDecorator.DECORATE;
87

@@ -16,8 +15,7 @@
1615

1716
public class SingleRequestAdvice {
1817
@Advice.OnMethodEnter(suppress = Throwable.class)
19-
public static AgentScope methodEnter(
20-
@Advice.Argument(value = 0, readOnly = false) HttpRequest request) {
18+
public static AgentScope methodEnter(@Advice.Argument(value = 0) final HttpRequest request) {
2119
final AkkaHttpClientHelpers.AkkaHttpHeaders headers =
2220
new AkkaHttpClientHelpers.AkkaHttpHeaders(request);
2321
if (headers.hadSpan()) {
@@ -27,11 +25,6 @@ public static AgentScope methodEnter(
2725
final AgentSpan span = startSpan("akka-http", AKKA_CLIENT_REQUEST);
2826
DECORATE.afterStart(span);
2927
DECORATE.onRequest(span, request);
30-
if (request != null) {
31-
DECORATE.injectContext(getCurrentContext().with(span), request, headers);
32-
// Request is immutable, so we have to assign new value once we update headers
33-
request = headers.getRequest();
34-
}
3528
return activateSpan(span);
3629
}
3730

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package datadog.trace.instrumentation.akkahttp106;
2+
3+
import static datadog.trace.agent.tooling.InstrumenterModule.TargetSystem.CONTEXT_TRACKING;
4+
import static datadog.trace.bootstrap.instrumentation.api.Java8BytecodeBridge.getCurrentContext;
5+
import static datadog.trace.instrumentation.akkahttp106.AkkaHttpClientDecorator.DECORATE;
6+
7+
import akka.http.scaladsl.model.HttpRequest;
8+
import datadog.trace.agent.tooling.annotation.AppliesOn;
9+
import net.bytebuddy.asm.Advice;
10+
11+
@AppliesOn(CONTEXT_TRACKING)
12+
public class SingleRequestContextPropagationAdvice {
13+
@Advice.OnMethodEnter(suppress = Throwable.class)
14+
public static void methodEnter(
15+
@Advice.Argument(value = 0, readOnly = false) HttpRequest request) {
16+
if (request == null) {
17+
return;
18+
}
19+
final AkkaHttpClientHelpers.AkkaHttpHeaders headers =
20+
new AkkaHttpClientHelpers.AkkaHttpHeaders(request);
21+
22+
DECORATE.injectContext(getCurrentContext(), request, headers);
23+
request = headers.getRequest();
24+
}
25+
}

dd-java-agent/instrumentation/apache-httpclient/apache-httpasyncclient-4.0/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/ApacheHttpAsyncClientInstrumentation.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.instrumentation.apachehttpasyncclient;
22

3+
import static datadog.trace.agent.tooling.InstrumenterModule.TargetSystem.CONTEXT_TRACKING;
34
import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface;
45
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
56
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.captureActiveSpan;
@@ -12,9 +13,11 @@
1213
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
1314

1415
import datadog.trace.agent.tooling.Instrumenter;
16+
import datadog.trace.agent.tooling.annotation.AppliesOn;
1517
import datadog.trace.api.InstrumenterConfig;
1618
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
1719
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
20+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
1821
import net.bytebuddy.asm.Advice;
1922
import net.bytebuddy.description.type.TypeDescription;
2023
import net.bytebuddy.matcher.ElementMatcher;
@@ -61,30 +64,47 @@ public ElementMatcher<TypeDescription> hierarchyMatcher() {
6164

6265
@Override
6366
public void methodAdvice(MethodTransformer transformer) {
64-
transformer.applyAdvice(
67+
transformer.applyAdvices(
6568
isMethod()
6669
.and(named("execute"))
6770
.and(takesArguments(4))
6871
.and(takesArgument(0, named("org.apache.http.nio.protocol.HttpAsyncRequestProducer")))
6972
.and(takesArgument(1, named("org.apache.http.nio.protocol.HttpAsyncResponseConsumer")))
7073
.and(takesArgument(2, named("org.apache.http.protocol.HttpContext")))
7174
.and(takesArgument(3, named("org.apache.http.concurrent.FutureCallback"))),
75+
ApacheHttpAsyncClientInstrumentation.class.getName() + "$ClientContextPropagationAdvice",
7276
ApacheHttpAsyncClientInstrumentation.class.getName() + "$ClientAdvice");
7377
}
7478

75-
public static class ClientAdvice {
79+
@AppliesOn(CONTEXT_TRACKING)
80+
@SuppressFBWarnings("UC_USELESS_OBJECT")
81+
public static class ClientContextPropagationAdvice {
82+
@Advice.OnMethodEnter(suppress = Throwable.class)
83+
public static void methodEnter(
84+
@Advice.Argument(value = 0, readOnly = false) HttpAsyncRequestProducer requestProducer) {
85+
final DelegatingRequestProducer delegatingRequestProducer =
86+
new DelegatingRequestProducer(requestProducer);
87+
delegatingRequestProducer.setInjectContext(true);
88+
requestProducer = delegatingRequestProducer;
89+
}
90+
}
7691

92+
@SuppressFBWarnings("UC_USELESS_OBJECT")
93+
public static class ClientAdvice {
7794
@Advice.OnMethodEnter(suppress = Throwable.class)
7895
public static AgentSpan methodEnter(
7996
@Advice.Argument(value = 0, readOnly = false) HttpAsyncRequestProducer requestProducer,
8097
@Advice.Argument(2) HttpContext context,
8198
@Advice.Argument(value = 3, readOnly = false) FutureCallback<?> futureCallback) {
8299

100+
if (!(requestProducer instanceof DelegatingRequestProducer)) {
101+
requestProducer = new DelegatingRequestProducer(requestProducer);
102+
}
103+
83104
final AgentScope.Continuation parentContinuation = captureActiveSpan();
84105
final AgentSpan clientSpan = startSpan(HTTP_REQUEST);
85106
DECORATE.afterStart(clientSpan);
86-
87-
requestProducer = new DelegatingRequestProducer(clientSpan, requestProducer);
107+
((DelegatingRequestProducer) requestProducer).setSpan(clientSpan);
88108
futureCallback =
89109
new TraceContinuedFutureCallback<>(
90110
parentContinuation, clientSpan, context, futureCallback);

dd-java-agent/instrumentation/apache-httpclient/apache-httpasyncclient-4.0/src/main/java/datadog/trace/instrumentation/apachehttpasyncclient/DelegatingRequestProducer.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static datadog.trace.instrumentation.apachehttpasyncclient.ApacheHttpAsyncClientDecorator.DECORATE;
55
import static datadog.trace.instrumentation.apachehttpasyncclient.HttpHeadersInjectAdapter.SETTER;
66

7+
import datadog.context.Context;
78
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
89
import java.io.IOException;
910
import org.apache.http.HttpException;
@@ -15,14 +16,22 @@
1516
import org.apache.http.protocol.HttpContext;
1617

1718
public class DelegatingRequestProducer implements HttpAsyncRequestProducer {
18-
final AgentSpan span;
19+
AgentSpan span;
1920
final HttpAsyncRequestProducer delegate;
21+
boolean injectContext = false;
2022

21-
public DelegatingRequestProducer(final AgentSpan span, final HttpAsyncRequestProducer delegate) {
22-
this.span = span;
23+
public DelegatingRequestProducer(final HttpAsyncRequestProducer delegate) {
2324
this.delegate = delegate;
2425
}
2526

27+
public void setInjectContext(boolean injectContext) {
28+
this.injectContext = injectContext;
29+
}
30+
31+
public void setSpan(final AgentSpan span) {
32+
this.span = span;
33+
}
34+
2635
@Override
2736
public HttpHost getTarget() {
2837
return delegate.getTarget();
@@ -31,8 +40,16 @@ public HttpHost getTarget() {
3140
@Override
3241
public HttpRequest generateRequest() throws IOException, HttpException {
3342
final HttpRequest request = delegate.generateRequest();
34-
DECORATE.onRequest(span, new HostAndRequestAsHttpUriRequest(delegate.getTarget(), request));
35-
DECORATE.injectContext(current().with(span), request, SETTER);
43+
if (span != null) {
44+
DECORATE.onRequest(span, new HostAndRequestAsHttpUriRequest(delegate.getTarget(), request));
45+
}
46+
if (injectContext) {
47+
Context receiver = current();
48+
if (span != null) {
49+
receiver = receiver.with(span);
50+
}
51+
DECORATE.injectContext(receiver, request, SETTER);
52+
}
3653
return request;
3754
}
3855

0 commit comments

Comments
 (0)