diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test_before_1_11_106/groovy/Aws0ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test_before_1_11_106/groovy/Aws0ClientTest.groovy
deleted file mode 100644
index 78baace09f5c..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test_before_1_11_106/groovy/Aws0ClientTest.groovy
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import com.amazonaws.AmazonClientException
-import com.amazonaws.ClientConfiguration
-import com.amazonaws.Request
-import com.amazonaws.SDKGlobalConfiguration
-import com.amazonaws.auth.AWSCredentialsProviderChain
-import com.amazonaws.auth.BasicAWSCredentials
-import com.amazonaws.auth.EnvironmentVariableCredentialsProvider
-import com.amazonaws.auth.InstanceProfileCredentialsProvider
-import com.amazonaws.auth.NoOpSigner
-import com.amazonaws.auth.SignerFactory
-import com.amazonaws.auth.SystemPropertiesCredentialsProvider
-import com.amazonaws.auth.profile.ProfileCredentialsProvider
-import com.amazonaws.handlers.RequestHandler2
-import com.amazonaws.retry.PredefinedRetryPolicies
-import com.amazonaws.services.ec2.AmazonEC2Client
-import com.amazonaws.services.rds.AmazonRDSClient
-import com.amazonaws.services.rds.model.DeleteOptionGroupRequest
-import com.amazonaws.services.s3.AmazonS3Client
-import com.amazonaws.services.s3.S3ClientOptions
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
-import io.opentelemetry.semconv.incubating.RpcIncubatingAttributes
-import io.opentelemetry.semconv.ServerAttributes
-import io.opentelemetry.semconv.ErrorAttributes
-import io.opentelemetry.semconv.HttpAttributes
-import io.opentelemetry.semconv.NetworkAttributes
-import io.opentelemetry.semconv.UrlAttributes
-import io.opentelemetry.testing.internal.armeria.common.HttpResponse
-import io.opentelemetry.testing.internal.armeria.common.HttpStatus
-import io.opentelemetry.testing.internal.armeria.common.MediaType
-import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension
-import spock.lang.Shared
-
-import java.time.Duration
-
-import static io.opentelemetry.api.trace.SpanKind.CLIENT
-import static io.opentelemetry.api.trace.StatusCode.ERROR
-import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
-
-class Aws0ClientTest extends AgentInstrumentationSpecification {
-
- private static final CREDENTIALS_PROVIDER_CHAIN = new AWSCredentialsProviderChain(
- new EnvironmentVariableCredentialsProvider(),
- new SystemPropertiesCredentialsProvider(),
- new ProfileCredentialsProvider(),
- new InstanceProfileCredentialsProvider())
-
- @Shared
- def server = new MockWebServerExtension()
-
- def setupSpec() {
- System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key")
- System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key")
- server.start()
- }
-
- def cleanupSpec() {
- System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY)
- System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY)
- server.stop()
- }
-
- def setup() {
- server.beforeTestExecution(null)
- }
-
- def "request handler is hooked up with constructor"() {
- setup:
- String accessKey = "asdf"
- String secretKey = "qwerty"
- def credentials = new BasicAWSCredentials(accessKey, secretKey)
- def client = new AmazonS3Client(credentials)
- if (addHandler) {
- client.addRequestHandler(new RequestHandler2() {})
- }
-
- expect:
- client.requestHandler2s != null
- client.requestHandler2s.size() == size
- client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler"
-
- where:
- addHandler | size
- true | 2
- false | 1
- }
-
- def "send #operation request with mocked response"() {
- setup:
- server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body))
-
- when:
- def response = call.call(client)
-
- then:
- response != null
-
- client.requestHandler2s != null
- client.requestHandler2s.size() == handlerCount
- client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler"
-
- assertTraces(1) {
- trace(0, 1) {
- span(0) {
- name "$service.$operation"
- kind CLIENT
- hasNoParent()
- attributes {
- "$UrlAttributes.URL_FULL" "${server.httpUri()}"
- "$HttpAttributes.HTTP_REQUEST_METHOD" "$method"
- "$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
- "$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
- "$ServerAttributes.SERVER_PORT" server.httpPort()
- "$ServerAttributes.SERVER_ADDRESS" "127.0.0.1"
- "$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
- "$RpcIncubatingAttributes.RPC_SERVICE" { it.contains(service) }
- "$RpcIncubatingAttributes.RPC_METHOD" "${operation}"
- "aws.endpoint" "${server.httpUri()}"
- "aws.agent" "java-aws-sdk"
- for (def addedTag : additionalAttributes) {
- "$addedTag.key" "$addedTag.value"
- }
- }
- }
- }
- }
-
- def request = server.takeRequest()
- request.request().headers().get("X-Amzn-Trace-Id") != null
- request.request().headers().get("traceparent") == null
-
- where:
- service | operation | method | path | handlerCount | client | additionalAttributes | call | body
- "S3" | "CreateBucket" | "PUT" | "/testbucket/" | 1 | new AmazonS3Client().withEndpoint("${server.httpUri()}") | ["aws.bucket.name": "testbucket"] | { c -> c.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build()); c.createBucket("testbucket") } | ""
- "S3" | "GetObject" | "GET" | "/someBucket/someKey" | 1 | new AmazonS3Client().withEndpoint("${server.httpUri()}") | ["aws.bucket.name": "someBucket"] | { c -> c.getObject("someBucket", "someKey") } | ""
- "EC2" | "AllocateAddress" | "POST" | "/" | 4 | new AmazonEC2Client().withEndpoint("${server.httpUri()}") | [:] | { c -> c.allocateAddress() } | """
-
- 59dbff89-35bd-4eac-99ed-be587EXAMPLE
- 192.0.2.1
- standard
-
- """
- "RDS" | "DeleteOptionGroup" | "POST" | "/" | 1 | new AmazonRDSClient().withEndpoint("${server.httpUri()}") | [:] | { c -> c.deleteOptionGroup(new DeleteOptionGroupRequest()) } | """
-
-
- 0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99
-
-
- """
- }
-
- def "send #operation request to closed port"() {
- setup:
- server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body))
-
- when:
- call.call(client)
-
- then:
- thrown AmazonClientException
-
- assertTraces(1) {
- trace(0, 1) {
- span(0) {
- name "$service.$operation"
- kind CLIENT
- status ERROR
- errorEvent AmazonClientException, ~/Unable to execute HTTP request/
- hasNoParent()
- attributes {
- "$UrlAttributes.URL_FULL" "http://localhost:${UNUSABLE_PORT}"
- "$HttpAttributes.HTTP_REQUEST_METHOD" "$method"
- "$ServerAttributes.SERVER_PORT" 61
- "$ServerAttributes.SERVER_ADDRESS" "localhost"
- "$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
- "$RpcIncubatingAttributes.RPC_SERVICE" { it.contains(service) }
- "$RpcIncubatingAttributes.RPC_METHOD" "${operation}"
- "aws.endpoint" "http://localhost:${UNUSABLE_PORT}"
- "aws.agent" "java-aws-sdk"
- for (def addedTag : additionalAttributes) {
- "$addedTag.key" "$addedTag.value"
- }
- "$ErrorAttributes.ERROR_TYPE" AmazonClientException.name
- }
- }
- }
- }
-
- where:
- service | operation | method | url | call | additionalAttributes | body | client
- "S3" | "GetObject" | "GET" | "someBucket/someKey" | { client -> client.getObject("someBucket", "someKey") } | ["aws.bucket.name": "someBucket"] | "" | new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN, new ClientConfiguration().withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0))).withEndpoint("http://localhost:${UNUSABLE_PORT}")
- }
-
- def "naughty request handler doesn't break the trace"() {
- setup:
- def client = new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN)
- client.addRequestHandler(new RequestHandler2() {
- void beforeRequest(Request> request) {
- throw new IllegalStateException("bad handler")
- }
- })
-
- when:
- client.getObject("someBucket", "someKey")
-
- then:
- !Span.current().getSpanContext().isValid()
- thrown IllegalStateException
-
- assertTraces(1) {
- trace(0, 1) {
- span(0) {
- name "S3.GetObject"
- kind CLIENT
- status ERROR
- errorEvent IllegalStateException, "bad handler"
- hasNoParent()
- attributes {
- "$UrlAttributes.URL_FULL" "https://s3.amazonaws.com"
- "$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
- "$ServerAttributes.SERVER_ADDRESS" "s3.amazonaws.com"
- "$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
- "$RpcIncubatingAttributes.RPC_SERVICE" "Amazon S3"
- "$RpcIncubatingAttributes.RPC_METHOD" "GetObject"
- "aws.endpoint" "https://s3.amazonaws.com"
- "aws.agent" "java-aws-sdk"
- "aws.bucket.name" "someBucket"
- "$ErrorAttributes.ERROR_TYPE" IllegalStateException.name
- }
- }
- }
- }
- }
-
- // TODO(anuraaga): Add events for retries.
- def "timeout and retry errors not captured"() {
- setup:
- // One retry so two requests.
- server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofMillis(5000)))
- server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofMillis(5000)))
- AmazonS3Client client = new AmazonS3Client(new ClientConfiguration()
- .withRequestTimeout(50 /* ms */)
- .withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(1)))
- .withEndpoint("${server.httpUri()}")
-
- when:
- client.getObject("someBucket", "someKey")
-
- then:
- !Span.current().getSpanContext().isValid()
- thrown AmazonClientException
-
- assertTraces(1) {
- trace(0, 1) {
- span(0) {
- name "S3.GetObject"
- kind CLIENT
- status ERROR
- errorEvent AmazonClientException, ~/Unable to execute HTTP request/
- hasNoParent()
- attributes {
- "$UrlAttributes.URL_FULL" "${server.httpUri()}"
- "$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
- "$ServerAttributes.SERVER_PORT" server.httpPort()
- "$ServerAttributes.SERVER_ADDRESS" "127.0.0.1"
- "$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
- "$RpcIncubatingAttributes.RPC_SERVICE" "Amazon S3"
- "$RpcIncubatingAttributes.RPC_METHOD" "GetObject"
- "aws.endpoint" "${server.httpUri()}"
- "aws.agent" "java-aws-sdk"
- "aws.bucket.name" "someBucket"
- "$ErrorAttributes.ERROR_TYPE" AmazonClientException.name
- }
- }
- }
- }
- }
-
- def "calling generatePresignedUrl does not leak context"() {
- setup:
- SignerFactory.registerSigner("noop", NoOpSigner)
- def client = new AmazonS3Client(new ClientConfiguration().withSignerOverride("noop"))
- .withEndpoint("${server.httpUri()}")
-
- when:
- client.generatePresignedUrl("someBucket", "someKey", new Date())
-
- then:
- // expecting no active span after call to generatePresignedUrl
- !Span.current().getSpanContext().isValid()
- }
-}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test_before_1_11_106/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws0ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test_before_1_11_106/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws0ClientTest.java
new file mode 100644
index 000000000000..dc524dbcc466
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test_before_1_11_106/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws0ClientTest.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import static io.opentelemetry.api.common.AttributeKey.stringKey;
+import static io.opentelemetry.api.trace.SpanKind.CLIENT;
+import static io.opentelemetry.api.trace.SpanKind.PRODUCER;
+import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
+import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE;
+import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
+import static io.opentelemetry.semconv.HttpAttributes.HTTP_RESPONSE_STATUS_CODE;
+import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PROTOCOL_VERSION;
+import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
+import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
+import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
+import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_METHOD;
+import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_SERVICE;
+import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_SYSTEM;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyMap;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+
+import com.amazonaws.AmazonClientException;
+import com.amazonaws.AmazonWebServiceClient;
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.Request;
+import com.amazonaws.SDKGlobalConfiguration;
+import com.amazonaws.auth.AWSCredentialsProviderChain;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
+import com.amazonaws.auth.InstanceProfileCredentialsProvider;
+import com.amazonaws.auth.NoOpSigner;
+import com.amazonaws.auth.SignerFactory;
+import com.amazonaws.auth.SystemPropertiesCredentialsProvider;
+import com.amazonaws.auth.profile.ProfileCredentialsProvider;
+import com.amazonaws.handlers.RequestHandler2;
+import com.amazonaws.retry.PredefinedRetryPolicies;
+import com.amazonaws.services.ec2.AmazonEC2Client;
+import com.amazonaws.services.rds.AmazonRDSClient;
+import com.amazonaws.services.rds.model.DeleteOptionGroupRequest;
+import com.amazonaws.services.s3.AmazonS3Client;
+import com.google.common.collect.ImmutableMap;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
+import io.opentelemetry.sdk.trace.data.StatusData;
+import io.opentelemetry.testing.internal.armeria.common.HttpResponse;
+import io.opentelemetry.testing.internal.armeria.common.HttpStatus;
+import io.opentelemetry.testing.internal.armeria.common.MediaType;
+import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension;
+import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.RecordedRequest;
+import java.lang.reflect.Field;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class Aws0ClientTest {
+
+ @RegisterExtension
+ private static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+ private static final AWSCredentialsProviderChain credentialsProvider =
+ new AWSCredentialsProviderChain(
+ new EnvironmentVariableCredentialsProvider(),
+ new SystemPropertiesCredentialsProvider(),
+ new ProfileCredentialsProvider(),
+ new InstanceProfileCredentialsProvider());
+
+ private static final MockWebServerExtension server = new MockWebServerExtension();
+
+ @BeforeAll
+ static void setUp() {
+ System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key");
+ System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key");
+ server.start();
+ }
+
+ @BeforeEach
+ void reset() {
+ server.beforeTestExecution(null);
+ }
+
+ @AfterAll
+ static void cleanUp() {
+ System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY);
+ System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY);
+ server.stop();
+ }
+
+ private static Stream provideArguments() {
+ return Stream.of(Arguments.of(true, 2), Arguments.of(false, 1));
+ }
+
+ @ParameterizedTest
+ @SuppressWarnings("unchecked")
+ @MethodSource("provideArguments")
+ void testRequestHandlerIsHookedUpWithConstructor(boolean addHandler, int size) throws Exception {
+ BasicAWSCredentials credentials = new BasicAWSCredentials("asdf", "qwerty");
+ AmazonS3Client client = new AmazonS3Client(credentials);
+ if (addHandler) {
+ client.addRequestHandler(new RequestHandler2() {});
+ }
+
+ List requestHandler2s = extractRequestHandlers(client);
+
+ assertThat(requestHandler2s).isNotNull();
+ assertThat(requestHandler2s.size()).isEqualTo(size);
+ assertThat(requestHandler2s.stream().findFirst().get().getClass().getSimpleName())
+ .isEqualTo("TracingRequestHandler");
+ }
+
+ private static Stream provideSendRequestArguments() {
+ return Stream.of(
+ Arguments.of(
+ new AmazonS3Client().withEndpoint(server.httpUri().toString()),
+ "S3",
+ "CreateBucket",
+ "PUT",
+ 1,
+ (Function) c -> c.createBucket("testbucket"),
+ ImmutableMap.of("aws.bucket.name", "testbucket"),
+ ""),
+ Arguments.of(
+ new AmazonS3Client().withEndpoint(server.httpUri().toString()),
+ "S3",
+ "GetObject",
+ "GET",
+ 1,
+ (Function) c -> c.getObject("someBucket", "someKey"),
+ ImmutableMap.of("aws.bucket.name", "someBucket"),
+ ""),
+ Arguments.of(
+ new AmazonEC2Client().withEndpoint(server.httpUri().toString()),
+ "EC2",
+ "AllocateAddress",
+ "POST",
+ 4,
+ (Function) AmazonEC2Client::allocateAddress,
+ emptyMap(),
+ ""
+ + " 59dbff89-35bd-4eac-99ed-be587EXAMPLE"
+ + " 192.0.2.1"
+ + " standard"
+ + ""),
+ Arguments.of(
+ new AmazonRDSClient().withEndpoint(server.httpUri().toString()),
+ "RDS",
+ "DeleteOptionGroup",
+ "POST",
+ 1,
+ (Function)
+ c -> c.deleteOptionGroup(new DeleteOptionGroupRequest()),
+ emptyMap(),
+ ""
+ + " 59dbff89-35bd-4eac-99ed-be587EXAMPLE"
+ + " 192.0.2.1"
+ + " standard"
+ + ""));
+ }
+
+ @ParameterizedTest
+ @MethodSource("provideSendRequestArguments")
+ @SuppressWarnings("unchecked")
+ void testSendRequestWithMockedResponse(
+ AmazonWebServiceClient client,
+ String service,
+ String operation,
+ String method,
+ int handlerCount,
+ Function call,
+ Map additionalAttributes,
+ String body)
+ throws Exception {
+ server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
+
+ Object response = call.apply(client);
+ assertThat(response).isNotNull();
+
+ List requestHandler2s = extractRequestHandlers(client);
+
+ assertThat(requestHandler2s).isNotNull();
+ assertThat(requestHandler2s.size()).isEqualTo(handlerCount);
+ assertThat(requestHandler2s.stream().findFirst().get().getClass().getSimpleName())
+ .isEqualTo("TracingRequestHandler");
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span -> {
+ List attributes =
+ new ArrayList<>(
+ asList(
+ equalTo(URL_FULL, server.httpUri().toString()),
+ equalTo(HTTP_REQUEST_METHOD, method),
+ equalTo(HTTP_RESPONSE_STATUS_CODE, 200),
+ equalTo(NETWORK_PROTOCOL_VERSION, "1.1"),
+ equalTo(SERVER_PORT, server.httpPort()),
+ equalTo(SERVER_ADDRESS, "127.0.0.1"),
+ equalTo(RPC_SYSTEM, "aws-api"),
+ satisfies(RPC_SERVICE, v -> v.contains(service)),
+ equalTo(RPC_METHOD, operation),
+ equalTo(stringKey("aws.endpoint"), server.httpUri().toString()),
+ equalTo(stringKey("aws.agent"), "java-aws-sdk")));
+
+ additionalAttributes.forEach((k, v) -> attributes.add(equalTo(stringKey(k), v)));
+
+ span.hasName(service + "." + operation)
+ .hasKind(operation.equals("SendMessage") ? PRODUCER : CLIENT)
+ .hasNoParent()
+ .hasAttributesSatisfyingExactly(attributes);
+ }));
+
+ RecordedRequest request = server.takeRequest();
+ assertThat(request.request().headers().get("X-Amzn-Trace-Id")).isNotNull();
+ assertThat(request.request().headers().get("traceparent")).isNull();
+ }
+
+ @Test
+ void testSendS3RequestToClosedPort() {
+ AmazonS3Client client =
+ new AmazonS3Client(
+ credentialsProvider,
+ new ClientConfiguration()
+ .withRetryPolicy(
+ PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0)))
+ .withEndpoint("http://localhost:" + UNUSABLE_PORT);
+
+ server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
+
+ Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
+ assertThat(caught).isInstanceOf(AmazonClientException.class);
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span ->
+ span.hasName("S3.GetObject")
+ .hasKind(CLIENT)
+ .hasStatus(StatusData.error())
+ .hasException(caught)
+ .hasNoParent()
+ .hasAttributesSatisfyingExactly(
+ equalTo(URL_FULL, "http://localhost:" + UNUSABLE_PORT),
+ equalTo(HTTP_REQUEST_METHOD, "GET"),
+ equalTo(SERVER_ADDRESS, "localhost"),
+ equalTo(SERVER_PORT, 61),
+ equalTo(RPC_SYSTEM, "aws-api"),
+ equalTo(RPC_SERVICE, "Amazon S3"),
+ equalTo(RPC_METHOD, "GetObject"),
+ equalTo(stringKey("aws.endpoint"), "http://localhost:" + UNUSABLE_PORT),
+ equalTo(stringKey("aws.agent"), "java-aws-sdk"),
+ equalTo(stringKey("aws.bucket.name"), "someBucket"),
+ equalTo(ERROR_TYPE, AmazonClientException.class.getName()))));
+ }
+
+ @Test
+ void testNaughtyRequestHandlerDoesntBreakTheTrace() {
+ AmazonS3Client client = new AmazonS3Client(credentialsProvider);
+ client.addRequestHandler(
+ new RequestHandler2() {
+ @Override
+ public void beforeRequest(Request> request) {
+ throw new IllegalStateException("bad handler");
+ }
+ });
+
+ Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
+
+ assertThat(caught).isInstanceOf(IllegalStateException.class);
+ assertThat(Span.current().getSpanContext().isValid()).isFalse();
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span ->
+ span.hasName("S3.GetObject")
+ .hasKind(CLIENT)
+ .hasStatus(StatusData.error())
+ .hasException(caught)
+ .hasNoParent()
+ .hasAttributesSatisfyingExactly(
+ equalTo(URL_FULL, "https://s3.amazonaws.com"),
+ equalTo(HTTP_REQUEST_METHOD, "GET"),
+ equalTo(SERVER_ADDRESS, "s3.amazonaws.com"),
+ equalTo(RPC_SYSTEM, "aws-api"),
+ equalTo(RPC_SERVICE, "Amazon S3"),
+ equalTo(RPC_METHOD, "GetObject"),
+ equalTo(stringKey("aws.endpoint"), "https://s3.amazonaws.com"),
+ equalTo(stringKey("aws.agent"), "java-aws-sdk"),
+ equalTo(stringKey("aws.bucket.name"), "someBucket"),
+ equalTo(ERROR_TYPE, IllegalStateException.class.getName()))));
+ }
+
+ @Test
+ void testTimeoutAndRetryErrorsAreNotCaptured() {
+ server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(5)));
+ server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(5)));
+ AmazonS3Client client =
+ new AmazonS3Client(
+ new ClientConfiguration()
+ .withRequestTimeout(50 /* ms */)
+ .withRetryPolicy(
+ PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(1)))
+ .withEndpoint(server.httpUri().toString());
+
+ Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
+
+ assertThat(caught).isInstanceOf(AmazonClientException.class);
+ assertThat(Span.current().getSpanContext().isValid()).isFalse();
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span ->
+ span.hasName("S3.GetObject")
+ .hasKind(CLIENT)
+ .hasStatus(StatusData.error())
+ .hasException(caught)
+ .hasNoParent()
+ .hasAttributesSatisfyingExactly(
+ equalTo(URL_FULL, server.httpUri().toString()),
+ equalTo(HTTP_REQUEST_METHOD, "GET"),
+ equalTo(SERVER_PORT, server.httpPort()),
+ equalTo(SERVER_ADDRESS, "127.0.0.1"),
+ equalTo(RPC_SYSTEM, "aws-api"),
+ equalTo(RPC_SERVICE, "Amazon S3"),
+ equalTo(RPC_METHOD, "GetObject"),
+ equalTo(stringKey("aws.endpoint"), server.httpUri().toString()),
+ equalTo(stringKey("aws.agent"), "java-aws-sdk"),
+ equalTo(stringKey("aws.bucket.name"), "someBucket"),
+ equalTo(ERROR_TYPE, AmazonClientException.class.getName()))));
+ }
+
+ @Test
+ void testCallingGeneratePresignedUrlDoesNotLeakContext() {
+ SignerFactory.registerSigner("noop", NoOpSigner.class);
+ AmazonS3Client client =
+ new AmazonS3Client(new ClientConfiguration().withSignerOverride("noop"))
+ .withEndpoint(server.httpUri().toString());
+
+ client.generatePresignedUrl("someBucket", "someKey", new Date());
+
+ assertThat(Span.current().getSpanContext().isValid()).isFalse();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List extractRequestHandlers(Object client) throws Exception {
+ Field requestHandler2sField = AmazonWebServiceClient.class.getDeclaredField("requestHandler2s");
+ requestHandler2sField.setAccessible(true);
+ return (List) requestHandler2sField.get(client);
+ }
+}