Convert aws sdk tests for before 1.11.106 from groovy to java (#12755)

This commit is contained in:
Jay DeLuca 2024-11-20 18:16:05 -05:00 committed by GitHub
parent ed8d860d83
commit bd49adf03e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 371 additions and 297 deletions

View File

@ -1,297 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import com.amazonaws.AmazonClientException
import com.amazonaws.ClientConfiguration
import com.amazonaws.Request
import com.amazonaws.SDKGlobalConfiguration
import com.amazonaws.auth.AWSCredentialsProviderChain
import com.amazonaws.auth.BasicAWSCredentials
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider
import com.amazonaws.auth.InstanceProfileCredentialsProvider
import com.amazonaws.auth.NoOpSigner
import com.amazonaws.auth.SignerFactory
import com.amazonaws.auth.SystemPropertiesCredentialsProvider
import com.amazonaws.auth.profile.ProfileCredentialsProvider
import com.amazonaws.handlers.RequestHandler2
import com.amazonaws.retry.PredefinedRetryPolicies
import com.amazonaws.services.ec2.AmazonEC2Client
import com.amazonaws.services.rds.AmazonRDSClient
import com.amazonaws.services.rds.model.DeleteOptionGroupRequest
import com.amazonaws.services.s3.AmazonS3Client
import com.amazonaws.services.s3.S3ClientOptions
import io.opentelemetry.api.trace.Span
import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
import io.opentelemetry.semconv.incubating.RpcIncubatingAttributes
import io.opentelemetry.semconv.ServerAttributes
import io.opentelemetry.semconv.ErrorAttributes
import io.opentelemetry.semconv.HttpAttributes
import io.opentelemetry.semconv.NetworkAttributes
import io.opentelemetry.semconv.UrlAttributes
import io.opentelemetry.testing.internal.armeria.common.HttpResponse
import io.opentelemetry.testing.internal.armeria.common.HttpStatus
import io.opentelemetry.testing.internal.armeria.common.MediaType
import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension
import spock.lang.Shared
import java.time.Duration
import static io.opentelemetry.api.trace.SpanKind.CLIENT
import static io.opentelemetry.api.trace.StatusCode.ERROR
import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
class Aws0ClientTest extends AgentInstrumentationSpecification {
private static final CREDENTIALS_PROVIDER_CHAIN = new AWSCredentialsProviderChain(
new EnvironmentVariableCredentialsProvider(),
new SystemPropertiesCredentialsProvider(),
new ProfileCredentialsProvider(),
new InstanceProfileCredentialsProvider())
@Shared
def server = new MockWebServerExtension()
def setupSpec() {
System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key")
System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key")
server.start()
}
def cleanupSpec() {
System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY)
System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY)
server.stop()
}
def setup() {
server.beforeTestExecution(null)
}
def "request handler is hooked up with constructor"() {
setup:
String accessKey = "asdf"
String secretKey = "qwerty"
def credentials = new BasicAWSCredentials(accessKey, secretKey)
def client = new AmazonS3Client(credentials)
if (addHandler) {
client.addRequestHandler(new RequestHandler2() {})
}
expect:
client.requestHandler2s != null
client.requestHandler2s.size() == size
client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler"
where:
addHandler | size
true | 2
false | 1
}
def "send #operation request with mocked response"() {
setup:
server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body))
when:
def response = call.call(client)
then:
response != null
client.requestHandler2s != null
client.requestHandler2s.size() == handlerCount
client.requestHandler2s.get(0).getClass().getSimpleName() == "TracingRequestHandler"
assertTraces(1) {
trace(0, 1) {
span(0) {
name "$service.$operation"
kind CLIENT
hasNoParent()
attributes {
"$UrlAttributes.URL_FULL" "${server.httpUri()}"
"$HttpAttributes.HTTP_REQUEST_METHOD" "$method"
"$HttpAttributes.HTTP_RESPONSE_STATUS_CODE" 200
"$NetworkAttributes.NETWORK_PROTOCOL_VERSION" "1.1"
"$ServerAttributes.SERVER_PORT" server.httpPort()
"$ServerAttributes.SERVER_ADDRESS" "127.0.0.1"
"$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
"$RpcIncubatingAttributes.RPC_SERVICE" { it.contains(service) }
"$RpcIncubatingAttributes.RPC_METHOD" "${operation}"
"aws.endpoint" "${server.httpUri()}"
"aws.agent" "java-aws-sdk"
for (def addedTag : additionalAttributes) {
"$addedTag.key" "$addedTag.value"
}
}
}
}
}
def request = server.takeRequest()
request.request().headers().get("X-Amzn-Trace-Id") != null
request.request().headers().get("traceparent") == null
where:
service | operation | method | path | handlerCount | client | additionalAttributes | call | body
"S3" | "CreateBucket" | "PUT" | "/testbucket/" | 1 | new AmazonS3Client().withEndpoint("${server.httpUri()}") | ["aws.bucket.name": "testbucket"] | { c -> c.setS3ClientOptions(S3ClientOptions.builder().setPathStyleAccess(true).build()); c.createBucket("testbucket") } | ""
"S3" | "GetObject" | "GET" | "/someBucket/someKey" | 1 | new AmazonS3Client().withEndpoint("${server.httpUri()}") | ["aws.bucket.name": "someBucket"] | { c -> c.getObject("someBucket", "someKey") } | ""
"EC2" | "AllocateAddress" | "POST" | "/" | 4 | new AmazonEC2Client().withEndpoint("${server.httpUri()}") | [:] | { c -> c.allocateAddress() } | """
<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" | "/" | 1 | new AmazonRDSClient().withEndpoint("${server.httpUri()}") | [:] | { 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>
"""
}
def "send #operation request to closed port"() {
setup:
server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body))
when:
call.call(client)
then:
thrown AmazonClientException
assertTraces(1) {
trace(0, 1) {
span(0) {
name "$service.$operation"
kind CLIENT
status ERROR
errorEvent AmazonClientException, ~/Unable to execute HTTP request/
hasNoParent()
attributes {
"$UrlAttributes.URL_FULL" "http://localhost:${UNUSABLE_PORT}"
"$HttpAttributes.HTTP_REQUEST_METHOD" "$method"
"$ServerAttributes.SERVER_PORT" 61
"$ServerAttributes.SERVER_ADDRESS" "localhost"
"$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
"$RpcIncubatingAttributes.RPC_SERVICE" { it.contains(service) }
"$RpcIncubatingAttributes.RPC_METHOD" "${operation}"
"aws.endpoint" "http://localhost:${UNUSABLE_PORT}"
"aws.agent" "java-aws-sdk"
for (def addedTag : additionalAttributes) {
"$addedTag.key" "$addedTag.value"
}
"$ErrorAttributes.ERROR_TYPE" AmazonClientException.name
}
}
}
}
where:
service | operation | method | url | call | additionalAttributes | body | client
"S3" | "GetObject" | "GET" | "someBucket/someKey" | { client -> client.getObject("someBucket", "someKey") } | ["aws.bucket.name": "someBucket"] | "" | new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN, new ClientConfiguration().withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0))).withEndpoint("http://localhost:${UNUSABLE_PORT}")
}
def "naughty request handler doesn't break the trace"() {
setup:
def client = new AmazonS3Client(CREDENTIALS_PROVIDER_CHAIN)
client.addRequestHandler(new RequestHandler2() {
void beforeRequest(Request<?> request) {
throw new IllegalStateException("bad handler")
}
})
when:
client.getObject("someBucket", "someKey")
then:
!Span.current().getSpanContext().isValid()
thrown IllegalStateException
assertTraces(1) {
trace(0, 1) {
span(0) {
name "S3.GetObject"
kind CLIENT
status ERROR
errorEvent IllegalStateException, "bad handler"
hasNoParent()
attributes {
"$UrlAttributes.URL_FULL" "https://s3.amazonaws.com"
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
"$ServerAttributes.SERVER_ADDRESS" "s3.amazonaws.com"
"$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
"$RpcIncubatingAttributes.RPC_SERVICE" "Amazon S3"
"$RpcIncubatingAttributes.RPC_METHOD" "GetObject"
"aws.endpoint" "https://s3.amazonaws.com"
"aws.agent" "java-aws-sdk"
"aws.bucket.name" "someBucket"
"$ErrorAttributes.ERROR_TYPE" IllegalStateException.name
}
}
}
}
}
// TODO(anuraaga): Add events for retries.
def "timeout and retry errors not captured"() {
setup:
// One retry so two requests.
server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofMillis(5000)))
server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofMillis(5000)))
AmazonS3Client client = new AmazonS3Client(new ClientConfiguration()
.withRequestTimeout(50 /* ms */)
.withRetryPolicy(PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(1)))
.withEndpoint("${server.httpUri()}")
when:
client.getObject("someBucket", "someKey")
then:
!Span.current().getSpanContext().isValid()
thrown AmazonClientException
assertTraces(1) {
trace(0, 1) {
span(0) {
name "S3.GetObject"
kind CLIENT
status ERROR
errorEvent AmazonClientException, ~/Unable to execute HTTP request/
hasNoParent()
attributes {
"$UrlAttributes.URL_FULL" "${server.httpUri()}"
"$HttpAttributes.HTTP_REQUEST_METHOD" "GET"
"$ServerAttributes.SERVER_PORT" server.httpPort()
"$ServerAttributes.SERVER_ADDRESS" "127.0.0.1"
"$RpcIncubatingAttributes.RPC_SYSTEM" "aws-api"
"$RpcIncubatingAttributes.RPC_SERVICE" "Amazon S3"
"$RpcIncubatingAttributes.RPC_METHOD" "GetObject"
"aws.endpoint" "${server.httpUri()}"
"aws.agent" "java-aws-sdk"
"aws.bucket.name" "someBucket"
"$ErrorAttributes.ERROR_TYPE" AmazonClientException.name
}
}
}
}
}
def "calling generatePresignedUrl does not leak context"() {
setup:
SignerFactory.registerSigner("noop", NoOpSigner)
def client = new AmazonS3Client(new ClientConfiguration().withSignerOverride("noop"))
.withEndpoint("${server.httpUri()}")
when:
client.generatePresignedUrl("someBucket", "someKey", new Date())
then:
// expecting no active span after call to generatePresignedUrl
!Span.current().getSpanContext().isValid()
}
}

