Skip to content

Commit db7ec8d

Browse files
committed
Capture the SNS target ARN as the messaging.destination.name attribute if provided with preference for the topic ARN.
1 parent 5c9c14c commit db7ec8d

File tree

5 files changed

+77
-41
lines changed

5 files changed

+77
-41
lines changed

instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/RequestAccess.java

+9
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,18 @@ static String getTableName(Object request) {
5050
return invokeOrNull(access.getTableName, request);
5151
}
5252

53+
@Nullable
5354
static String getTopicArn(Object request) {
5455
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
5556
return invokeOrNull(access.getTopicArn, request);
5657
}
5758

59+
@Nullable
60+
static String getTargetArn(Object request) {
61+
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
62+
return invokeOrNull(access.getTargetArn, request);
63+
}
64+
5865
@Nullable
5966
private static String invokeOrNull(@Nullable MethodHandle method, Object obj) {
6067
if (method == null) {
@@ -73,6 +80,7 @@ private static String invokeOrNull(@Nullable MethodHandle method, Object obj) {
7380
@Nullable private final MethodHandle getStreamName;
7481
@Nullable private final MethodHandle getTableName;
7582
@Nullable private final MethodHandle getTopicArn;
83+
@Nullable private final MethodHandle getTargetArn;
7684

7785
private RequestAccess(Class<?> clz) {
7886
getBucketName = findAccessorOrNull(clz, "getBucketName");
@@ -81,6 +89,7 @@ private RequestAccess(Class<?> clz) {
8189
getStreamName = findAccessorOrNull(clz, "getStreamName");
8290
getTableName = findAccessorOrNull(clz, "getTableName");
8391
getTopicArn = findAccessorOrNull(clz, "getTopicArn");
92+
getTargetArn = findAccessorOrNull(clz, "getTargetArn");
8493
}
8594

8695
@Nullable

instrumentation/aws-sdk/aws-sdk-1.11/library/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/SnsAttributesExtractor.java

+14-12
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
11
package io.opentelemetry.instrumentation.awssdk.v1_11;
22

3+
import com.amazonaws.AmazonWebServiceRequest;
34
import com.amazonaws.Request;
45
import com.amazonaws.Response;
5-
import io.opentelemetry.api.common.AttributeKey;
66
import io.opentelemetry.api.common.AttributesBuilder;
77
import io.opentelemetry.context.Context;
88
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
99
import io.opentelemetry.semconv.SemanticAttributes;
10-
import java.util.function.Function;
1110
import javax.annotation.Nullable;
1211

1312
public class SnsAttributesExtractor implements AttributesExtractor<Request<?>, Response<?>> {
1413
@Override
1514
public void onStart(AttributesBuilder attributes, Context parentContext, Request<?> request) {
16-
setRequestAttribute(attributes, SemanticAttributes.MESSAGING_DESTINATION_NAME,
17-
request.getOriginalRequest(), RequestAccess::getTopicArn);
15+
String destination = findMessageDestination(request.getOriginalRequest());
16+
if (destination != null) {
17+
attributes.put(SemanticAttributes.MESSAGING_DESTINATION_NAME, destination);
18+
}
1819
}
1920

20-
private static void setRequestAttribute(
21-
AttributesBuilder attributes,
22-
AttributeKey<String> key,
23-
Object request,
24-
Function<Object, String> getter) {
25-
String value = getter.apply(request);
26-
if (value != null) {
27-
attributes.put(key, value);
21+
/*
22+
* Attempt to discover the destination of the SNS message by first checking for a topic ARN and
23+
* falling back to the target ARN. If neither is found null is returned.
24+
*/
25+
private static String findMessageDestination(AmazonWebServiceRequest request) {
26+
String destination = RequestAccess.getTopicArn(request);
27+
if (destination != null) {
28+
return destination;
2829
}
30+
return RequestAccess.getTargetArn(request);
2931
}
3032

3133
@Override

instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy

+10
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ abstract class AbstractAws1ClientTest extends InstrumentationSpecification {
166166
</ResponseMetadata>
167167
</PublishResponse>
168168
"""
169+
"SNS" | "Publish" | "POST" | "d74b8436-ae13-5ab4-a9ff-ce54dfea72a0" | AmazonSNSClientBuilder.standard() | { c -> c.publish(new PublishRequest().withMessage("somemessage").withTargetArn("somearn")) } | ["$SemanticAttributes.MESSAGING_DESTINATION_NAME": "somearn"] | """
170+
<PublishResponse xmlns="https://sns.amazonaws.com/doc/2010-03-31/">
171+
<PublishResult>
172+
<MessageId>567910cd-659e-55d4-8ccb-5aaf14679dc0</MessageId>
173+
</PublishResult>
174+
<ResponseMetadata>
175+
<RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>
176+
</ResponseMetadata>
177+
</PublishResponse>
178+
"""
169179
}
170180

171181
def "send #operation request to closed port"() {

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

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

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

8+
import io.opentelemetry.semconv.SemanticAttributes;
9+
810
import static io.opentelemetry.instrumentation.awssdk.v2_2.FieldMapping.request;
911

1012
import java.util.Collections;
@@ -16,7 +18,10 @@ enum AwsSdkRequestType {
1618
SQS(request("aws.queue.url", "QueueUrl"), request("aws.queue.name", "QueueName")),
1719
KINESIS(request("aws.stream.name", "StreamName")),
1820
DYNAMODB(request("aws.table.name", "TableName")),
19-
SNS(request("messaging.destination.name", "TopicArn"));
21+
SNS(
22+
request(SemanticAttributes.MESSAGING_DESTINATION_NAME.getKey(), "TargetArn"),
23+
request(SemanticAttributes.MESSAGING_DESTINATION_NAME.getKey(), "TopicArn")
24+
);
2025

2126
// Wrapping in unmodifiableMap
2227
@SuppressWarnings("ImmutableEnumChecker")

instrumentation/aws-sdk/aws-sdk-2.2/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v2_2/AbstractAws2ClientTest.groovy

+38-28
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,10 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
8686
setup:
8787
configureSdkClient(builder)
8888
def client = builder
89-
.endpointOverride(clientUri)
90-
.region(Region.AP_NORTHEAST_1)
91-
.credentialsProvider(CREDENTIALS_PROVIDER)
92-
.build()
89+
.endpointOverride(clientUri)
90+
.region(Region.AP_NORTHEAST_1)
91+
.credentialsProvider(CREDENTIALS_PROVIDER)
92+
.build()
9393

9494
if (body instanceof Closure) {
9595
server.enqueue(body.call())
@@ -170,6 +170,16 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
170170
</ResponseMetadata>
171171
</PublishResponse>
172172
"""
173+
"Sns" | "Publish" | "POST" | "d74b8436-ae13-5ab4-a9ff-ce54dfea72a0" | SnsClient.builder() | { c -> c.publish(PublishRequest.builder().message("somemessage").targetArn("somearn").build()) } | """
174+
<PublishResponse xmlns="https://sns.amazonaws.com/doc/2010-03-31/">
175+
<PublishResult>
176+
<MessageId>567910cd-659e-55d4-8ccb-5aaf14679dc0</MessageId>
177+
</PublishResult>
178+
<ResponseMetadata>
179+
<RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>
180+
</ResponseMetadata>
181+
</PublishResponse>
182+
"""
173183
"Sqs" | "CreateQueue" | "POST" | "7a62c49f-347e-4fc4-9331-6e8e7a96aa73" | SqsClient.builder() | { c -> c.createQueue(CreateQueueRequest.builder().queueName("somequeue").build()) } | {
174184
if (!Boolean.getBoolean("testLatestDeps")) {
175185
def content = """
@@ -186,9 +196,9 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
186196
}
187197
"""
188198
ResponseHeaders headers = ResponseHeaders.builder(HttpStatus.OK)
189-
.contentType(MediaType.PLAIN_TEXT_UTF_8)
190-
.add("x-amzn-RequestId", "7a62c49f-347e-4fc4-9331-6e8e7a96aa73")
191-
.build()
199+
.contentType(MediaType.PLAIN_TEXT_UTF_8)
200+
.add("x-amzn-RequestId", "7a62c49f-347e-4fc4-9331-6e8e7a96aa73")
201+
.build()
192202
return HttpResponse.of(headers, HttpData.of(StandardCharsets.UTF_8, content))
193203
}
194204
"Sqs" | "SendMessage" | "POST" | "27daac76-34dd-47df-bd01-1f6e873584a0" | SqsClient.builder() | { c -> c.sendMessage(SendMessageRequest.builder().queueUrl(QUEUE_URL).messageBody("").build()) } | {
@@ -213,9 +223,9 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
213223
}
214224
"""
215225
ResponseHeaders headers = ResponseHeaders.builder(HttpStatus.OK)
216-
.contentType(MediaType.PLAIN_TEXT_UTF_8)
217-
.add("x-amzn-RequestId", "27daac76-34dd-47df-bd01-1f6e873584a0")
218-
.build()
226+
.contentType(MediaType.PLAIN_TEXT_UTF_8)
227+
.add("x-amzn-RequestId", "27daac76-34dd-47df-bd01-1f6e873584a0")
228+
.build()
219229
return HttpResponse.of(headers, HttpData.of(StandardCharsets.UTF_8, content))
220230
}
221231
"Ec2" | "AllocateAddress" | "POST" | "59dbff89-35bd-4eac-99ed-be587EXAMPLE" | Ec2Client.builder() | { c -> c.allocateAddress() } | """
@@ -237,10 +247,10 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
237247
setup:
238248
configureSdkClient(builder)
239249
def client = builder
240-
.endpointOverride(clientUri)
241-
.region(Region.AP_NORTHEAST_1)
242-
.credentialsProvider(CREDENTIALS_PROVIDER)
243-
.build()
250+
.endpointOverride(clientUri)
251+
.region(Region.AP_NORTHEAST_1)
252+
.credentialsProvider(CREDENTIALS_PROVIDER)
253+
.build()
244254

245255
if (body instanceof Closure) {
246256
server.enqueue(body.call())
@@ -338,9 +348,9 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
338348
}
339349
"""
340350
ResponseHeaders headers = ResponseHeaders.builder(HttpStatus.OK)
341-
.contentType(MediaType.PLAIN_TEXT_UTF_8)
342-
.add("x-amzn-RequestId", "7a62c49f-347e-4fc4-9331-6e8e7a96aa73")
343-
.build()
351+
.contentType(MediaType.PLAIN_TEXT_UTF_8)
352+
.add("x-amzn-RequestId", "7a62c49f-347e-4fc4-9331-6e8e7a96aa73")
353+
.build()
344354
return HttpResponse.of(headers, HttpData.of(StandardCharsets.UTF_8, content))
345355
}
346356
"Sqs" | "SendMessage" | "POST" | "27daac76-34dd-47df-bd01-1f6e873584a0" | SqsAsyncClient.builder() | { c -> c.sendMessage(SendMessageRequest.builder().queueUrl(QUEUE_URL).messageBody("").build()) } | {
@@ -365,9 +375,9 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
365375
}
366376
"""
367377
ResponseHeaders headers = ResponseHeaders.builder(HttpStatus.OK)
368-
.contentType(MediaType.PLAIN_TEXT_UTF_8)
369-
.add("x-amzn-RequestId", "27daac76-34dd-47df-bd01-1f6e873584a0")
370-
.build()
378+
.contentType(MediaType.PLAIN_TEXT_UTF_8)
379+
.add("x-amzn-RequestId", "27daac76-34dd-47df-bd01-1f6e873584a0")
380+
.build()
371381
return HttpResponse.of(headers, HttpData.of(StandardCharsets.UTF_8, content))
372382
}
373383
"Ec2" | "AllocateAddress" | "POST" | "59dbff89-35bd-4eac-99ed-be587EXAMPLE" | Ec2AsyncClient.builder() | { c -> c.allocateAddress() } | """
@@ -382,7 +392,7 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
382392
<ResponseMetadata><RequestId>0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99</RequestId></ResponseMetadata>
383393
</DeleteOptionGroupResponse>
384394
"""
385-
"Sns" | "Publish" | "POST" | "f187a3c1-376f-11df-8963-01868b7c937a" | SnsAsyncClient.builder() | { SnsAsyncClient c -> c.publish(r -> r.message("hello").topicArn("somearn")) } | """
395+
"Sns" | "Publish" | "POST" | "f187a3c1-376f-11df-8963-01868b7c937a" | SnsAsyncClient.builder() | { SnsAsyncClient c -> c.publish(r -> r.message("hello").topicArn("somearn")) } | """
386396
<PublishResponse xmlns="https://sns.amazonaws.com/doc/2010-03-31/">
387397
<PublishResult>
388398
<MessageId>94f20ce6-13c5-43a0-9a9e-ca52d816e90b</MessageId>
@@ -403,13 +413,13 @@ abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest {
403413
server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofMillis(5000)))
404414
server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofMillis(5000)))
405415
def builder = S3Client.builder()
406-
.overrideConfiguration(createOverrideConfigurationBuilder()
407-
.retryPolicy(RetryPolicy.builder().numRetries(1).build())
408-
.build())
409-
.endpointOverride(clientUri)
410-
.region(Region.AP_NORTHEAST_1)
411-
.credentialsProvider(CREDENTIALS_PROVIDER)
412-
.httpClientBuilder(ApacheHttpClient.builder().socketTimeout(Duration.ofMillis(50)))
416+
.overrideConfiguration(createOverrideConfigurationBuilder()
417+
.retryPolicy(RetryPolicy.builder().numRetries(1).build())
418+
.build())
419+
.endpointOverride(clientUri)
420+
.region(Region.AP_NORTHEAST_1)
421+
.credentialsProvider(CREDENTIALS_PROVIDER)
422+
.httpClientBuilder(ApacheHttpClient.builder().socketTimeout(Duration.ofMillis(50)))
413423

414424
if (Boolean.getBoolean("testLatestDeps")) {
415425
builder.forcePathStyle(true)

0 commit comments

Comments
 (0)