Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_REQUEST_ID;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_SNS_TOPIC_ARN;
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME;
import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_METHOD;
import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_SERVICE;
Expand Down Expand Up @@ -90,6 +91,7 @@ static SpanDataAssert sns(SpanDataAssert span, String topicArn, String rpcMethod
.hasAttributesSatisfyingExactly(
equalTo(stringKey("aws.agent"), "java-aws-sdk"),
equalTo(MESSAGING_DESTINATION_NAME, topicArn),
satisfies(AWS_SNS_TOPIC_ARN, v -> v.isInstanceOf(String.class)),
satisfies(AWS_REQUEST_ID, v -> v.isInstanceOf(String.class)),
equalTo(RPC_METHOD, rpcMethod),
equalTo(RPC_SYSTEM, "aws-api"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class AwsSdkAttributesExtractor implements AttributesExtractor<Request<?>, Respo
// Copied from AwsIncubatingAttributes
private static final AttributeKey<String> AWS_SECRETSMANAGER_SECRET_ARN =
stringKey("aws.secretsmanager.secret.arn");
private static final AttributeKey<String> AWS_SNS_TOPIC_ARN = stringKey("aws.sns.topic.arn");
private static final AttributeKey<String> AWS_STEP_FUNCTIONS_ACTIVITY_ARN =
stringKey("aws.step_functions.activity.arn");
private static final AttributeKey<String> AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN =
Expand All @@ -45,6 +46,7 @@ private static boolean canGetResponseMetadata() {
@Override
public void onStart(AttributesBuilder attributes, Context parentContext, Request<?> request) {
Object originalRequest = request.getOriginalRequest();
setAttribute(attributes, AWS_SNS_TOPIC_ARN, originalRequest, RequestAccess::getSnsTopicArn);
setAttribute(
attributes,
AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN,
Expand All @@ -67,6 +69,7 @@ public void onEnd(
Object awsResp = getAwsResponse(response);
if (awsResp != null) {
setAttribute(attributes, AWS_SECRETSMANAGER_SECRET_ARN, awsResp, RequestAccess::getSecretArn);
setAttribute(attributes, AWS_SNS_TOPIC_ARN, awsResp, RequestAccess::getSnsTopicArn);
setAttribute(
attributes,
AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static String getTableName(Object request) {
}

@Nullable
static String getTopicArn(Object request) {
static String getSnsTopicArn(Object request) {
RequestAccess access = REQUEST_ACCESSORS.get(request.getClass());
return invokeOrNull(access.getTopicArn, request);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public void onStart(AttributesBuilder attributes, Context parentContext, Request
* falling back to the target ARN. If neither is found null is returned.
*/
private static String findMessageDestination(AmazonWebServiceRequest request) {
String destination = RequestAccess.getTopicArn(request);
String destination = RequestAccess.getSnsTopicArn(request);
if (destination != null) {
return destination;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
package io.opentelemetry.instrumentation.awssdk.v1_11;

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_SNS_TOPIC_ARN;
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;

import com.amazonaws.services.sns.AmazonSNS;
import com.amazonaws.services.sns.AmazonSNSClientBuilder;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.PublishRequest;
import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
import io.opentelemetry.testing.internal.armeria.common.HttpResponse;
Expand All @@ -24,6 +27,25 @@
import org.junit.jupiter.params.provider.MethodSource;

public abstract class AbstractSnsClientTest extends AbstractBaseAwsClientTest {
private static final String publishResponseBody =
"<PublishResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <PublishResult>"
+ " <MessageId>567910cd-659e-55d4-8ccb-5aaf14679dc0</MessageId>"
+ " </PublishResult>"
+ " <ResponseMetadata>"
+ " <RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>"
+ " </ResponseMetadata>"
+ "</PublishResponse>";

private static final String createTopicResponseBody =
"<CreateTopicResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <CreateTopicResult>"
+ " <TopicArn>arn:aws:sns:us-east-1:123456789012:sns-topic-foo</TopicArn>"
+ " </CreateTopicResult>"
+ " <ResponseMetadata>"
+ " <RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>"
+ " </ResponseMetadata>"
+ "</CreateTopicResponse>";

public abstract AmazonSNSClientBuilder configureClient(AmazonSNSClientBuilder client);

Expand All @@ -34,32 +56,23 @@ protected boolean hasRequestId() {

@ParameterizedTest
@MethodSource("provideArguments")
public void testSendRequestWithMockedResponse(Function<AmazonSNS, Object> call) throws Exception {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as far as I can tell you could have kept the original parameterized tests and just added the additionalAttributes as another parameter

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good feedback. Thank you @laurit.

void testSendRequestWithMockedResponse(
Function<AmazonSNS, Object> call,
String operation,
String responseBody,
List<AttributeAssertion> additionalAttributes)
throws Exception {
AmazonSNSClientBuilder clientBuilder = AmazonSNSClientBuilder.standard();
AmazonSNS client =
configureClient(clientBuilder)
.withEndpointConfiguration(endpoint)
.withCredentials(credentialsProvider)
.build();

String body =
"<PublishResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <PublishResult>"
+ " <MessageId>567910cd-659e-55d4-8ccb-5aaf14679dc0</MessageId>"
+ " </PublishResult>"
+ " <ResponseMetadata>"
+ " <RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>"
+ " </ResponseMetadata>"
+ "</PublishResponse>";

server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));

List<AttributeAssertion> additionalAttributes =
singletonList(equalTo(MESSAGING_DESTINATION_NAME, "somearn"));

server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, responseBody));
Object response = call.apply(client);
assertRequestWithMockedResponse(
response, client, "SNS", "Publish", "POST", additionalAttributes);
response, client, "SNS", operation, "POST", additionalAttributes);
}

private static Stream<Arguments> provideArguments() {
Expand All @@ -68,11 +81,26 @@ private static Stream<Arguments> provideArguments() {
(Function<AmazonSNS, Object>)
c ->
c.publish(
new PublishRequest().withMessage("somemessage").withTopicArn("somearn"))),
new PublishRequest().withMessage("somemessage").withTopicArn("somearn")),
"Publish",
publishResponseBody,
asList(
equalTo(MESSAGING_DESTINATION_NAME, "somearn"),
equalTo(AWS_SNS_TOPIC_ARN, "somearn"))),
Arguments.of(
(Function<AmazonSNS, Object>)
c ->
c.publish(
new PublishRequest().withMessage("somemessage").withTargetArn("somearn"))));
new PublishRequest().withMessage("somemessage").withTargetArn("somearn")),
"Publish",
publishResponseBody,
singletonList(equalTo(MESSAGING_DESTINATION_NAME, "somearn"))),
Arguments.of(
(Function<AmazonSNS, Object>)
c -> c.createTopic(new CreateTopicRequest().withName("sns-topic-foo")),
"CreateTopic",
createTopicResponseBody,
singletonList(
equalTo(AWS_SNS_TOPIC_ARN, "arn:aws:sns:us-east-1:123456789012:sns-topic-foo"))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ enum AwsSdkRequestType {
* Only one of TopicArn and TargetArn are permitted on an SNS request.
*/
request(AttributeKeys.MESSAGING_DESTINATION_NAME.getKey(), "TargetArn"),
request(AttributeKeys.MESSAGING_DESTINATION_NAME.getKey(), "TopicArn")),
request(AttributeKeys.MESSAGING_DESTINATION_NAME.getKey(), "TopicArn"),
request(AttributeKeys.AWS_SNS_TOPIC_ARN.getKey(), "TopicArn"),
response(AttributeKeys.AWS_SNS_TOPIC_ARN.getKey(), "TopicArn")),
STEPFUNCTIONS(
request(AttributeKeys.AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN.getKey(), "stateMachineArn"),
request(AttributeKeys.AWS_STEP_FUNCTIONS_ACTIVITY_ARN.getKey(), "activityArn"));
Expand All @@ -47,6 +49,7 @@ private static class AttributeKeys {
// Copied from AwsIncubatingAttributes
static final AttributeKey<String> AWS_SECRETSMANAGER_SECRET_ARN =
stringKey("aws.secretsmanager.secret.arn");
static final AttributeKey<String> AWS_SNS_TOPIC_ARN = stringKey("aws.sns.topic.arn");
static final AttributeKey<String> AWS_STEP_FUNCTIONS_ACTIVITY_ARN =
stringKey("aws.step_functions.activity.arn");
static final AttributeKey<String> AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_REQUEST_ID;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_SECRETSMANAGER_SECRET_ARN;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_SNS_TOPIC_ARN;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_STEP_FUNCTIONS_ACTIVITY_ARN;
import static io.opentelemetry.semconv.incubating.AwsIncubatingAttributes.AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN;
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME;
Expand Down Expand Up @@ -98,7 +99,12 @@
import software.amazon.awssdk.services.sns.SnsAsyncClientBuilder;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.SnsClientBuilder;
import software.amazon.awssdk.services.sns.model.CreateTopicRequest;
import software.amazon.awssdk.services.sns.model.CreateTopicResponse;
import software.amazon.awssdk.services.sns.model.PublishRequest;
import software.amazon.awssdk.services.sns.model.PublishResponse;
import software.amazon.awssdk.services.sns.model.SubscribeRequest;
import software.amazon.awssdk.services.sns.model.SubscribeResponse;
import software.amazon.awssdk.services.sqs.SqsAsyncClient;
import software.amazon.awssdk.services.sqs.SqsAsyncClientBuilder;
import software.amazon.awssdk.services.sqs.SqsClient;
Expand Down Expand Up @@ -139,6 +145,36 @@ public abstract class AbstractAws2ClientTest extends AbstractAws2ClientCoreTest
+ " \"CreatedDate\": \"1.523477145713E9\""
+ "}";

private static final String snsPublishResponseBody =
"<PublishResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <PublishResult>"
+ " <MessageId>567910cd-659e-55d4-8ccb-5aaf14679dc0</MessageId>"
+ " </PublishResult>"
+ " <ResponseMetadata>"
+ " <RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>"
+ " </ResponseMetadata>"
+ "</PublishResponse>";

private static final String snsSubscribeResponseBody =
"<SubscribeResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <SubscribeResult>"
+ " <SubscriptionArn>arn:aws:sns:us-west-2:123456789012:MyTopic:abc123</SubscriptionArn>"
+ " </SubscribeResult>"
+ " <ResponseMetadata>"
+ " <RequestId>0ac9cda2-abcd-11d3-f92b-31fa5e8dbc67</RequestId>"
+ " </ResponseMetadata>"
+ " </SubscribeResponse>";

private static final String snsCreateTopicResponseBody =
"<CreateTopicResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <CreateTopicResult>"
+ " <TopicArn>arn:aws:sns:us-east-1:123456789012:sns-topic-name-foo</TopicArn>"
+ " </CreateTopicResult>"
+ " <ResponseMetadata>"
+ " <RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>"
+ " </ResponseMetadata>"
+ "</CreateTopicResponse>";

private static void assumeSupportedConfig(String operation) {
Assumptions.assumeFalse(
operation.equals("SendMessage") && isSqsAttributeInjectionEnabled(),
Expand Down Expand Up @@ -223,7 +259,22 @@ private void clientAssertions(
}

if (service.equals("Sns")) {
attributes.add(equalTo(MESSAGING_DESTINATION_NAME, "somearn"));
switch (operation) {
case "CreateTopic":
attributes.add(
equalTo(AWS_SNS_TOPIC_ARN, "arn:aws:sns:us-east-1:123456789012:sns-topic-name-foo"));
break;
case "Publish":
attributes.add(equalTo(MESSAGING_DESTINATION_NAME, "sns-target-arn"));
break;
case "Subscribe":
attributes.add(equalTo(MESSAGING_DESTINATION_NAME, "sns-topic-arn"));
attributes.add(equalTo(AWS_SNS_TOPIC_ARN, "sns-topic-arn"));
break;
default:
attributes.add(equalTo(AWS_SNS_TOPIC_ARN, "Bug-Unknown-Operation-ARN"));
break;
}
}

if (service.equals("Sqs") && operation.equals("CreateQueue")) {
Expand Down Expand Up @@ -516,22 +567,43 @@ private static Stream<Arguments> provideSnsArguments() {
c ->
c.publish(
PublishRequest.builder()
.message("somemessage")
.topicArn("somearn")
.build())),
.message("sns-msg-foo")
.targetArn("sns-target-arn")
.build()),
"Publish",
"POST",
snsPublishResponseBody,
"d74b8436-ae13-5ab4-a9ff-ce54dfea72a0"),
Arguments.of(
(Function<SnsClient, Object>)
c ->
c.publish(
PublishRequest.builder()
.message("somemessage")
.targetArn("somearn")
.build())));
c.subscribe(
SubscribeRequest.builder()
.topicArn("sns-topic-arn")
.protocol("email")
.endpoint("[email protected]")
.build()),
"Subscribe",
"POST",
snsSubscribeResponseBody,
"0ac9cda2-abcd-11d3-f92b-31fa5e8dbc67"),
Arguments.of(
(Function<SnsClient, Object>)
c -> c.createTopic(CreateTopicRequest.builder().name("sns-topic-name-foo").build()),
"CreateTopic",
"POST",
snsCreateTopicResponseBody,
"d74b8436-ae13-5ab4-a9ff-ce54dfea72a0"));
}

@ParameterizedTest
@MethodSource("provideSnsArguments")
void testSnsSendOperationRequestWithBuilder(Function<SnsClient, Object> call) {
void testSnsSendOperationRequestWithBuilder(
Function<SnsClient, Object> call,
String operation,
String method,
String responseBody,
String requestId) {
SnsClientBuilder builder = SnsClient.builder();
configureSdkClient(builder);
SnsClient client =
Expand All @@ -541,28 +613,25 @@ void testSnsSendOperationRequestWithBuilder(Function<SnsClient, Object> call) {
.credentialsProvider(CREDENTIALS_PROVIDER)
.build();

String body =
"<PublishResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <PublishResult>"
+ " <MessageId>567910cd-659e-55d4-8ccb-5aaf14679dc0</MessageId>"
+ " </PublishResult>"
+ " <ResponseMetadata>"
+ " <RequestId>d74b8436-ae13-5ab4-a9ff-ce54dfea72a0</RequestId>"
+ " </ResponseMetadata>"
+ "</PublishResponse>";

server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, responseBody));
Object response = call.apply(client);

assertThat(response.getClass().getSimpleName())
.satisfiesAnyOf(
v -> assertThat(v).startsWith("Publish"),
v -> assertThat(response).isInstanceOf(ResponseInputStream.class));
clientAssertions("Sns", "Publish", "POST", response, "d74b8436-ae13-5ab4-a9ff-ce54dfea72a0");
v -> assertThat(response).isInstanceOf(CreateTopicResponse.class),
v -> assertThat(response).isInstanceOf(PublishResponse.class),
v -> assertThat(response).isInstanceOf(SubscribeResponse.class));
clientAssertions("Sns", operation, method, response, requestId);
}

@Test
void testSnsAsyncSendOperationRequestWithBuilder() {
@ParameterizedTest
@MethodSource("provideSnsArguments")
void testSnsAsyncSendOperationRequestWithBuilder(
Function<SnsClient, Object> call,
String operation,
String method,
String responseBody,
String requestId) {
SnsAsyncClientBuilder builder = SnsAsyncClient.builder();
configureSdkClient(builder);
SnsAsyncClient client =
Expand All @@ -572,20 +641,15 @@ void testSnsAsyncSendOperationRequestWithBuilder() {
.credentialsProvider(CREDENTIALS_PROVIDER)
.build();

String body =
"<PublishResponse xmlns=\"https://sns.amazonaws.com/doc/2010-03-31/\">"
+ " <PublishResult>"
+ " <MessageId>94f20ce6-13c5-43a0-9a9e-ca52d816e90b</MessageId>"
+ " </PublishResult>"
+ " <ResponseMetadata>"
+ " <RequestId>f187a3c1-376f-11df-8963-01868b7c937a</RequestId>"
+ " </ResponseMetadata>"
+ "</PublishResponse>";

server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
Object response = client.publish(r -> r.message("hello").topicArn("somearn"));
server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, responseBody));
Object response = call.apply(wrapClient(SnsClient.class, SnsAsyncClient.class, client));

clientAssertions("Sns", "Publish", "POST", response, "f187a3c1-376f-11df-8963-01868b7c937a");
assertThat(response.getClass().getSimpleName())
.satisfiesAnyOf(
v -> assertThat(response).isInstanceOf(CreateTopicResponse.class),
v -> assertThat(response).isInstanceOf(PublishResponse.class),
v -> assertThat(response).isInstanceOf(SubscribeResponse.class));
clientAssertions("Sns", operation, method, response, requestId);
}

@Test
Expand Down
Loading