Skip to content

Commit 7d86ad0

Browse files
committed
Example of how to group related instrumentations under a single module (AwsSdkModule)
1 parent e8df8a0 commit 7d86ad0

File tree

4 files changed

+108
-98
lines changed

4 files changed

+108
-98
lines changed

dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/AWSHttpClientInstrumentation.java

Lines changed: 1 addition & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
import com.amazonaws.AmazonClientException;
1010
import com.amazonaws.Request;
1111
import com.amazonaws.handlers.RequestHandler2;
12-
import com.google.auto.service.AutoService;
1312
import datadog.trace.agent.tooling.Instrumenter;
14-
import datadog.trace.agent.tooling.InstrumenterModule;
1513
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
1614
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
1715
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
@@ -22,26 +20,14 @@
2220
* {@link AmazonClientException} (for example an error thrown by another handler). In these cases
2321
* {@link RequestHandler2#afterError} is not called.
2422
*/
25-
@AutoService(InstrumenterModule.class)
26-
public class AWSHttpClientInstrumentation extends InstrumenterModule.Tracing
23+
public class AWSHttpClientInstrumentation
2724
implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice {
2825

29-
public AWSHttpClientInstrumentation() {
30-
super("aws-sdk");
31-
}
32-
3326
@Override
3427
public String instrumentedType() {
3528
return "com.amazonaws.http.AmazonHttpClient";
3629
}
3730

38-
@Override
39-
public String[] helperClassNames() {
40-
return new String[] {
41-
packageName + ".OnErrorDecorator", packageName + ".AwsNameCache",
42-
};
43-
}
44-
4531
@Override
4632
public void methodAdvice(MethodTransformer transformer) {
4733
transformer.applyAdvice(
@@ -74,57 +60,4 @@ public static void methodExit(
7460
}
7561
}
7662
}
77-
78-
/**
79-
* Due to a change in the AmazonHttpClient class, this instrumentation is needed to support newer
80-
* versions. The above class should cover older versions.
81-
*/
82-
@AutoService(InstrumenterModule.class)
83-
public static final class RequestExecutorInstrumentation extends AWSHttpClientInstrumentation {
84-
85-
@Override
86-
public String instrumentedType() {
87-
return "com.amazonaws.http.AmazonHttpClient$RequestExecutor";
88-
}
89-
90-
@Override
91-
public String[] helperClassNames() {
92-
return new String[] {
93-
packageName + ".OnErrorDecorator", packageName + ".AwsNameCache",
94-
};
95-
}
96-
97-
@Override
98-
public void methodAdvice(MethodTransformer transformer) {
99-
transformer.applyAdvice(
100-
isMethod().and(named("doExecute")),
101-
RequestExecutorInstrumentation.class.getName() + "$RequestExecutorAdvice");
102-
}
103-
104-
public static class RequestExecutorAdvice {
105-
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
106-
public static void methodExit(
107-
@Advice.FieldValue("request") final Request<?> request,
108-
@Advice.Thrown final Throwable throwable) {
109-
110-
final AgentScope scope = activeScope();
111-
// check name in case TracingRequestHandler failed to activate the span
112-
if (scope != null
113-
&& (AwsNameCache.spanName(request).equals(scope.span().getSpanName())
114-
|| scope.span() instanceof AgentTracer.NoopAgentSpan)) {
115-
scope.close();
116-
}
117-
118-
if (throwable != null) {
119-
final AgentSpan span = request.getHandlerContext(SPAN_CONTEXT_KEY);
120-
if (span != null) {
121-
request.addHandlerContext(SPAN_CONTEXT_KEY, null);
122-
DECORATE.onError(span, throwable);
123-
DECORATE.beforeFinish(span);
124-
span.finish();
125-
}
126-
}
127-
}
128-
}
129-
}
13063
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package datadog.trace.instrumentation.aws.v0;
2+
3+
import com.google.auto.service.AutoService;
4+
import datadog.trace.agent.tooling.Instrumenter;
5+
import datadog.trace.agent.tooling.InstrumenterModule;
6+
import java.util.Arrays;
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
@AutoService(InstrumenterModule.class)
11+
public final class AwsSdkModule extends InstrumenterModule.Tracing {
12+
13+
public AwsSdkModule() {
14+
super("aws-sdk");
15+
}
16+
17+
@Override
18+
public String[] helperClassNames() {
19+
return new String[] {
20+
packageName + ".AwsSdkClientDecorator",
21+
packageName + ".GetterAccess",
22+
packageName + ".GetterAccess$1",
23+
packageName + ".TracingRequestHandler",
24+
packageName + ".AwsNameCache",
25+
packageName + ".OnErrorDecorator",
26+
};
27+
}
28+
29+
@Override
30+
public Map<String, String> contextStore() {
31+
Map<String, String> map = new java.util.HashMap<>();
32+
map.put("com.amazonaws.services.sqs.model.ReceiveMessageResult", "java.lang.String");
33+
map.put(
34+
"com.amazonaws.AmazonWebServiceRequest",
35+
"datadog.trace.bootstrap.instrumentation.api.AgentSpan");
36+
return map;
37+
}
38+
39+
@Override
40+
public List<Instrumenter> typeInstrumentations() {
41+
return Arrays.asList(
42+
new AWSHttpClientInstrumentation(),
43+
new RequestExecutorInstrumentation(),
44+
new HandlerChainFactoryInstrumentation());
45+
}
46+
}

dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/main/java/datadog/trace/instrumentation/aws/v0/HandlerChainFactoryInstrumentation.java

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,23 @@
44
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
55

66
import com.amazonaws.handlers.RequestHandler2;
7-
import com.google.auto.service.AutoService;
87
import datadog.trace.agent.tooling.Instrumenter;
9-
import datadog.trace.agent.tooling.InstrumenterModule;
108
import datadog.trace.bootstrap.InstrumentationContext;
119
import java.util.List;
12-
import java.util.Map;
1310
import net.bytebuddy.asm.Advice;
1411

1512
/**
1613
* This instrumentation might work with versions before 1.11.0, but this was the first version that
1714
* is tested. It could possibly be extended earlier.
1815
*/
19-
@AutoService(InstrumenterModule.class)
20-
public final class HandlerChainFactoryInstrumentation extends InstrumenterModule.Tracing
16+
public final class HandlerChainFactoryInstrumentation
2117
implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice {
2218

23-
public HandlerChainFactoryInstrumentation() {
24-
super("aws-sdk");
25-
}
26-
2719
@Override
2820
public String instrumentedType() {
2921
return "com.amazonaws.handlers.HandlerChainFactory";
3022
}
3123

32-
@Override
33-
public String[] helperClassNames() {
34-
return new String[] {
35-
packageName + ".AwsSdkClientDecorator",
36-
packageName + ".GetterAccess",
37-
packageName + ".GetterAccess$1",
38-
packageName + ".TracingRequestHandler",
39-
packageName + ".AwsNameCache",
40-
};
41-
}
42-
43-
@Override
44-
public Map<String, String> contextStore() {
45-
Map<String, String> map = new java.util.HashMap<>();
46-
map.put("com.amazonaws.services.sqs.model.ReceiveMessageResult", "java.lang.String");
47-
map.put(
48-
"com.amazonaws.AmazonWebServiceRequest",
49-
"datadog.trace.bootstrap.instrumentation.api.AgentSpan");
50-
return map;
51-
}
52-
5324
@Override
5425
public void methodAdvice(MethodTransformer transformer) {
5526
transformer.applyAdvice(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package datadog.trace.instrumentation.aws.v0;
2+
3+
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
4+
import static datadog.trace.bootstrap.instrumentation.api.AgentTracer.activeScope;
5+
import static datadog.trace.instrumentation.aws.v0.OnErrorDecorator.DECORATE;
6+
import static datadog.trace.instrumentation.aws.v0.OnErrorDecorator.SPAN_CONTEXT_KEY;
7+
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
8+
9+
import com.amazonaws.Request;
10+
import datadog.trace.agent.tooling.Instrumenter;
11+
import datadog.trace.bootstrap.instrumentation.api.AgentScope;
12+
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
13+
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
14+
import net.bytebuddy.asm.Advice;
15+
16+
/**
17+
* Due to a change in the AmazonHttpClient class, this instrumentation is needed to support newer
18+
* versions. The {@link AWSHttpClientInstrumentation} class should cover older versions.
19+
*/
20+
public final class RequestExecutorInstrumentation
21+
implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice {
22+
23+
@Override
24+
public String instrumentedType() {
25+
return "com.amazonaws.http.AmazonHttpClient$RequestExecutor";
26+
}
27+
28+
@Override
29+
public void methodAdvice(MethodTransformer transformer) {
30+
transformer.applyAdvice(
31+
isMethod().and(named("doExecute")),
32+
RequestExecutorInstrumentation.class.getName() + "$RequestExecutorAdvice");
33+
}
34+
35+
public static class RequestExecutorAdvice {
36+
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
37+
public static void methodExit(
38+
@Advice.FieldValue("request") final Request<?> request,
39+
@Advice.Thrown final Throwable throwable) {
40+
41+
final AgentScope scope = activeScope();
42+
// check name in case TracingRequestHandler failed to activate the span
43+
if (scope != null
44+
&& (AwsNameCache.spanName(request).equals(scope.span().getSpanName())
45+
|| scope.span() instanceof AgentTracer.NoopAgentSpan)) {
46+
scope.close();
47+
}
48+
49+
if (throwable != null) {
50+
final AgentSpan span = request.getHandlerContext(SPAN_CONTEXT_KEY);
51+
if (span != null) {
52+
request.addHandlerContext(SPAN_CONTEXT_KEY, null);
53+
DECORATE.onError(span, throwable);
54+
DECORATE.beforeFinish(span);
55+
span.finish();
56+
}
57+
}
58+
}
59+
}
60+
}

0 commit comments

Comments
 (0)