Skip to content

Commit 4a9b965

Browse files
authored
Add process spans to aws2 sqs instrumentation (#9778)
1 parent 976ca64 commit 4a9b965

31 files changed

+1593
-233
lines changed

instrumentation/aws-sdk/aws-sdk-2.2/javaagent/build.gradle.kts

+19-2
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,30 @@ testing {
108108

109109
tasks {
110110
val testExperimentalSqs by registering(Test::class) {
111-
group = "verification"
112-
111+
filter {
112+
excludeTestsMatching("Aws2SqsSuppressReceiveSpansTest")
113+
}
113114
systemProperty("otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", "true")
115+
systemProperty("otel.instrumentation.messaging.experimental.receive-telemetry.enabled", "true")
116+
}
117+
118+
val testReceiveSpansDisabled by registering(Test::class) {
119+
filter {
120+
includeTestsMatching("Aws2SqsSuppressReceiveSpansTest")
121+
}
122+
include("**/Aws2SqsSuppressReceiveSpansTest.*")
123+
}
124+
125+
test {
126+
filter {
127+
excludeTestsMatching("Aws2SqsSuppressReceiveSpansTest")
128+
}
129+
systemProperty("otel.instrumentation.messaging.experimental.receive-telemetry.enabled", "true")
114130
}
115131

116132
check {
117133
dependsOn(testExperimentalSqs)
134+
dependsOn(testReceiveSpansDisabled)
118135
dependsOn(testing.suites)
119136
}
120137

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2;
7+
8+
import static net.bytebuddy.matcher.ElementMatchers.named;
9+
10+
import io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure.AwsSdkSingletons;
11+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
12+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
13+
import net.bytebuddy.asm.Advice;
14+
import net.bytebuddy.description.type.TypeDescription;
15+
import net.bytebuddy.matcher.ElementMatcher;
16+
import software.amazon.awssdk.services.sqs.SqsAsyncClient;
17+
18+
public class DefaultSqsAsyncClientBuilderInstrumentation implements TypeInstrumentation {
19+
20+
@Override
21+
public ElementMatcher<TypeDescription> typeMatcher() {
22+
return named("software.amazon.awssdk.services.sqs.DefaultSqsAsyncClientBuilder");
23+
}
24+
25+
@Override
26+
public void transform(TypeTransformer transformer) {
27+
transformer.applyAdviceToMethod(
28+
named("buildClient"), this.getClass().getName() + "$BuildClientAdvice");
29+
}
30+
31+
@SuppressWarnings("unused")
32+
public static class BuildClientAdvice {
33+
34+
@Advice.OnMethodExit(suppress = Throwable.class)
35+
public static void methodExit(@Advice.Return(readOnly = false) SqsAsyncClient sqsClient) {
36+
sqsClient = AwsSdkSingletons.telemetry().wrap(sqsClient);
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.awssdk.v2_2;
7+
8+
import static net.bytebuddy.matcher.ElementMatchers.named;
9+
10+
import io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure.AwsSdkSingletons;
11+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
12+
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
13+
import net.bytebuddy.asm.Advice;
14+
import net.bytebuddy.description.type.TypeDescription;
15+
import net.bytebuddy.matcher.ElementMatcher;
16+
import software.amazon.awssdk.services.sqs.SqsClient;
17+
18+
public class DefaultSqsClientBuilderInstrumentation implements TypeInstrumentation {
19+
20+
@Override
21+
public ElementMatcher<TypeDescription> typeMatcher() {
22+
return named("software.amazon.awssdk.services.sqs.DefaultSqsClientBuilder");
23+
}
24+
25+
@Override
26+
public void transform(TypeTransformer transformer) {
27+
transformer.applyAdviceToMethod(
28+
named("buildClient"), this.getClass().getName() + "$BuildClientAdvice");
29+
}
30+
31+
@SuppressWarnings("unused")
32+
public static class BuildClientAdvice {
33+
34+
@Advice.OnMethodExit(suppress = Throwable.class)
35+
public static void methodExit(@Advice.Return(readOnly = false) SqsClient sqsClient) {
36+
sqsClient = AwsSdkSingletons.telemetry().wrap(sqsClient);
37+
}
38+
}
39+
}

instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/awssdk/v2_2/SqsInstrumentationModule.java

+11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@
1111
import com.google.auto.service.AutoService;
1212
import io.opentelemetry.instrumentation.awssdk.v2_2.SqsAdviceBridge;
1313
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
14+
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1415
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
16+
import java.util.ArrayList;
17+
import java.util.List;
1518
import net.bytebuddy.asm.Advice;
1619
import net.bytebuddy.matcher.ElementMatcher;
1720

@@ -27,6 +30,14 @@ public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
2730
return hasClassesNamed("software.amazon.awssdk.services.sqs.SqsClient");
2831
}
2932

33+
@Override
34+
public List<TypeInstrumentation> typeInstrumentations() {
35+
List<TypeInstrumentation> instrumentations = new ArrayList<>(super.typeInstrumentations());
36+
instrumentations.add(new DefaultSqsClientBuilderInstrumentation());
37+
instrumentations.add(new DefaultSqsAsyncClientBuilderInstrumentation());
38+
return instrumentations;
39+
}
40+
3041
@Override
3142
public void doTransform(TypeTransformer transformer) {
3243
transformer.applyAdviceToMethod(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import io.opentelemetry.instrumentation.awssdk.v2_2.AbstractAws2SqsSuppressReceiveSpansTest
7+
import io.opentelemetry.instrumentation.test.AgentTestTrait
8+
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration
9+
import software.amazon.awssdk.services.sqs.SqsAsyncClient
10+
import software.amazon.awssdk.services.sqs.SqsClient
11+
12+
class Aws2SqsSuppressReceiveSpansTest extends AbstractAws2SqsSuppressReceiveSpansTest implements AgentTestTrait {
13+
@Override
14+
ClientOverrideConfiguration.Builder createOverrideConfigurationBuilder() {
15+
return ClientOverrideConfiguration.builder()
16+
}
17+
18+
@Override
19+
SqsClient configureSqsClient(SqsClient sqsClient) {
20+
return sqsClient
21+
}
22+
23+
@Override
24+
SqsAsyncClient configureSqsClient(SqsAsyncClient sqsClient) {
25+
return sqsClient
26+
}
27+
}

instrumentation/aws-sdk/aws-sdk-2.2/javaagent/src/test/groovy/Aws2SqsTracingTest.groovy

+12
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,22 @@
66
import io.opentelemetry.instrumentation.awssdk.v2_2.AbstractAws2SqsTracingTest
77
import io.opentelemetry.instrumentation.test.AgentTestTrait
88
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration
9+
import software.amazon.awssdk.services.sqs.SqsAsyncClient
10+
import software.amazon.awssdk.services.sqs.SqsClient
911

1012
class Aws2SqsTracingTest extends AbstractAws2SqsTracingTest implements AgentTestTrait {
1113
@Override
1214
ClientOverrideConfiguration.Builder createOverrideConfigurationBuilder() {
1315
return ClientOverrideConfiguration.builder()
1416
}
17+
18+
@Override
19+
SqsClient configureSqsClient(SqsClient sqsClient) {
20+
return sqsClient
21+
}
22+
23+
@Override
24+
SqsAsyncClient configureSqsClient(SqsAsyncClient sqsClient) {
25+
return sqsClient
26+
}
1527
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure;
7+
8+
import io.opentelemetry.api.GlobalOpenTelemetry;
9+
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
10+
import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry;
11+
12+
public final class AwsSdkSingletons {
13+
14+
private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES =
15+
ConfigPropertiesUtil.getBoolean(
16+
"otel.instrumentation.aws-sdk.experimental-span-attributes", false);
17+
18+
private static final boolean USE_MESSAGING_PROPAGATOR =
19+
ConfigPropertiesUtil.getBoolean(
20+
"otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", false);
21+
22+
private static final boolean RECORD_INDIVIDUAL_HTTP_ERROR =
23+
ConfigPropertiesUtil.getBoolean(
24+
"otel.instrumentation.aws-sdk.experimental-record-individual-http-error", false);
25+
26+
private static final boolean RECEIVE_TELEMETRY_ENABLED =
27+
ConfigPropertiesUtil.getBoolean(
28+
"otel.instrumentation.messaging.experimental.receive-telemetry.enabled", false);
29+
30+
private static final AwsSdkTelemetry TELEMETRY =
31+
AwsSdkTelemetry.builder(GlobalOpenTelemetry.get())
32+
.setCaptureExperimentalSpanAttributes(CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES)
33+
.setMessagingReceiveInstrumentationEnabled(RECEIVE_TELEMETRY_ENABLED)
34+
.setUseConfiguredPropagatorForMessaging(USE_MESSAGING_PROPAGATOR)
35+
.setRecordIndividualHttpError(RECORD_INDIVIDUAL_HTTP_ERROR)
36+
.build();
37+
38+
public static AwsSdkTelemetry telemetry() {
39+
return TELEMETRY;
40+
}
41+
42+
private AwsSdkSingletons() {}
43+
}

instrumentation/aws-sdk/aws-sdk-2.2/library-autoconfigure/src/main/java/io/opentelemetry/instrumentation/awssdk/v2_2/autoconfigure/TracingExecutionInterceptor.java

+1-21
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55

66
package io.opentelemetry.instrumentation.awssdk.v2_2.autoconfigure;
77

8-
import io.opentelemetry.api.GlobalOpenTelemetry;
9-
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
10-
import io.opentelemetry.instrumentation.awssdk.v2_2.AwsSdkTelemetry;
118
import java.io.InputStream;
129
import java.nio.ByteBuffer;
1310
import java.util.Optional;
@@ -28,25 +25,8 @@
2825
*/
2926
public class TracingExecutionInterceptor implements ExecutionInterceptor {
3027

31-
private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES =
32-
ConfigPropertiesUtil.getBoolean(
33-
"otel.instrumentation.aws-sdk.experimental-span-attributes", false);
34-
35-
private static final boolean USE_MESSAGING_PROPAGATOR =
36-
ConfigPropertiesUtil.getBoolean(
37-
"otel.instrumentation.aws-sdk.experimental-use-propagator-for-messaging", false);
38-
39-
private static final boolean RECORD_INDIVIDUAL_HTTP_ERROR =
40-
ConfigPropertiesUtil.getBoolean(
41-
"otel.instrumentation.aws-sdk.experimental-record-individual-http-error", false);
42-
4328
private final ExecutionInterceptor delegate =
44-
AwsSdkTelemetry.builder(GlobalOpenTelemetry.get())
45-
.setCaptureExperimentalSpanAttributes(CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES)
46-
.setUseConfiguredPropagatorForMessaging(USE_MESSAGING_PROPAGATOR)
47-
.setRecordIndividualHttpError(RECORD_INDIVIDUAL_HTTP_ERROR)
48-
.build()
49-
.newExecutionInterceptor();
29+
AwsSdkSingletons.telemetry().newExecutionInterceptor();
5030

5131
@Override
5232
public void beforeExecution(

instrumentation/aws-sdk/aws-sdk-2.2/library/README.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,26 @@ To instrument all AWS SDK clients include the `opentelemetry-aws-sdk-2.2-autocon
99
To register instrumentation only on a specific SDK client, register the interceptor when creating it.
1010

1111
```java
12+
AwsSdkTelemetry telemetrty = AwsSdkTelemetry.create(openTelemetry).build();
1213
DynamoDbClient client = DynamoDbClient.builder()
1314
.overrideConfiguration(ClientOverrideConfiguration.builder()
14-
.addExecutionInterceptor(AwsSdk.newInterceptor()))
15+
.addExecutionInterceptor(telemetrty.newExecutionInterceptor()))
1516
.build())
1617
.build();
1718
```
1819

20+
For SQS an additional step is needed
21+
```java
22+
SqsClientBuilder sqsClientBuilder = SqsClient.builder();
23+
...
24+
SqsClient sqsClient = telemetry.wrap(sqsClientBuilder.build());
25+
```
26+
```java
27+
SqsAsyncClientBuilder sqsAsyncClientBuilder = SqsAsyncClient.builder();
28+
...
29+
SqsAsyncClient sqsAsyncClient = telemetry.wrap(sqsAsyncClientBuilder.build());
30+
```
31+
1932
## Trace propagation
2033

2134
The AWS SDK instrumentation always injects the trace header into the request

instrumentation/aws-sdk/aws-sdk-2.2/library/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ testing {
3636
dependencies {
3737
implementation(project())
3838
implementation(project(":instrumentation:aws-sdk:aws-sdk-2.2:testing"))
39+
compileOnly("software.amazon.awssdk:sqs:2.2.0")
3940
if (findProperty("testLatestDeps") as Boolean) {
4041
implementation("software.amazon.awssdk:aws-core:+")
4142
implementation("software.amazon.awssdk:aws-json-protocol:+")

0 commit comments

Comments
 (0)