View File

@ -0,0 +1,371 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.awssdk.v1_11;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.api.trace.SpanKind.CLIENT;
import static io.opentelemetry.api.trace.SpanKind.PRODUCER;
import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_RESPONSE_STATUS_CODE;
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PROTOCOL_VERSION;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_METHOD;
import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_SERVICE;
import static io.opentelemetry.semconv.incubating.RpcIncubatingAttributes.RPC_SYSTEM;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyMap;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonWebServiceClient;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Request;
import com.amazonaws.SDKGlobalConfiguration;
import com.amazonaws.auth.AWSCredentialsProviderChain;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
import com.amazonaws.auth.InstanceProfileCredentialsProvider;
import com.amazonaws.auth.NoOpSigner;
import com.amazonaws.auth.SignerFactory;
import com.amazonaws.auth.SystemPropertiesCredentialsProvider;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.handlers.RequestHandler2;
import com.amazonaws.retry.PredefinedRetryPolicies;
import com.amazonaws.services.ec2.AmazonEC2Client;
import com.amazonaws.services.rds.AmazonRDSClient;
import com.amazonaws.services.rds.model.DeleteOptionGroupRequest;
import com.amazonaws.services.s3.AmazonS3Client;
import com.google.common.collect.ImmutableMap;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
import io.opentelemetry.sdk.trace.data.StatusData;
import io.opentelemetry.testing.internal.armeria.common.HttpResponse;
import io.opentelemetry.testing.internal.armeria.common.HttpStatus;
import io.opentelemetry.testing.internal.armeria.common.MediaType;
import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.MockWebServerExtension;
import io.opentelemetry.testing.internal.armeria.testing.junit5.server.mock.RecordedRequest;
import java.lang.reflect.Field;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
class Aws0ClientTest {
@RegisterExtension
private static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
private static final AWSCredentialsProviderChain credentialsProvider =
new AWSCredentialsProviderChain(
new EnvironmentVariableCredentialsProvider(),
new SystemPropertiesCredentialsProvider(),
new ProfileCredentialsProvider(),
new InstanceProfileCredentialsProvider());
private static final MockWebServerExtension server = new MockWebServerExtension();
@BeforeAll
static void setUp() {
System.setProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY, "my-access-key");
System.setProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY, "my-secret-key");
server.start();
}
@BeforeEach
void reset() {
server.beforeTestExecution(null);
}
@AfterAll
static void cleanUp() {
System.clearProperty(SDKGlobalConfiguration.ACCESS_KEY_SYSTEM_PROPERTY);
System.clearProperty(SDKGlobalConfiguration.SECRET_KEY_SYSTEM_PROPERTY);
server.stop();
}
private static Stream<Arguments> provideArguments() {
return Stream.of(Arguments.of(true, 2), Arguments.of(false, 1));
}
@ParameterizedTest
@SuppressWarnings("unchecked")
@MethodSource("provideArguments")
void testRequestHandlerIsHookedUpWithConstructor(boolean addHandler, int size) throws Exception {
BasicAWSCredentials credentials = new BasicAWSCredentials("asdf", "qwerty");
AmazonS3Client client = new AmazonS3Client(credentials);
if (addHandler) {
client.addRequestHandler(new RequestHandler2() {});
}
List<RequestHandler2> requestHandler2s = extractRequestHandlers(client);
assertThat(requestHandler2s).isNotNull();
assertThat(requestHandler2s.size()).isEqualTo(size);
assertThat(requestHandler2s.stream().findFirst().get().getClass().getSimpleName())
.isEqualTo("TracingRequestHandler");
}
private static Stream<Arguments> provideSendRequestArguments() {
return Stream.of(
Arguments.of(
new AmazonS3Client().withEndpoint(server.httpUri().toString()),
"S3",
"CreateBucket",
"PUT",
1,
(Function<AmazonS3Client, Object>) c -> c.createBucket("testbucket"),
ImmutableMap.of("aws.bucket.name", "testbucket"),
""),
Arguments.of(
new AmazonS3Client().withEndpoint(server.httpUri().toString()),
"S3",
"GetObject",
"GET",
1,
(Function<AmazonS3Client, Object>) c -> c.getObject("someBucket", "someKey"),
ImmutableMap.of("aws.bucket.name", "someBucket"),
""),
Arguments.of(
new AmazonEC2Client().withEndpoint(server.httpUri().toString()),
"EC2",
"AllocateAddress",
"POST",
4,
(Function<AmazonEC2Client, Object>) AmazonEC2Client::allocateAddress,
emptyMap(),
"<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>"),
Arguments.of(
new AmazonRDSClient().withEndpoint(server.httpUri().toString()),
"RDS",
"DeleteOptionGroup",
"POST",
1,
(Function<AmazonRDSClient, Object>)
c -> c.deleteOptionGroup(new DeleteOptionGroupRequest()),
emptyMap(),
"<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>"));
}
@ParameterizedTest
@MethodSource("provideSendRequestArguments")
@SuppressWarnings("unchecked")
void testSendRequestWithMockedResponse(
AmazonWebServiceClient client,
String service,
String operation,
String method,
int handlerCount,
Function<AmazonWebServiceClient, Object> call,
Map<String, String> additionalAttributes,
String body)
throws Exception {
server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, body));
Object response = call.apply(client);
assertThat(response).isNotNull();
List<RequestHandler2> requestHandler2s = extractRequestHandlers(client);
assertThat(requestHandler2s).isNotNull();
assertThat(requestHandler2s.size()).isEqualTo(handlerCount);
assertThat(requestHandler2s.stream().findFirst().get().getClass().getSimpleName())
.isEqualTo("TracingRequestHandler");
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> {
List<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"), server.httpUri().toString()),
equalTo(stringKey("aws.agent"), "java-aws-sdk")));
additionalAttributes.forEach((k, v) -> attributes.add(equalTo(stringKey(k), v)));
span.hasName(service + "." + operation)
.hasKind(operation.equals("SendMessage") ? PRODUCER : CLIENT)
.hasNoParent()
.hasAttributesSatisfyingExactly(attributes);
}));
RecordedRequest request = server.takeRequest();
assertThat(request.request().headers().get("X-Amzn-Trace-Id")).isNotNull();
assertThat(request.request().headers().get("traceparent")).isNull();
}
@Test
void testSendS3RequestToClosedPort() {
AmazonS3Client client =
new AmazonS3Client(
credentialsProvider,
new ClientConfiguration()
.withRetryPolicy(
PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(0)))
.withEndpoint("http://localhost:" + UNUSABLE_PORT);
server.enqueue(HttpResponse.of(HttpStatus.OK, MediaType.PLAIN_TEXT_UTF_8, ""));
Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
assertThat(caught).isInstanceOf(AmazonClientException.class);
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("S3.GetObject")
.hasKind(CLIENT)
.hasStatus(StatusData.error())
.hasException(caught)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(URL_FULL, "http://localhost:" + UNUSABLE_PORT),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, "localhost"),
equalTo(SERVER_PORT, 61),
equalTo(RPC_SYSTEM, "aws-api"),
equalTo(RPC_SERVICE, "Amazon S3"),
equalTo(RPC_METHOD, "GetObject"),
equalTo(stringKey("aws.endpoint"), "http://localhost:" + UNUSABLE_PORT),
equalTo(stringKey("aws.agent"), "java-aws-sdk"),
equalTo(stringKey("aws.bucket.name"), "someBucket"),
equalTo(ERROR_TYPE, AmazonClientException.class.getName()))));
}
@Test
void testNaughtyRequestHandlerDoesntBreakTheTrace() {
AmazonS3Client client = new AmazonS3Client(credentialsProvider);
client.addRequestHandler(
new RequestHandler2() {
@Override
public void beforeRequest(Request<?> request) {
throw new IllegalStateException("bad handler");
}
});
Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
assertThat(caught).isInstanceOf(IllegalStateException.class);
assertThat(Span.current().getSpanContext().isValid()).isFalse();
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("S3.GetObject")
.hasKind(CLIENT)
.hasStatus(StatusData.error())
.hasException(caught)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(URL_FULL, "https://s3.amazonaws.com"),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_ADDRESS, "s3.amazonaws.com"),
equalTo(RPC_SYSTEM, "aws-api"),
equalTo(RPC_SERVICE, "Amazon S3"),
equalTo(RPC_METHOD, "GetObject"),
equalTo(stringKey("aws.endpoint"), "https://s3.amazonaws.com"),
equalTo(stringKey("aws.agent"), "java-aws-sdk"),
equalTo(stringKey("aws.bucket.name"), "someBucket"),
equalTo(ERROR_TYPE, IllegalStateException.class.getName()))));
}
@Test
void testTimeoutAndRetryErrorsAreNotCaptured() {
server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(5)));
server.enqueue(HttpResponse.delayed(HttpResponse.of(HttpStatus.OK), Duration.ofSeconds(5)));
AmazonS3Client client =
new AmazonS3Client(
new ClientConfiguration()
.withRequestTimeout(50 /* ms */)
.withRetryPolicy(
PredefinedRetryPolicies.getDefaultRetryPolicyWithCustomMaxRetries(1)))
.withEndpoint(server.httpUri().toString());
Throwable caught = catchThrowable(() -> client.getObject("someBucket", "someKey"));
assertThat(caught).isInstanceOf(AmazonClientException.class);
assertThat(Span.current().getSpanContext().isValid()).isFalse();
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span ->
span.hasName("S3.GetObject")
.hasKind(CLIENT)
.hasStatus(StatusData.error())
.hasException(caught)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(URL_FULL, server.httpUri().toString()),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(SERVER_PORT, server.httpPort()),
equalTo(SERVER_ADDRESS, "127.0.0.1"),
equalTo(RPC_SYSTEM, "aws-api"),
equalTo(RPC_SERVICE, "Amazon S3"),
equalTo(RPC_METHOD, "GetObject"),
equalTo(stringKey("aws.endpoint"), server.httpUri().toString()),
equalTo(stringKey("aws.agent"), "java-aws-sdk"),
equalTo(stringKey("aws.bucket.name"), "someBucket"),
equalTo(ERROR_TYPE, AmazonClientException.class.getName()))));
}
@Test
void testCallingGeneratePresignedUrlDoesNotLeakContext() {
SignerFactory.registerSigner("noop", NoOpSigner.class);
AmazonS3Client client =
new AmazonS3Client(new ClientConfiguration().withSignerOverride("noop"))
.withEndpoint(server.httpUri().toString());
client.generatePresignedUrl("someBucket", "someKey", new Date());
assertThat(Span.current().getSpanContext().isValid()).isFalse();
}
@SuppressWarnings("unchecked")
private static List<RequestHandler2> extractRequestHandlers(Object client) throws Exception {
Field requestHandler2sField = AmazonWebServiceClient.class.getDeclaredField("requestHandler2s");
requestHandler2sField.setAccessible(true);
return (List<RequestHandler2>) requestHandler2sField.get(client);
}
}