From 827566a5220f7d16fee4fbf6bb1a1be323fc8599 Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Wed, 30 Oct 2024 16:08:07 -0400
Subject: [PATCH 1/8] attempt again

---
 .../awssdk/v1_11/Aws1ClientTest.groovy        |  2 +-
 .../awssdk/v1_11/Aws1ClientTest.java          | 30 +++++++
 .../v1_11/AbstractAws1ClientTest.groovy       |  2 +-
 .../awssdk/v1_11/AbstractAws1ClientTest.java  | 84 +++++++++++++++++++
 4 files changed, 116 insertions(+), 2 deletions(-)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
index 3fa3506617f6..58b37c1f52c1 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
@@ -7,7 +7,7 @@ package io.opentelemetry.instrumentation.awssdk.v1_11
 
 import io.opentelemetry.instrumentation.test.LibraryTestTrait
 
-class Aws1ClientTest extends AbstractAws1ClientTest implements LibraryTestTrait {
+class Aws1ClientTest1 extends AbstractAws1ClientTest implements LibraryTestTrait {
   @Override
   def configureClient(def client) {
     client.withRequestHandlers(
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java
new file mode 100644
index 000000000000..f03e78d0cc62
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.client.builder.AwsClientBuilder;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class Aws1ClientTest extends AbstractAws1ClientTest {
+  @RegisterExtension
+  private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AwsClientBuilder configureClient(AwsClientBuilder client) {
+    return client.withRequestHandlers(
+        AwsSdkTelemetry.builder(testing().getOpenTelemetry())
+            .setCaptureExperimentalSpanAttributes(true)
+            .build()
+            .newRequestHandler());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
index c4c5bbb9f47a..fa6baf180f9b 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
@@ -53,7 +53,7 @@ import static io.opentelemetry.api.trace.SpanKind.PRODUCER
 import static io.opentelemetry.api.trace.StatusCode.ERROR
 import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
 
-abstract class AbstractAws1ClientTest extends InstrumentationSpecification {
+abstract class AbstractAws1ClientTest2 extends InstrumentationSpecification {
 
   abstract <T> T configureClient(T client)
 
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java
new file mode 100644
index 000000000000..1c52e09f4b6d
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import com.amazonaws.SDKGlobalConfiguration;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.AnonymousAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.handlers.RequestHandler2;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.amazonaws.services.s3.model.Bucket;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+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 java.lang.reflect.Field;
+import java.util.List;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractAws1ClientTest {
+  protected abstract InstrumentationExtension testing();
+
+  private static final MockWebServerExtension server = new MockWebServerExtension();
+  private static AwsClientBuilder.EndpointConfiguration endpoint;
+  private static final AWSStaticCredentialsProvider credentialsProvider =
+      new AWSStaticCredentialsProvider(new AnonymousAWSCredentials());
+
+  @BeforeAll
+  public 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();
+    endpoint = new AwsClientBuilder.EndpointConfiguration("${server.httpUri()}", "us-west-2");
+    server.beforeTestExecution(null);
+  }
+
+  @AfterAll
+  public static void cleanUp() {
+    System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY);
+    System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY);
+    server.stop();
+  }
+
+  //  abstract AwsClientBuilder<?> configureClient(AwsClientBuilder client);
+
+  @Test
+  @SuppressWarnings("unchecked")
+  public void test() throws NoSuchFieldException, IllegalAccessException {
+    String body = "";
+    AmazonS3ClientBuilder clientBuilder =
+        AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true);
+    AmazonS3 client =
+        (AmazonS3)
+            configureClient(clientBuilder)
+                .withEndpointConfiguration(endpoint)
+                .withCredentials(credentialsProvider)
+                .build();
+
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
+    Bucket response = client.createBucket("testbucket");
+
+    assertThat(response).isNotNull();
+
+    Field requestHandler2sField = client.getClass().getDeclaredField("requestHandler2s");
+    requestHandler2sField.setAccessible(true);
+    List<RequestHandler2> requestHandler2s =
+        (List<RequestHandler2>) requestHandler2sField.get(client);
+
+    assertThat(requestHandler2s).isNotNull();
+    assertThat(
+            requestHandler2s.stream()
+                .filter(h -> "TracingRequestHandler".equals(h.getClass().getSimpleName())))
+        .isNotNull();
+  }
+}

From 2f6685a0880533030b712679969c06380467fe0d Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Sat, 9 Nov 2024 14:05:49 -0500
Subject: [PATCH 2/8] s3 and dynamo working, now kinesis

---
 .../awssdk/v1_11/Aws1DynamoDbClientTest.java  |  30 +++++
 .../awssdk/v1_11/Aws1KinesisClientTest.java   |  30 +++++
 ...1ClientTest.java => Aws1S3ClientTest.java} |   8 +-
 .../v1_11/AbstractAws1ClientTest.groovy       |   2 +-
 .../v1_11/AbstractAws1BaseClientTest.java     | 116 ++++++++++++++++++
 .../awssdk/v1_11/AbstractAws1ClientTest.java  |  84 -------------
 .../v1_11/AbstractAws1DynamoDbClientTest.java |  41 +++++++
 .../v1_11/AbstractAws1KinesisClientTest.java  |  71 +++++++++++
 .../v1_11/AbstractAws1S3ClientTest.java       |  61 +++++++++
 9 files changed, 354 insertions(+), 89 deletions(-)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java
 rename instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/{Aws1ClientTest.java => Aws1S3ClientTest.java} (75%)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java
 delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java
new file mode 100644
index 000000000000..9110a306c847
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class Aws1DynamoDbClientTest extends AbstractAws1DynamoDbClientTest {
+  @RegisterExtension
+  private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder clientBuilder) {
+    return clientBuilder.withRequestHandlers(
+        AwsSdkTelemetry.builder(testing().getOpenTelemetry())
+            .setCaptureExperimentalSpanAttributes(true)
+            .build()
+            .newRequestHandler());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java
new file mode 100644
index 000000000000..7aa830a8d999
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class Aws1KinesisClientTest extends AbstractAws1KinesisClientTest {
+  @RegisterExtension
+  private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonKinesisClientBuilder configureClient(AmazonKinesisClientBuilder clientBuilder) {
+    return clientBuilder.withRequestHandlers(
+        AwsSdkTelemetry.builder(testing().getOpenTelemetry())
+            .setCaptureExperimentalSpanAttributes(true)
+            .build()
+            .newRequestHandler());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1S3ClientTest.java
similarity index 75%
rename from instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1S3ClientTest.java
index f03e78d0cc62..596bb39f6e58 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1S3ClientTest.java
@@ -5,12 +5,12 @@
 
 package io.opentelemetry.instrumentation.awssdk.v1_11;
 
-import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
 import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
 import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-class Aws1ClientTest extends AbstractAws1ClientTest {
+class Aws1S3ClientTest extends AbstractAws1S3ClientTest {
   @RegisterExtension
   private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
 
@@ -20,8 +20,8 @@ protected InstrumentationExtension testing() {
   }
 
   @Override
-  public AwsClientBuilder configureClient(AwsClientBuilder client) {
-    return client.withRequestHandlers(
+  public AmazonS3ClientBuilder configureClient(AmazonS3ClientBuilder clientBuilder) {
+    return clientBuilder.withRequestHandlers(
         AwsSdkTelemetry.builder(testing().getOpenTelemetry())
             .setCaptureExperimentalSpanAttributes(true)
             .build()
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
index fa6baf180f9b..c4c5bbb9f47a 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
@@ -53,7 +53,7 @@ import static io.opentelemetry.api.trace.SpanKind.PRODUCER
 import static io.opentelemetry.api.trace.StatusCode.ERROR
 import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
 
-abstract class AbstractAws1ClientTest2 extends InstrumentationSpecification {
+abstract class AbstractAws1ClientTest extends InstrumentationSpecification {
 
   abstract <T> T configureClient(T client)
 
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java
new file mode 100644
index 000000000000..68a1c06c3e91
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.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.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
+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 org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import com.amazonaws.AmazonWebServiceClient;
+import com.amazonaws.SDKGlobalConfiguration;
+import com.amazonaws.auth.AWSStaticCredentialsProvider;
+import com.amazonaws.auth.AnonymousAWSCredentials;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.handlers.RequestHandler2;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
+import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+
+public abstract class AbstractAws1BaseClientTest {
+  protected abstract InstrumentationExtension testing();
+
+  protected static MockWebServerExtension server = new MockWebServerExtension();
+  protected static AwsClientBuilder.EndpointConfiguration endpoint;
+  protected static final AWSStaticCredentialsProvider credentialsProvider =
+      new AWSStaticCredentialsProvider(new AnonymousAWSCredentials());
+
+  @BeforeAll
+  public 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();
+    endpoint = new AwsClientBuilder.EndpointConfiguration(server.httpUri().toString(), "us-west-2");
+    server.beforeTestExecution(null);
+  }
+
+  @AfterAll
+  public static void cleanUp() {
+    System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY);
+    System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY);
+    server.stop();
+  }
+
+  @SuppressWarnings("unchecked")
+  public void requestWithMockedResponse(
+      Object response,
+      Object client,
+      String service,
+      String operation,
+      String method,
+      Map<String, String> additionalAttributes)
+      throws NoSuchFieldException, IllegalAccessException {
+
+    assertThat(response).isNotNull();
+
+    Field requestHandler2sField = AmazonWebServiceClient.class.getDeclaredField("requestHandler2s");
+    requestHandler2sField.setAccessible(true);
+    List<RequestHandler2> requestHandler2s =
+        (List<RequestHandler2>) requestHandler2sField.get(client);
+
+    assertThat(requestHandler2s).isNotNull();
+    assertThat(
+            requestHandler2s.stream()
+                .filter(h -> "TracingRequestHandler".equals(h.getClass().getSimpleName())))
+        .isNotNull();
+
+    testing()
+        .waitAndAssertTraces(
+            trace ->
+                trace.hasSpansSatisfyingExactly(
+                    span -> {
+                      List<AttributeAssertion> 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"), endpoint.getServiceEndpoint()),
+                                  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);
+                    }));
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java
deleted file mode 100644
index 1c52e09f4b6d..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v1_11;
-
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
-
-import com.amazonaws.SDKGlobalConfiguration;
-import com.amazonaws.auth.AWSStaticCredentialsProvider;
-import com.amazonaws.auth.AnonymousAWSCredentials;
-import com.amazonaws.client.builder.AwsClientBuilder;
-import com.amazonaws.handlers.RequestHandler2;
-import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.AmazonS3ClientBuilder;
-import com.amazonaws.services.s3.model.Bucket;
-import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
-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 java.lang.reflect.Field;
-import java.util.List;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-
-public abstract class AbstractAws1ClientTest {
-  protected abstract InstrumentationExtension testing();
-
-  private static final MockWebServerExtension server = new MockWebServerExtension();
-  private static AwsClientBuilder.EndpointConfiguration endpoint;
-  private static final AWSStaticCredentialsProvider credentialsProvider =
-      new AWSStaticCredentialsProvider(new AnonymousAWSCredentials());
-
-  @BeforeAll
-  public 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();
-    endpoint = new AwsClientBuilder.EndpointConfiguration("${server.httpUri()}", "us-west-2");
-    server.beforeTestExecution(null);
-  }
-
-  @AfterAll
-  public static void cleanUp() {
-    System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY);
-    System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY);
-    server.stop();
-  }
-
-  //  abstract AwsClientBuilder<?> configureClient(AwsClientBuilder client);
-
-  @Test
-  @SuppressWarnings("unchecked")
-  public void test() throws NoSuchFieldException, IllegalAccessException {
-    String body = "";
-    AmazonS3ClientBuilder clientBuilder =
-        AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true);
-    AmazonS3 client =
-        (AmazonS3)
-            configureClient(clientBuilder)
-                .withEndpointConfiguration(endpoint)
-                .withCredentials(credentialsProvider)
-                .build();
-
-    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
-    Bucket response = client.createBucket("testbucket");
-
-    assertThat(response).isNotNull();
-
-    Field requestHandler2sField = client.getClass().getDeclaredField("requestHandler2s");
-    requestHandler2sField.setAccessible(true);
-    List<RequestHandler2> requestHandler2s =
-        (List<RequestHandler2>) requestHandler2sField.get(client);
-
-    assertThat(requestHandler2s).isNotNull();
-    assertThat(
-            requestHandler2s.stream()
-                .filter(h -> "TracingRequestHandler".equals(h.getClass().getSimpleName())))
-        .isNotNull();
-  }
-}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java
new file mode 100644
index 000000000000..0d37a2302883
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
+import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
+import com.google.common.collect.ImmutableMap;
+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 org.junit.jupiter.api.Test;
+
+public abstract class AbstractAws1DynamoDbClientTest extends AbstractAws1BaseClientTest {
+
+  public abstract AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder client);
+
+  @Test
+  public void sendRequestWithMockedResponse() throws Exception {
+    AmazonDynamoDBClientBuilder clientBuilder = AmazonDynamoDBClientBuilder.standard();
+    AmazonDynamoDB client =
+        configureClient(clientBuilder)
+            .withEndpointConfiguration(endpoint)
+            .withCredentials(credentialsProvider)
+            .build();
+
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
+
+    Object response = client.createTable(new CreateTableRequest("sometable", null));
+    requestWithMockedResponse(
+        response,
+        client,
+        "DynamoDBv2",
+        "CreateTable",
+        "POST",
+        ImmutableMap.of("aws.table.name", "sometable"));
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java
new file mode 100644
index 000000000000..44cab88fce58
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.kinesis.AmazonKinesis;
+import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder;
+import com.amazonaws.services.kinesis.model.DeleteStreamRequest;
+import com.google.common.collect.ImmutableMap;
+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 java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public abstract class AbstractAws1KinesisClientTest extends AbstractAws1BaseClientTest {
+
+  public abstract AmazonKinesisClientBuilder configureClient(AmazonKinesisClientBuilder client);
+
+  @ParameterizedTest
+  @MethodSource("provideArguments")
+  public void testSendRequestWithMockedResponse(
+      String operation,
+      String method,
+      Function<AmazonKinesis, Object> call,
+      Map<String, String> additionalAttributes)
+      throws Exception {
+
+    AmazonKinesisClientBuilder clientBuilder = AmazonKinesisClientBuilder.standard();
+
+    AmazonKinesis client =
+        configureClient(clientBuilder)
+            .withEndpointConfiguration(endpoint)
+            .withCredentials(credentialsProvider)
+            .build();
+
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
+
+    Object response = call.apply(client);
+    requestWithMockedResponse(response, client, "Kinesis", operation, method, additionalAttributes);
+  }
+
+  private static Stream<Arguments> provideArguments() {
+    return Stream.of(
+        Arguments.of(
+            "DeleteStream",
+            "POST",
+            (Function<AmazonKinesis, Object>)
+                c -> c.deleteStream(new DeleteStreamRequest().withStreamName("somestream")),
+            ImmutableMap.of("aws.stream.name", "somestream")),
+        // Some users may implicitly subclass the request object to mimic a fluent style
+        Arguments.of(
+            "DeleteStream",
+            "POST",
+            (Function<AmazonKinesis, Object>)
+                c ->
+                    c.deleteStream(
+                        new DeleteStreamRequest() {
+                          {
+                            withStreamName("somestream");
+                          }
+                        }),
+            ImmutableMap.of("aws.stream.name", "somestream")));
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java
new file mode 100644
index 000000000000..a1540800006b
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.google.common.collect.ImmutableMap;
+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 java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public abstract class AbstractAws1S3ClientTest extends AbstractAws1BaseClientTest {
+
+  public abstract AmazonS3ClientBuilder configureClient(AmazonS3ClientBuilder client);
+
+  @ParameterizedTest
+  @MethodSource("provideArguments")
+  public void testSendRequestWithMockedResponse(
+      String operation,
+      String method,
+      Function<AmazonS3, Object> call,
+      Map<String, String> additionalAttributes)
+      throws Exception {
+
+    AmazonS3ClientBuilder clientBuilder =
+        AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true);
+    AmazonS3 client =
+        configureClient(clientBuilder)
+            .withEndpointConfiguration(endpoint)
+            .withCredentials(credentialsProvider)
+            .build();
+
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
+
+    Object response = call.apply(client);
+    requestWithMockedResponse(response, client, "S3", operation, method, additionalAttributes);
+  }
+
+  private static Stream<Arguments> provideArguments() {
+    return Stream.of(
+        Arguments.of(
+            "CreateBucket",
+            "PUT",
+            (Function<AmazonS3, Object>) c -> c.createBucket("testbucket"),
+            ImmutableMap.of("aws.bucket.name", "testbucket")),
+        Arguments.of(
+            "GetObject",
+            "GET",
+            (Function<AmazonS3, Object>) c -> c.getObject("someBucket", "someKey"),
+            ImmutableMap.of("aws.bucket.name", "someBucket")));
+  }
+}

From 3f8ad533afd55ceba756b53ef02dea982b840e92 Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Sun, 10 Nov 2024 07:33:52 -0500
Subject: [PATCH 3/8] everything working

---
 .../awssdk/v1_11/Aws1ClientTest.groovy        | 137 ---------
 .../awssdk/v1_11/DynamoDbClientTest.java      |  27 ++
 .../awssdk/v1_11/Ec2ClientTest.java           |  27 ++
 .../awssdk/v1_11/KinesisClientTest.java       |  27 ++
 .../awssdk/v1_11/RdsClientTest.java           |  27 ++
 .../awssdk/v1_11/S3ClientTest.java            | 154 ++++++++++
 .../awssdk/v1_11/SnsClientTest.java           |  27 ++
 .../awssdk/v1_11/Aws1ClientTest.groovy        |  19 --
 ...lientTest.java => DynamoDbClientTest.java} |   2 +-
 .../awssdk/v1_11/Ec2ClientTest.java           |  30 ++
 ...ClientTest.java => KinesisClientTest.java} |   2 +-
 .../awssdk/v1_11/RdsClientTest.java           |  30 ++
 ...ws1S3ClientTest.java => S3ClientTest.java} |   2 +-
 .../awssdk/v1_11/SnsClientTest.java           |  30 ++
 .../aws-sdk-1.11/testing/build.gradle.kts     |   2 -
 .../v1_11/AbstractAws1ClientTest.groovy       | 286 ------------------
 .../v1_11/AbstractAws1S3ClientTest.java       |  61 ----
 ...st.java => AbstractBaseAwsClientTest.java} |  29 +-
 ...t.java => AbstractDynamoDbClientTest.java} |   9 +-
 .../awssdk/v1_11/AbstractEc2ClientTest.java   |  46 +++
 ...st.java => AbstractKinesisClientTest.java} |  40 ++-
 .../awssdk/v1_11/AbstractRdsClientTest.java   |  47 +++
 .../awssdk/v1_11/AbstractS3ClientTest.java    | 200 ++++++++++++
 .../awssdk/v1_11/AbstractSnsClientTest.java   |  76 +++++
 24 files changed, 797 insertions(+), 540 deletions(-)
 delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java
 delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
 rename instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/{Aws1DynamoDbClientTest.java => DynamoDbClientTest.java} (93%)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Ec2ClientTest.java
 rename instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/{Aws1KinesisClientTest.java => KinesisClientTest.java} (93%)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/RdsClientTest.java
 rename instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/{Aws1S3ClientTest.java => S3ClientTest.java} (94%)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SnsClientTest.java
 delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
 delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java
 rename instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/{AbstractAws1BaseClientTest.java => AbstractBaseAwsClientTest.java} (88%)
 rename instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/{AbstractAws1DynamoDbClientTest.java => AbstractDynamoDbClientTest.java} (87%)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractEc2ClientTest.java
 rename instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/{AbstractAws1KinesisClientTest.java => AbstractKinesisClientTest.java} (69%)
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractRdsClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSnsClientTest.java

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
deleted file mode 100644
index 8aabe4ffdff3..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/groovy/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11
-
-import com.amazonaws.AmazonWebServiceClient
-import com.amazonaws.ClientConfiguration
-import com.amazonaws.Request
-import com.amazonaws.auth.BasicAWSCredentials
-import com.amazonaws.auth.NoOpSigner
-import com.amazonaws.auth.SignerFactory
-import com.amazonaws.handlers.RequestHandler2
-import com.amazonaws.regions.Regions
-import com.amazonaws.services.s3.AmazonS3Client
-import com.amazonaws.services.s3.AmazonS3ClientBuilder
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.api.trace.SpanKind
-import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractAws1ClientTest
-import io.opentelemetry.instrumentation.test.AgentTestTrait
-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.UrlAttributes
-
-import static io.opentelemetry.api.trace.StatusCode.ERROR
-
-class Aws1ClientTest extends AbstractAws1ClientTest implements AgentTestTrait {
-  @Override
-  def configureClient(def client) {
-    return client
-  }
-
-  // Verify agent instruments old and new construction patterns.
-
-  def "request handler is hooked up with builder"() {
-    setup:
-    def builder = AmazonS3ClientBuilder.standard()
-      .withRegion(Regions.US_EAST_1)
-    if (addHandler) {
-      builder.withRequestHandlers(new RequestHandler2() {})
-    }
-    AmazonWebServiceClient client = builder.build()
-
-    expect:
-    client.requestHandler2s != null
-    client.requestHandler2s.size() == size
-    client.requestHandler2s.get(position).getClass().getSimpleName() == "TracingRequestHandler"
-
-    where:
-    addHandler | size | position
-    true       | 2    | 1
-    false      | 1    | 0
-  }
-
-  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
-  }
-
-  // Test cases that require workarounds using bytecode instrumentation
-
-  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.HeadBucket"
-          kind SpanKind.CLIENT
-          status ERROR
-          errorEvent IllegalStateException, "bad handler"
-          hasNoParent()
-          attributes {
-            "$UrlAttributes.URL_FULL" "https://s3.amazonaws.com"
-            "$HttpAttributes.HTTP_REQUEST_METHOD" "HEAD"
-            "$ServerAttributes.SERVER_ADDRESS" "s3.amazonaws.com"
-            "$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
-            "$RpcIncubatingAttributes.RPC_SERVICE" "Amazon S3"
-            "$RpcIncubatingAttributes.RPC_METHOD" "HeadBucket"
-            "aws.endpoint" "https://s3.amazonaws.com"
-            "aws.agent" "java-aws-sdk"
-            "aws.bucket.name" "someBucket"
-            "$ErrorAttributes.ERROR_TYPE" IllegalStateException.name
-          }
-        }
-      }
-    }
-  }
-
-  def "calling generatePresignedUrl does not leak context"() {
-    setup:
-    SignerFactory.registerSigner("noop", NoOpSigner)
-    def client = AmazonS3ClientBuilder.standard()
-      .withRegion(Regions.US_EAST_1)
-      .withClientConfiguration(new ClientConfiguration().withSignerOverride("noop"))
-      .build()
-
-    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/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
new file mode 100644
index 000000000000..b5098b9c68e8
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractDynamoDbClientTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class DynamoDbClientTest extends AbstractDynamoDbClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Override
+  public AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder client) {
+    return client;
+  }
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java
new file mode 100644
index 000000000000..a2366f14596b
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractEc2ClientTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class Ec2ClientTest extends AbstractEc2ClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonEC2ClientBuilder configureClient(AmazonEC2ClientBuilder clientBuilder) {
+    return clientBuilder;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java
new file mode 100644
index 000000000000..070515665472
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractKinesisClientTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class KinesisClientTest extends AbstractKinesisClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonKinesisClientBuilder configureClient(AmazonKinesisClientBuilder clientBuilder) {
+    return clientBuilder;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java
new file mode 100644
index 000000000000..87849fe7af10
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.rds.AmazonRDSClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractRdsClientTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class RdsClientTest extends AbstractRdsClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonRDSClientBuilder configureClient(AmazonRDSClientBuilder client) {
+    return client;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
new file mode 100644
index 000000000000..bf97f9068c2a
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
+import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE;
+import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
+import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
+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 org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.assertj.core.api.AssertionsForClassTypes.catchThrowable;
+
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.Request;
+import com.amazonaws.auth.BasicAWSCredentials;
+import com.amazonaws.auth.NoOpSigner;
+import com.amazonaws.auth.SignerFactory;
+import com.amazonaws.handlers.RequestHandler2;
+import com.amazonaws.regions.Regions;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3Client;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractS3ClientTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.sdk.trace.data.StatusData;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Stream;
+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;
+
+@SuppressWarnings("deprecation") // AmazonS3Client constructor is deprecated
+class S3ClientTest extends AbstractS3ClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonS3ClientBuilder configureClient(AmazonS3ClientBuilder client) {
+    return client;
+  }
+
+  // Verify agent instruments old and new construction patterns.
+  @ParameterizedTest
+  @MethodSource("provideS3Arguments")
+  void testRequestHandlerIsHookedUpWithBuilder(boolean addHandler, int size, int position)
+      throws Exception {
+    AmazonS3ClientBuilder builder = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1);
+
+    if (addHandler) {
+      builder.withRequestHandlers(new RequestHandler2() {});
+    }
+    AmazonS3 client = builder.build();
+
+    List<RequestHandler2> requestHandler2s = extractRequestHandlers(client);
+    assertThat(requestHandler2s).isNotNull();
+    assertThat(requestHandler2s.size()).isEqualTo(size);
+    assertThat(requestHandler2s.get(position).getClass().getSimpleName())
+        .isEqualTo("TracingRequestHandler");
+  }
+
+  private static Stream<Arguments> provideS3Arguments() {
+    return Stream.of(Arguments.of(true, 2, 1), Arguments.of(false, 1, 0));
+  }
+
+  @ParameterizedTest
+  @MethodSource("provideS3Arguments")
+  void testRequestHandlerIsHookedUpWithConstructor(boolean addHandler, int size) throws Exception {
+    String accessKey = "asdf";
+    String secretKey = "qwerty";
+    BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
+    AmazonS3Client client = new AmazonS3Client(credentials);
+    if (addHandler) {
+      client.addRequestHandler(new RequestHandler2() {});
+    }
+
+    List<RequestHandler2> requestHandler2s = extractRequestHandlers(client);
+
+    assertThat(requestHandler2s).isNotNull();
+    assertThat(requestHandler2s.size()).isEqualTo(size);
+    assertThat(requestHandler2s.get(0).getClass().getSimpleName())
+        .isEqualTo("TracingRequestHandler");
+  }
+
+  @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.HeadBucket")
+                            .hasKind(CLIENT)
+                            .hasStatus(StatusData.error())
+                            .hasException(caught)
+                            .hasNoParent()
+                            .hasAttributesSatisfyingExactly(
+                                equalTo(URL_FULL, "https://s3.amazonaws.com"),
+                                equalTo(HTTP_REQUEST_METHOD, "HEAD"),
+                                equalTo(SERVER_ADDRESS, "s3.amazonaws.com"),
+                                equalTo(RPC_SYSTEM, "aws-api"),
+                                equalTo(RPC_SERVICE, "Amazon S3"),
+                                equalTo(RPC_METHOD, "HeadBucket"),
+                                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 testCallingGeneratePresignedUrlDoesNotLeakContext() {
+    SignerFactory.registerSigner("noop", NoOpSigner.class);
+    AmazonS3 client =
+        AmazonS3ClientBuilder.standard()
+            .withRegion(Regions.US_EAST_1)
+            .withClientConfiguration(new ClientConfiguration().withSignerOverride("noop"))
+            .build();
+
+    client.generatePresignedUrl("someBucket", "someKey", new Date());
+
+    assertThat(Span.current().getSpanContext().isValid()).isFalse();
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java
new file mode 100644
index 000000000000..22fa16628403
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.sns.AmazonSNSClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractSnsClientTest;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class SnsClientTest extends AbstractSnsClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonSNSClientBuilder configureClient(AmazonSNSClientBuilder clientBuilder) {
+    return clientBuilder;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
deleted file mode 100644
index 58b37c1f52c1..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1ClientTest.groovy
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v1_11
-
-import io.opentelemetry.instrumentation.test.LibraryTestTrait
-
-class Aws1ClientTest1 extends AbstractAws1ClientTest implements LibraryTestTrait {
-  @Override
-  def configureClient(def client) {
-    client.withRequestHandlers(
-      AwsSdkTelemetry.builder(getOpenTelemetry())
-        .setCaptureExperimentalSpanAttributes(true)
-        .build()
-        .newRequestHandler())
-  }
-}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
similarity index 93%
rename from instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
index 9110a306c847..697f0e98c6eb 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1DynamoDbClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
@@ -10,7 +10,7 @@
 import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-class Aws1DynamoDbClientTest extends AbstractAws1DynamoDbClientTest {
+class DynamoDbClientTest extends AbstractDynamoDbClientTest {
   @RegisterExtension
   private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
 
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Ec2ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Ec2ClientTest.java
new file mode 100644
index 000000000000..bccd1a4d2eb6
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Ec2ClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class Ec2ClientTest extends AbstractEc2ClientTest {
+  @RegisterExtension
+  private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonEC2ClientBuilder configureClient(AmazonEC2ClientBuilder clientBuilder) {
+    return clientBuilder.withRequestHandlers(
+        AwsSdkTelemetry.builder(testing().getOpenTelemetry())
+            .setCaptureExperimentalSpanAttributes(true)
+            .build()
+            .newRequestHandler());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/KinesisClientTest.java
similarity index 93%
rename from instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/KinesisClientTest.java
index 7aa830a8d999..5837d70d2cb3 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1KinesisClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/KinesisClientTest.java
@@ -10,7 +10,7 @@
 import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-class Aws1KinesisClientTest extends AbstractAws1KinesisClientTest {
+class KinesisClientTest extends AbstractKinesisClientTest {
   @RegisterExtension
   private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
 
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/RdsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/RdsClientTest.java
new file mode 100644
index 000000000000..d4b86cdf1e93
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/RdsClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.rds.AmazonRDSClientBuilder;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class RdsClientTest extends AbstractRdsClientTest {
+  @RegisterExtension
+  private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonRDSClientBuilder configureClient(AmazonRDSClientBuilder clientBuilder) {
+    return clientBuilder.withRequestHandlers(
+        AwsSdkTelemetry.builder(testing().getOpenTelemetry())
+            .setCaptureExperimentalSpanAttributes(true)
+            .build()
+            .newRequestHandler());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/S3ClientTest.java
similarity index 94%
rename from instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1S3ClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/S3ClientTest.java
index 596bb39f6e58..f14c5d04584b 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/Aws1S3ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/S3ClientTest.java
@@ -10,7 +10,7 @@
 import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-class Aws1S3ClientTest extends AbstractAws1S3ClientTest {
+class S3ClientTest extends AbstractS3ClientTest {
   @RegisterExtension
   private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
 
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SnsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SnsClientTest.java
new file mode 100644
index 000000000000..fa6b765e8a59
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library/src/test/java/io/opentelemetry/instrumentation/awssdk/v1_11/SnsClientTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.sns.AmazonSNSClientBuilder;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class SnsClientTest extends AbstractSnsClientTest {
+  @RegisterExtension
+  private static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonSNSClientBuilder configureClient(AmazonSNSClientBuilder clientBuilder) {
+    return clientBuilder.withRequestHandlers(
+        AwsSdkTelemetry.builder(testing().getOpenTelemetry())
+            .setCaptureExperimentalSpanAttributes(true)
+            .build()
+            .newRequestHandler());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts b/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts
index b15ba0bd52a3..545f5dffce2c 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/build.gradle.kts
@@ -20,7 +20,5 @@ dependencies {
 
   implementation("com.google.guava:guava")
 
-  implementation("org.apache.groovy:groovy")
   implementation("io.opentelemetry:opentelemetry-api")
-  implementation("org.spockframework:spock-core")
 }
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
deleted file mode 100644
index c4c5bbb9f47a..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1ClientTest.groovy
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v1_11
-
-import com.amazonaws.AmazonClientException
-import com.amazonaws.ClientConfiguration
-import com.amazonaws.SDKGlobalConfiguration
-import com.amazonaws.SdkClientException
-import com.amazonaws.auth.AWSCredentialsProviderChain
-import com.amazonaws.auth.AWSStaticCredentialsProvider
-import com.amazonaws.auth.AnonymousAWSCredentials
-import com.amazonaws.auth.EnvironmentVariableCredentialsProvider
-import com.amazonaws.auth.InstanceProfileCredentialsProvider
-import com.amazonaws.auth.SystemPropertiesCredentialsProvider
-import com.amazonaws.auth.profile.ProfileCredentialsProvider
-import com.amazonaws.client.builder.AwsClientBuilder
-import com.amazonaws.retry.PredefinedRetryPolicies
-import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
-import com.amazonaws.services.dynamodbv2.model.CreateTableRequest
-import com.amazonaws.services.ec2.AmazonEC2ClientBuilder
-import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder
-import com.amazonaws.services.kinesis.model.DeleteStreamRequest
-import com.amazonaws.services.rds.AmazonRDSClientBuilder
-import com.amazonaws.services.rds.model.DeleteOptionGroupRequest
-import com.amazonaws.services.s3.AmazonS3Client
-import com.amazonaws.services.s3.AmazonS3ClientBuilder
-import com.amazonaws.services.sns.AmazonSNSClientBuilder
-import com.amazonaws.services.sns.model.PublishRequest
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.instrumentation.test.InstrumentationSpecification
-import io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes
-import io.opentelemetry.semconv.incubating.RpcIncubatingAttributes
-import io.opentelemetry.semconv.incubating.AwsIncubatingAttributes
-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 spock.lang.Unroll
-
-import java.time.Duration
-
-import static io.opentelemetry.api.trace.SpanKind.CLIENT
-import static io.opentelemetry.api.trace.SpanKind.PRODUCER
-import static io.opentelemetry.api.trace.StatusCode.ERROR
-import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
-
-abstract class AbstractAws1ClientTest extends InstrumentationSpecification {
-
-  abstract <T> T configureClient(T client)
-
-  static final CREDENTIALS_PROVIDER_CHAIN = new AWSCredentialsProviderChain(
-    new EnvironmentVariableCredentialsProvider(),
-    new SystemPropertiesCredentialsProvider(),
-    new ProfileCredentialsProvider(),
-    new InstanceProfileCredentialsProvider())
-
-  @Shared
-  def credentialsProvider = new AWSStaticCredentialsProvider(new AnonymousAWSCredentials())
-
-  @Shared
-  def server = new MockWebServerExtension()
-
-  @Shared
-  def endpoint
-
-  def setupSpec() {
-    System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key")
-    System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key")
-    server.start()
-    endpoint = new AwsClientBuilder.EndpointConfiguration("${server.httpUri()}", "us-west-2")
-  }
-
-  def cleanupSpec() {
-    System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY)
-    System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY)
-    server.stop()
-  }
-
-  def setup() {
-    server.beforeTestExecution(null)
-  }
-
-  @Unroll
-  def "send #operation request with mocked response"() {
-    setup:
-    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body))
-
-    when:
-    def client = configureClient(clientBuilder).withEndpointConfiguration(endpoint).withCredentials(credentialsProvider).build()
-    def response = call.call(client)
-
-    then:
-    response != null
-
-    client.requestHandler2s != null
-    client.requestHandler2s.find { it.getClass().getSimpleName() == "TracingRequestHandler" } != null
-
-    def hasRequestId = service in ["SNS", "RDS", "EC2"]
-
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "$service.$operation"
-          kind operation == "SendMessage" ? PRODUCER : 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"
-            "$AwsIncubatingAttributes.AWS_REQUEST_ID" hasRequestId ? String : null
-            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                  | clientBuilder                                                     | call                                                                            | additionalAttributes              | body
-    "S3"         | "CreateBucket"      | "PUT"  | "/testbucket/"        | AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true) | { c -> c.createBucket("testbucket") }                                           | ["aws.bucket.name": "testbucket"] | ""
-    "S3"         | "GetObject"         | "GET"  | "/someBucket/someKey" | AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true) | { c -> c.getObject("someBucket", "someKey") }                                   | ["aws.bucket.name": "someBucket"] | ""
-    "DynamoDBv2" | "CreateTable"       | "POST" | "/"                   | AmazonDynamoDBClientBuilder.standard()                            | { c -> c.createTable(new CreateTableRequest("sometable", null)) }               | ["aws.table.name": "sometable"]   | ""
-    "Kinesis"    | "DeleteStream"      | "POST" | "/"                   | AmazonKinesisClientBuilder.standard()                             | { c -> c.deleteStream(new DeleteStreamRequest().withStreamName("somestream")) } | ["aws.stream.name": "somestream"] | ""
-    // Some users may implicitly subclass the request object to mimic a fluent style
-    "Kinesis"    | "DeleteStream"      | "POST" | "/"                   | AmazonKinesisClientBuilder.standard()                             | { c ->
-      c.deleteStream(new DeleteStreamRequest() {
-        {
-          withStreamName("somestream")
-        }
-      })
-    }                                                                                                                                                                                                                         | ["aws.stream.name": "somestream"] | ""
-    "EC2"        | "AllocateAddress"   | "POST" | "/"                   | AmazonEC2ClientBuilder.standard()                                 | { c -> c.allocateAddress() }                                                    | [:]                               | """
-        <AllocateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
-           <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
-           <publicIp>192.0.2.1</publicIp>
-           <domain>standard</domain>
-        </AllocateAddressResponse>
-      """
-    "RDS"        | "DeleteOptionGroup" | "POST" | "/"                   | AmazonRDSClientBuilder.standard()                                 | { c -> c.deleteOptionGroup(new DeleteOptionGroupRequest()) }                    | [:]                               | """
-        <DeleteOptionGroupResponse xmlns="http://rds.amazonaws.com/doc/2014-09-01/">
-          <ResponseMetadata>
-            <RequestId>0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99</RequestId>
-          </ResponseMetadata>
-        </DeleteOptionGroupResponse>
-      """
-    "SNS"        | "Publish"           | "POST" | "d74b8436-ae13-5ab4-a9ff-ce54dfea72a0" | AmazonSNSClientBuilder.standard()                 | { c -> c.publish(new PublishRequest().withMessage("somemessage").withTopicArn("somearn")) } | ["$MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME": "somearn"] | """
-          <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>
-      """
-      "SNS"      | "Publish"            | "POST" | "d74b8436-ae13-5ab4-a9ff-ce54dfea72a0" | AmazonSNSClientBuilder.standard()                 | { c -> c.publish(new PublishRequest().withMessage("somemessage").withTargetArn("somearn")) } | ["$MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME": "somearn"] | """
-          <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>
-      """
-  }
-
-  def "send #operation request to closed port"() {
-    setup:
-    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body))
-
-    when:
-    def client = configureClient(clientBuilder)
-      .withCredentials(CREDENTIALS_PROVIDER_CHAIN)
-      .withClientConfiguration(new ClientConfiguration().withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0)))
-      .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://127.0.0.1:${UNUSABLE_PORT}", "us-east-1"))
-      .build()
-    call.call(client)
-
-    then:
-    thrown SdkClientException
-
-    assertTraces(1) {
-      trace(0, 1) {
-        span(0) {
-          name "$service.$operation"
-          kind CLIENT
-          status ERROR
-          errorEvent SdkClientException, ~/Unable to execute HTTP request/
-          hasNoParent()
-          attributes {
-            "$UrlAttributes.URL_FULL" "http://127.0.0.1:${UNUSABLE_PORT}"
-            "$HttpAttributes.HTTP_REQUEST_METHOD" "$method"
-            "$ServerAttributes.SERVER_ADDRESS" "127.0.0.1"
-            "$ServerAttributes.SERVER_PORT" 61
-            "$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
-            "$RpcIncubatingAttributes.RPC_SERVICE" { it.contains(service) }
-            "$RpcIncubatingAttributes.RPC_METHOD" "${operation}"
-            "aws.endpoint" "http://127.0.0.1:${UNUSABLE_PORT}"
-            "aws.agent" "java-aws-sdk"
-            for (def addedTag : additionalAttributes) {
-              "$addedTag.key" "$addedTag.value"
-            }
-            "$ErrorAttributes.ERROR_TYPE" SdkClientException.name
-          }
-        }
-      }
-    }
-
-    where:
-    service | operation   | method | url                  | call                                          | additionalAttributes              | body | clientBuilder
-    "S3"    | "GetObject" | "GET"  | "someBucket/someKey" | { c -> c.getObject("someBucket", "someKey") } | ["aws.bucket.name": "someBucket"] | ""   | AmazonS3ClientBuilder.standard()
-  }
-
-  // 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 = configureClient(AmazonS3ClientBuilder.standard())
-      .withClientConfiguration(new ClientConfiguration()
-        .withRequestTimeout(50 /* ms */)
-        .withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(1)))
-      .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("${server.httpUri()}", "us-east-1"))
-      .build()
-
-    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
-          try {
-            errorEvent AmazonClientException, ~/Unable to execute HTTP request/
-          } catch (AssertionError e) {
-            errorEvent SdkClientException, "Unable to execute HTTP request: Request did not complete before the request timeout configuration."
-          }
-          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" {it == SdkClientException.name || it == AmazonClientException.name }
-          }
-        }
-      }
-    }
-  }
-}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java
deleted file mode 100644
index a1540800006b..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1S3ClientTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v1_11;
-
-import com.amazonaws.services.s3.AmazonS3;
-import com.amazonaws.services.s3.AmazonS3ClientBuilder;
-import com.google.common.collect.ImmutableMap;
-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 java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-public abstract class AbstractAws1S3ClientTest extends AbstractAws1BaseClientTest {
-
-  public abstract AmazonS3ClientBuilder configureClient(AmazonS3ClientBuilder client);
-
-  @ParameterizedTest
-  @MethodSource("provideArguments")
-  public void testSendRequestWithMockedResponse(
-      String operation,
-      String method,
-      Function<AmazonS3, Object> call,
-      Map<String, String> additionalAttributes)
-      throws Exception {
-
-    AmazonS3ClientBuilder clientBuilder =
-        AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true);
-    AmazonS3 client =
-        configureClient(clientBuilder)
-            .withEndpointConfiguration(endpoint)
-            .withCredentials(credentialsProvider)
-            .build();
-
-    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
-
-    Object response = call.apply(client);
-    requestWithMockedResponse(response, client, "S3", operation, method, additionalAttributes);
-  }
-
-  private static Stream<Arguments> provideArguments() {
-    return Stream.of(
-        Arguments.of(
-            "CreateBucket",
-            "PUT",
-            (Function<AmazonS3, Object>) c -> c.createBucket("testbucket"),
-            ImmutableMap.of("aws.bucket.name", "testbucket")),
-        Arguments.of(
-            "GetObject",
-            "GET",
-            (Function<AmazonS3, Object>) c -> c.getObject("someBucket", "someKey"),
-            ImmutableMap.of("aws.bucket.name", "someBucket")));
-  }
-}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
similarity index 88%
rename from instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
index 68a1c06c3e91..cbf3e6778d11 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1BaseClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
@@ -38,9 +38,11 @@
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 
-public abstract class AbstractAws1BaseClientTest {
+public abstract class AbstractBaseAwsClientTest {
   protected abstract InstrumentationExtension testing();
 
+  protected abstract boolean hasRequestId();
+
   protected static MockWebServerExtension server = new MockWebServerExtension();
   protected static AwsClientBuilder.EndpointConfiguration endpoint;
   protected static final AWSStaticCredentialsProvider credentialsProvider =
@@ -62,23 +64,18 @@ public static void cleanUp() {
     server.stop();
   }
 
-  @SuppressWarnings("unchecked")
-  public void requestWithMockedResponse(
+  public void assertRequestWithMockedResponse(
       Object response,
       Object client,
       String service,
       String operation,
       String method,
       Map<String, String> additionalAttributes)
-      throws NoSuchFieldException, IllegalAccessException {
+      throws Exception {
 
     assertThat(response).isNotNull();
 
-    Field requestHandler2sField = AmazonWebServiceClient.class.getDeclaredField("requestHandler2s");
-    requestHandler2sField.setAccessible(true);
-    List<RequestHandler2> requestHandler2s =
-        (List<RequestHandler2>) requestHandler2sField.get(client);
-
+    List<RequestHandler2> requestHandler2s = extractRequestHandlers(client);
     assertThat(requestHandler2s).isNotNull();
     assertThat(
             requestHandler2s.stream()
@@ -104,6 +101,13 @@ public void requestWithMockedResponse(
                                   equalTo(RPC_METHOD, operation),
                                   equalTo(stringKey("aws.endpoint"), endpoint.getServiceEndpoint()),
                                   equalTo(stringKey("aws.agent"), "java-aws-sdk")));
+
+                      if (hasRequestId()) {
+                        attributes.add(
+                            satisfies(
+                                stringKey("aws.request_id"), v -> v.isInstanceOf(String.class)));
+                      }
+
                       additionalAttributes.forEach(
                           (k, v) -> attributes.add(equalTo(stringKey(k), v)));
 
@@ -113,4 +117,11 @@ public void requestWithMockedResponse(
                           .hasAttributesSatisfyingExactly(attributes);
                     }));
   }
+
+  @SuppressWarnings("unchecked")
+  protected List<RequestHandler2> extractRequestHandlers(Object client) throws Exception {
+    Field requestHandler2sField = AmazonWebServiceClient.class.getDeclaredField("requestHandler2s");
+    requestHandler2sField.setAccessible(true);
+    return (List<RequestHandler2>) requestHandler2sField.get(client);
+  }
 }
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractDynamoDbClientTest.java
similarity index 87%
rename from instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractDynamoDbClientTest.java
index 0d37a2302883..ba62420ae920 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1DynamoDbClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractDynamoDbClientTest.java
@@ -14,10 +14,15 @@
 import io.opentelemetry.testing.internal.armeria.common.MediaType;
 import org.junit.jupiter.api.Test;
 
-public abstract class AbstractAws1DynamoDbClientTest extends AbstractAws1BaseClientTest {
+public abstract class AbstractDynamoDbClientTest extends AbstractBaseAwsClientTest {
 
   public abstract AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder client);
 
+  @Override
+  protected boolean hasRequestId() {
+    return false;
+  }
+
   @Test
   public void sendRequestWithMockedResponse() throws Exception {
     AmazonDynamoDBClientBuilder clientBuilder = AmazonDynamoDBClientBuilder.standard();
@@ -30,7 +35,7 @@ public void sendRequestWithMockedResponse() throws Exception {
     server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
 
     Object response = client.createTable(new CreateTableRequest("sometable", null));
-    requestWithMockedResponse(
+    assertRequestWithMockedResponse(
         response,
         client,
         "DynamoDBv2",
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractEc2ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractEc2ClientTest.java
new file mode 100644
index 000000000000..7ba705fa20ec
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractEc2ClientTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.ec2.AmazonEC2;
+import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
+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 java.util.Collections;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractEc2ClientTest extends AbstractBaseAwsClientTest {
+
+  public abstract AmazonEC2ClientBuilder configureClient(AmazonEC2ClientBuilder client);
+
+  @Override
+  protected boolean hasRequestId() {
+    return true;
+  }
+
+  @Test
+  public void sendRequestWithMockedResponse() throws Exception {
+    AmazonEC2ClientBuilder clientBuilder = AmazonEC2ClientBuilder.standard();
+    AmazonEC2 client =
+        configureClient(clientBuilder)
+            .withEndpointConfiguration(endpoint)
+            .withCredentials(credentialsProvider)
+            .build();
+
+    String body =
+        "<AllocateAddressResponse xmlns=\"http://ec2.amazonaws.com/doc/2016-11-15/\">"
+            + "   <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>"
+            + "   <publicIp>192.0.2.1</publicIp>"
+            + "   <domain>standard</domain>"
+            + "</AllocateAddressResponse>";
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
+
+    Object response = client.allocateAddress();
+    assertRequestWithMockedResponse(
+        response, client, "EC2", "AllocateAddress", "POST", Collections.emptyMap());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractKinesisClientTest.java
similarity index 69%
rename from instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java
rename to instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractKinesisClientTest.java
index 44cab88fce58..372780343fc1 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractAws1KinesisClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractKinesisClientTest.java
@@ -19,19 +19,19 @@
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
-public abstract class AbstractAws1KinesisClientTest extends AbstractAws1BaseClientTest {
+public abstract class AbstractKinesisClientTest extends AbstractBaseAwsClientTest {
 
   public abstract AmazonKinesisClientBuilder configureClient(AmazonKinesisClientBuilder client);
 
+  @Override
+  protected boolean hasRequestId() {
+    return false;
+  }
+
   @ParameterizedTest
   @MethodSource("provideArguments")
   public void testSendRequestWithMockedResponse(
-      String operation,
-      String method,
-      Function<AmazonKinesis, Object> call,
-      Map<String, String> additionalAttributes)
-      throws Exception {
-
+      String operation, Function<AmazonKinesis, Object> call) throws Exception {
     AmazonKinesisClientBuilder clientBuilder = AmazonKinesisClientBuilder.standard();
 
     AmazonKinesis client =
@@ -42,30 +42,28 @@ public void testSendRequestWithMockedResponse(
 
     server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
 
+    Map<String, String> additionalAttributes = ImmutableMap.of("aws.stream.name", "somestream");
     Object response = call.apply(client);
-    requestWithMockedResponse(response, client, "Kinesis", operation, method, additionalAttributes);
+    assertRequestWithMockedResponse(
+        response, client, "Kinesis", operation, "POST", additionalAttributes);
   }
 
   private static Stream<Arguments> provideArguments() {
     return Stream.of(
         Arguments.of(
             "DeleteStream",
-            "POST",
             (Function<AmazonKinesis, Object>)
-                c -> c.deleteStream(new DeleteStreamRequest().withStreamName("somestream")),
-            ImmutableMap.of("aws.stream.name", "somestream")),
+                c -> c.deleteStream(new DeleteStreamRequest().withStreamName("somestream"))),
         // Some users may implicitly subclass the request object to mimic a fluent style
         Arguments.of(
-            "DeleteStream",
-            "POST",
+            "CustomDeleteStream",
             (Function<AmazonKinesis, Object>)
-                c ->
-                    c.deleteStream(
-                        new DeleteStreamRequest() {
-                          {
-                            withStreamName("somestream");
-                          }
-                        }),
-            ImmutableMap.of("aws.stream.name", "somestream")));
+                c -> c.deleteStream(new CustomDeleteStreamRequest("somestream"))));
+  }
+
+  public static class CustomDeleteStreamRequest extends DeleteStreamRequest {
+    public CustomDeleteStreamRequest(String streamName) {
+      withStreamName(streamName);
+    }
   }
 }
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractRdsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractRdsClientTest.java
new file mode 100644
index 000000000000..040812e57024
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractRdsClientTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.rds.AmazonRDS;
+import com.amazonaws.services.rds.AmazonRDSClientBuilder;
+import com.amazonaws.services.rds.model.DeleteOptionGroupRequest;
+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 java.util.Collections;
+import org.junit.jupiter.api.Test;
+
+public abstract class AbstractRdsClientTest extends AbstractBaseAwsClientTest {
+
+  public abstract AmazonRDSClientBuilder configureClient(AmazonRDSClientBuilder client);
+
+  @Override
+  protected boolean hasRequestId() {
+    return true;
+  }
+
+  @Test
+  public void sendRequestWithMockedResponse() throws Exception {
+    AmazonRDSClientBuilder clientBuilder = AmazonRDSClientBuilder.standard();
+    AmazonRDS client =
+        configureClient(clientBuilder)
+            .withEndpointConfiguration(endpoint)
+            .withCredentials(credentialsProvider)
+            .build();
+
+    String body =
+        "<DeleteOptionGroupResponse xmlns=\"http://rds.amazonaws.com/doc/2014-09-01/\">"
+            + "    <ResponseMetadata>"
+            + "        <RequestId>0ac9cda2-bbf4-11d3-f92b-31fa5e8dbc99</RequestId>"
+            + "    </ResponseMetadata>"
+            + "</DeleteOptionGroupResponse>";
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
+
+    Object response = client.deleteOptionGroup(new DeleteOptionGroupRequest());
+    assertRequestWithMockedResponse(
+        response, client, "RDS", "DeleteOptionGroup", "POST", Collections.emptyMap());
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
new file mode 100644
index 000000000000..e099f3923932
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import static io.opentelemetry.api.common.AttributeKey.stringKey;
+import static io.opentelemetry.api.trace.SpanKind.CLIENT;
+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.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 org.assertj.core.api.Assertions.catchThrowable;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+import com.amazonaws.AmazonClientException;
+import com.amazonaws.ClientConfiguration;
+import com.amazonaws.SdkClientException;
+import com.amazonaws.client.builder.AwsClientBuilder;
+import com.amazonaws.retry.PredefinedRetryPolicies;
+import com.amazonaws.services.s3.AmazonS3;
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import com.google.common.collect.ImmutableMap;
+import io.opentelemetry.api.trace.Span;
+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 java.time.Duration;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public abstract class AbstractS3ClientTest extends AbstractBaseAwsClientTest {
+
+  public abstract AmazonS3ClientBuilder configureClient(AmazonS3ClientBuilder client);
+
+  private final AmazonS3ClientBuilder clientBuilder =
+      AmazonS3ClientBuilder.standard().withPathStyleAccessEnabled(true);
+
+  @Override
+  protected boolean hasRequestId() {
+    return false;
+  }
+
+  @ParameterizedTest
+  @MethodSource("provideArguments")
+  public void testSendRequestWithMockedResponse(
+      String operation,
+      String method,
+      Function<AmazonS3, Object> call,
+      Map<String, String> additionalAttributes)
+      throws Exception {
+
+    AmazonS3 client =
+        configureClient(clientBuilder)
+            .withEndpointConfiguration(endpoint)
+            .withCredentials(credentialsProvider)
+            .build();
+
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
+
+    Object response = call.apply(client);
+    assertRequestWithMockedResponse(
+        response, client, "S3", operation, method, additionalAttributes);
+  }
+
+  private static Stream<Arguments> provideArguments() {
+    return Stream.of(
+        Arguments.of(
+            "CreateBucket",
+            "PUT",
+            (Function<AmazonS3, Object>) c -> c.createBucket("testbucket"),
+            ImmutableMap.of("aws.bucket.name", "testbucket")),
+        Arguments.of(
+            "GetObject",
+            "GET",
+            (Function<AmazonS3, Object>) c -> c.getObject("someBucket", "someKey"),
+            ImmutableMap.of("aws.bucket.name", "someBucket")));
+  }
+
+  @Test
+  public void testSendRequestToClosedPort() {
+    server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
+
+    AmazonS3 client =
+        configureClient(clientBuilder)
+            .withCredentials(credentialsProvider)
+            .withClientConfiguration(
+                new ClientConfiguration()
+                    .withRetryPolicy(
+                        PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0)))
+            .withEndpointConfiguration(
+                new AwsClientBuilder.EndpointConfiguration(
+                    "http://127.0.0.1:" + UNUSABLE_PORT, "us-east-1"))
+            .build();
+
+    Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
+    assertThat(caught).isInstanceOf(SdkClientException.class);
+
+    testing()
+        .waitAndAssertTraces(
+            trace ->
+                trace.hasSpansSatisfyingExactly(
+                    span ->
+                        span.hasName("S3.GetObject")
+                            .hasKind(CLIENT)
+                            .hasStatus(StatusData.error())
+                            .hasException(caught)
+                            .hasNoParent()
+                            .hasAttributesSatisfyingExactly(
+                                equalTo(URL_FULL, "http://127.0.0.1:" + UNUSABLE_PORT),
+                                equalTo(HTTP_REQUEST_METHOD, "GET"),
+                                equalTo(SERVER_ADDRESS, "127.0.0.1"),
+                                equalTo(SERVER_PORT, 61),
+                                equalTo(RPC_SYSTEM, "aws-api"),
+                                equalTo(RPC_SERVICE, "Amazon S3"),
+                                equalTo(RPC_METHOD, "GetObject"),
+                                equalTo(
+                                    stringKey("aws.endpoint"), "http://127.0.0.1:" + UNUSABLE_PORT),
+                                equalTo(stringKey("aws.agent"), "java-aws-sdk"),
+                                equalTo(stringKey("aws.bucket.name"), "someBucket"),
+                                equalTo(ERROR_TYPE, SdkClientException.class.getName()))));
+  }
+
+  @Test
+  void testTimeoutAndRetryErrorsNotCaptured() {
+    server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(5)));
+    server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(5)));
+    AmazonS3 client =
+        configureClient(AmazonS3ClientBuilder.standard())
+            .withClientConfiguration(
+                new ClientConfiguration()
+                    .withRequestTimeout(50 /* ms */)
+                    .withRetryPolicy(
+                        PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(1)))
+            .withEndpointConfiguration(
+                new AwsClientBuilder.EndpointConfiguration(
+                    server.httpUri().toString(), "us-east-1"))
+            .build();
+
+    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())
+                          .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"),
+                              satisfies(
+                                  ERROR_TYPE,
+                                  val ->
+                                      val.satisfiesAnyOf(
+                                          v ->
+                                              assertThat(v)
+                                                  .isEqualTo(SdkClientException.class.getName()),
+                                          v ->
+                                              assertThat(v)
+                                                  .isEqualTo(
+                                                      AmazonClientException.class.getName()))));
+
+                      try {
+                        span.hasException(
+                            new AmazonClientException("Unable to execute HTTP request"));
+                      } catch (AssertionError e) {
+                        span.hasException(
+                            new SdkClientException(
+                                "Unable to execute HTTP request: Request did not complete before the request timeout configuration."));
+                      }
+                    }));
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSnsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSnsClientTest.java
new file mode 100644
index 000000000000..4a728f645c55
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractSnsClientTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.instrumentation.awssdk.v1_11;
+
+import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME;
+
+import com.amazonaws.services.sns.AmazonSNS;
+import com.amazonaws.services.sns.AmazonSNSClientBuilder;
+import com.amazonaws.services.sns.model.PublishRequest;
+import com.google.common.collect.ImmutableMap;
+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 java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+public abstract class AbstractSnsClientTest extends AbstractBaseAwsClientTest {
+
+  public abstract AmazonSNSClientBuilder configureClient(AmazonSNSClientBuilder client);
+
+  @Override
+  protected boolean hasRequestId() {
+    return true;
+  }
+
+  @ParameterizedTest
+  @MethodSource("provideArguments")
+  public void testSendRequestWithMockedResponse(Function<AmazonSNS, Object> call) 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));
+
+    Map<String, String> additionalAttributes =
+        ImmutableMap.of(MESSAGING_DESTINATION_NAME.toString(), "somearn");
+
+    Object response = call.apply(client);
+    assertRequestWithMockedResponse(
+        response, client, "SNS", "Publish", "POST", additionalAttributes);
+  }
+
+  private static Stream<Arguments> provideArguments() {
+    return Stream.of(
+        Arguments.of(
+            (Function<AmazonSNS, Object>)
+                c ->
+                    c.publish(
+                        new PublishRequest().withMessage("somemessage").withTopicArn("somearn"))),
+        Arguments.of(
+            (Function<AmazonSNS, Object>)
+                c ->
+                    c.publish(
+                        new PublishRequest().withMessage("somemessage").withTargetArn("somearn"))));
+  }
+}

From 547b2950f5d66a84c6f13d118d334cbd61bba8ce Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Sun, 10 Nov 2024 08:09:35 -0500
Subject: [PATCH 4/8] autoconfigure

---
 .../awssdk/v1_11/DynamoDbClientTest.java      |  8 +++---
 .../v1_11/instrumentor/Aws1ClientTest.groovy  | 16 -----------
 .../awssdk/v1_11/DynamoDbClientTest.java      | 27 +++++++++++++++++++
 .../awssdk/v1_11/Ec2ClientTest.java           | 27 +++++++++++++++++++
 .../awssdk/v1_11/KinesisClientTest.java       | 27 +++++++++++++++++++
 .../awssdk/v1_11/RdsClientTest.java           | 27 +++++++++++++++++++
 .../awssdk/v1_11/S3ClientTest.java            | 27 +++++++++++++++++++
 .../awssdk/v1_11/SnsClientTest.java           | 27 +++++++++++++++++++
 8 files changed, 166 insertions(+), 20 deletions(-)
 delete mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/Aws1ClientTest.groovy
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
 create mode 100644 instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
index b5098b9c68e8..c4ebb6a07c79 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
@@ -16,12 +16,12 @@ class DynamoDbClientTest extends AbstractDynamoDbClientTest {
   static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
 
   @Override
-  public AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder client) {
-    return client;
+  protected InstrumentationExtension testing() {
+    return testing;
   }
 
   @Override
-  protected InstrumentationExtension testing() {
-    return testing;
+  public AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder clientBuilder) {
+    return clientBuilder;
   }
 }
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/Aws1ClientTest.groovy b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/Aws1ClientTest.groovy
deleted file mode 100644
index 24a138e80993..000000000000
--- a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/groovy/io/opentelemetry/instrumentation/awssdk/v1_11/instrumentor/Aws1ClientTest.groovy
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package io.opentelemetry.instrumentation.awssdk.v1_11.instrumentor
-
-import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractAws1ClientTest
-import io.opentelemetry.instrumentation.test.LibraryTestTrait
-
-class Aws1ClientTest extends AbstractAws1ClientTest implements LibraryTestTrait {
-  @Override
-  def configureClient(def client) {
-    return client
-  }
-}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
new file mode 100644
index 000000000000..9455ef45c01e
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/DynamoDbClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractDynamoDbClientTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class DynamoDbClientTest extends AbstractDynamoDbClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonDynamoDBClientBuilder configureClient(AmazonDynamoDBClientBuilder client) {
+    return client;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java
new file mode 100644
index 000000000000..6c4b6cacaab5
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/Ec2ClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractEc2ClientTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class Ec2ClientTest extends AbstractEc2ClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonEC2ClientBuilder configureClient(AmazonEC2ClientBuilder clientBuilder) {
+    return clientBuilder;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java
new file mode 100644
index 000000000000..696ae7997787
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/KinesisClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.kinesis.AmazonKinesisClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractKinesisClientTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class KinesisClientTest extends AbstractKinesisClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonKinesisClientBuilder configureClient(AmazonKinesisClientBuilder clientBuilder) {
+    return clientBuilder;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java
new file mode 100644
index 000000000000..07dbab293b00
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/RdsClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.rds.AmazonRDSClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractRdsClientTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class RdsClientTest extends AbstractRdsClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonRDSClientBuilder configureClient(AmazonRDSClientBuilder client) {
+    return client;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
new file mode 100644
index 000000000000..d16b91df6725
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.s3.AmazonS3ClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractS3ClientTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class S3ClientTest extends AbstractS3ClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonS3ClientBuilder configureClient(AmazonS3ClientBuilder client) {
+    return client;
+  }
+}
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java
new file mode 100644
index 000000000000..54227249a9ec
--- /dev/null
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/library-autoconfigure/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/SnsClientTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
+
+import com.amazonaws.services.sns.AmazonSNSClientBuilder;
+import io.opentelemetry.instrumentation.awssdk.v1_11.AbstractSnsClientTest;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.LibraryInstrumentationExtension;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class SnsClientTest extends AbstractSnsClientTest {
+  @RegisterExtension
+  static final InstrumentationExtension testing = LibraryInstrumentationExtension.create();
+
+  @Override
+  protected InstrumentationExtension testing() {
+    return testing;
+  }
+
+  @Override
+  public AmazonSNSClientBuilder configureClient(AmazonSNSClientBuilder clientBuilder) {
+    return clientBuilder;
+  }
+}

From 54f155fb109063317c2c21f40cb5e056e305a189 Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Mon, 11 Nov 2024 07:35:44 -0500
Subject: [PATCH 5/8] use different assertion

---
 .../javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java  | 4 ++--
 .../awssdk/v1_11/AbstractBaseAwsClientTest.java               | 2 +-
 .../instrumentation/awssdk/v1_11/AbstractS3ClientTest.java    | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
index bf97f9068c2a..0f9af7af4b95 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
@@ -15,8 +15,8 @@
 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 org.assertj.core.api.AssertionsForClassTypes.assertThat;
-import static org.assertj.core.api.AssertionsForClassTypes.catchThrowable;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
 
 import com.amazonaws.ClientConfiguration;
 import com.amazonaws.Request;
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
index cbf3e6778d11..b797d619548a 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
@@ -20,7 +20,7 @@
 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 org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
 
 import com.amazonaws.AmazonWebServiceClient;
 import com.amazonaws.SDKGlobalConfiguration;
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
index e099f3923932..363910a24b27 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
@@ -18,8 +18,8 @@
 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 org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.catchThrowable;
-import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
 
 import com.amazonaws.AmazonClientException;
 import com.amazonaws.ClientConfiguration;

From c258180dc0d6d22d6fc2b9dcfb0a1b8ebf5e7313 Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Mon, 11 Nov 2024 07:37:56 -0500
Subject: [PATCH 6/8] move deprecation warning to methods

---
 .../javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
index 0f9af7af4b95..fdcaab272098 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
@@ -42,7 +42,6 @@
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
-@SuppressWarnings("deprecation") // AmazonS3Client constructor is deprecated
 class S3ClientTest extends AbstractS3ClientTest {
   @RegisterExtension
   static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
@@ -82,6 +81,7 @@ private static Stream<Arguments> provideS3Arguments() {
 
   @ParameterizedTest
   @MethodSource("provideS3Arguments")
+  @SuppressWarnings("deprecation") // AmazonS3Client constructor is deprecated
   void testRequestHandlerIsHookedUpWithConstructor(boolean addHandler, int size) throws Exception {
     String accessKey = "asdf";
     String secretKey = "qwerty";
@@ -100,6 +100,7 @@ void testRequestHandlerIsHookedUpWithConstructor(boolean addHandler, int size) t
   }
 
   @Test
+  @SuppressWarnings("deprecation") // AmazonS3Client constructor is deprecated
   void testNaughtyRequestHandlerDoesntBreakTheTrace() {
     AmazonS3Client client = new AmazonS3Client(credentialsProvider);
     client.addRequestHandler(

From 70b434979192ef267dec4d860ddb257627e5e401 Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Mon, 11 Nov 2024 07:52:19 -0500
Subject: [PATCH 7/8] fix visibility of setup/cleanup methods, add beforeEach
 for resetting context

---
 .../awssdk/v1_11/AbstractBaseAwsClientTest.java          | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
index b797d619548a..c76bffa37562 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractBaseAwsClientTest.java
@@ -37,6 +37,7 @@
 import java.util.Map;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
 
 public abstract class AbstractBaseAwsClientTest {
   protected abstract InstrumentationExtension testing();
@@ -49,16 +50,20 @@ public abstract class AbstractBaseAwsClientTest {
       new AWSStaticCredentialsProvider(new AnonymousAWSCredentials());
 
   @BeforeAll
-  public static void setUp() {
+  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();
     endpoint = new AwsClientBuilder.EndpointConfiguration(server.httpUri().toString(), "us-west-2");
+  }
+
+  @BeforeEach
+  void reset() {
     server.beforeTestExecution(null);
   }
 
   @AfterAll
-  public static void cleanUp() {
+  static void cleanUp() {
     System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY);
     System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY);
     server.stop();

From ba5e621c257693a3df99f9a5654d3b5389014dfd Mon Sep 17 00:00:00 2001
From: Jay DeLuca <jaydeluca4@gmail.com>
Date: Mon, 11 Nov 2024 16:58:15 -0500
Subject: [PATCH 8/8] remove unneeded vars, make s3 exception more specific

---
 .../awssdk/v1_11/S3ClientTest.java            |  4 +-
 .../awssdk/v1_11/AbstractS3ClientTest.java    | 58 +++++++------------
 2 files changed, 21 insertions(+), 41 deletions(-)

diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
index fdcaab272098..fa8bd71d66be 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/awssdk/v1_11/S3ClientTest.java
@@ -83,9 +83,7 @@ private static Stream<Arguments> provideS3Arguments() {
   @MethodSource("provideS3Arguments")
   @SuppressWarnings("deprecation") // AmazonS3Client constructor is deprecated
   void testRequestHandlerIsHookedUpWithConstructor(boolean addHandler, int size) throws Exception {
-    String accessKey = "asdf";
-    String secretKey = "qwerty";
-    BasicAWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
+    BasicAWSCredentials credentials = new BasicAWSCredentials("asdf", "qwerty");
     AmazonS3Client client = new AmazonS3Client(credentials);
     if (addHandler) {
       client.addRequestHandler(new RequestHandler2() {});
diff --git a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
index 363910a24b27..37333d093464 100644
--- a/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
+++ b/instrumentation/aws-sdk/aws-sdk-1.11/testing/src/main/java/io/opentelemetry/instrumentation/awssdk/v1_11/AbstractS3ClientTest.java
@@ -9,7 +9,6 @@
 import static io.opentelemetry.api.trace.SpanKind.CLIENT;
 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.ServerAttributes.SERVER_ADDRESS;
@@ -159,42 +158,25 @@ void testTimeoutAndRetryErrorsNotCaptured() {
         .waitAndAssertTraces(
             trace ->
                 trace.hasSpansSatisfyingExactly(
-                    span -> {
-                      span.hasName("S3.GetObject")
-                          .hasKind(CLIENT)
-                          .hasStatus(StatusData.error())
-                          .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"),
-                              satisfies(
-                                  ERROR_TYPE,
-                                  val ->
-                                      val.satisfiesAnyOf(
-                                          v ->
-                                              assertThat(v)
-                                                  .isEqualTo(SdkClientException.class.getName()),
-                                          v ->
-                                              assertThat(v)
-                                                  .isEqualTo(
-                                                      AmazonClientException.class.getName()))));
-
-                      try {
-                        span.hasException(
-                            new AmazonClientException("Unable to execute HTTP request"));
-                      } catch (AssertionError e) {
-                        span.hasException(
-                            new SdkClientException(
-                                "Unable to execute HTTP request: Request did not complete before the request timeout configuration."));
-                      }
-                    }));
+                    span ->
+                        span.hasName("S3.GetObject")
+                            .hasKind(CLIENT)
+                            .hasStatus(StatusData.error())
+                            .hasNoParent()
+                            .hasException(
+                                new SdkClientException(
+                                    "Unable to execute HTTP request: Request did not complete before the request timeout configuration."))
+                            .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, SdkClientException.class.getName()))));
   }
 }