From 2453fb797451e39e0f2b8e79151649605971257e Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 11:19:56 -0700 Subject: [PATCH 1/9] Implementing ProtocolRpcV2Cbor FeatureID --- .../poet/client/specs/JsonProtocolSpec.java | 61 +++++++++- .../useragent/BusinessMetricFeatureId.java | 3 +- .../tests/ProtocolRpcV2CborUserAgentTest.java | 107 ++++++++++++++++++ 3 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java index 8e1afb25e8e0..8f0fe2210f8e 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java @@ -25,10 +25,14 @@ import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeVariableName; import com.squareup.javapoet.WildcardTypeName; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; import java.util.function.Function; import javax.lang.model.element.Modifier; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.eventstream.EventStreamAsyncResponseTransformer; import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionPojoSupplier; import software.amazon.awssdk.awscore.eventstream.RestEventStreamAsyncResponseTransformer; @@ -48,6 +52,7 @@ import software.amazon.awssdk.codegen.poet.client.traits.RequestCompressionTrait; import software.amazon.awssdk.codegen.poet.eventstream.EventStreamUtils; import software.amazon.awssdk.codegen.poet.model.EventStreamSpecHelper; +import software.amazon.awssdk.core.ApiName; import software.amazon.awssdk.core.SdkPojoBuilder; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.async.AsyncRequestBody; @@ -56,6 +61,7 @@ import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.HttpResponseHandler; import software.amazon.awssdk.core.protocol.VoidSdkResponse; +import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.protocols.cbor.AwsCborProtocolFactory; import software.amazon.awssdk.protocols.core.ExceptionMetadata; import software.amazon.awssdk.protocols.json.AwsJsonProtocol; @@ -224,7 +230,10 @@ public CodeBlock executionHandler(OperationModel opModel) { .add(discoveredEndpoint(opModel)) .add(credentialType(opModel, model)) .add(".withRequestConfiguration(clientConfiguration)") - .add(".withInput($L)\n", opModel.getInput().getVariableName()) + .add(".withInput($L)\n", + model.getMetadata().isRpcV2CborProtocol() ? + "applyRpcV2CborUserAgent(" + opModel.getInput().getVariableName() + ")" : + opModel.getInput().getVariableName()) .add(".withMetricCollector(apiCallMetricCollector)") .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -320,7 +329,10 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper builder.add(RequestCompressionTrait.create(opModel, model)) .add(".withInput($L)$L)", - opModel.getInput().getVariableName(), asyncResponseTransformerVariable(isStreaming, isRestJson, opModel)) + intermediateModel.getMetadata().isRpcV2CborProtocol() ? + "applyRpcV2CborUserAgent(" + opModel.getInput().getVariableName() + ")" : + opModel.getInput().getVariableName(), + asyncResponseTransformerVariable(isStreaming, isRestJson, opModel)) .add(opModel.getEndpointDiscovery() != null ? ");" : ";"); if (opModel.hasStreamingOutput()) { @@ -568,4 +580,49 @@ private String protocolFactoryLiteral(IntermediateModel model, OperationModel op private boolean isRestJson(IntermediateModel model) { return model.getMetadata().getProtocol() == Protocol.REST_JSON; } + + @Override + public List additionalMethods() { + List methods = new ArrayList<>(); + + applyRpcV2CborUserAgentMethod().ifPresent(methods::add); + + return methods; + } + + private Optional applyRpcV2CborUserAgentMethod() { + if (!model.getMetadata().isRpcV2CborProtocol()) { + return Optional.empty(); + } + + TypeVariableName typeVariableName = + TypeVariableName.get("T", poetExtensions.getModelClass(model.getSdkRequestBaseClassName())); + + ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName + .get(ClassName.get(Consumer.class), ClassName.get(AwsRequestOverrideConfiguration.Builder.class)); + + CodeBlock codeBlock = CodeBlock.builder() + .addStatement("$T userAgentApplier = b -> " + + "b.addApiName($T.builder().name($S).version($S).build())", + parameterizedTypeName, ApiName.class, + "sdk-metrics", + BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value()) + .addStatement("$T overrideConfiguration =\n" + + " request.overrideConfiguration().map(c -> c.toBuilder()" + + ".applyMutation(userAgentApplier).build())\n" + + " .orElse((AwsRequestOverrideConfiguration.builder()" + + ".applyMutation(userAgentApplier).build()))", + AwsRequestOverrideConfiguration.class) + .addStatement("return (T) request.toBuilder().overrideConfiguration(overrideConfiguration)" + + ".build()") + .build(); + + return Optional.of(MethodSpec.methodBuilder("applyRpcV2CborUserAgent") + .addModifiers(Modifier.PRIVATE, Modifier.STATIC) + .addParameter(typeVariableName, "request") + .addTypeVariable(typeVariableName) + .addCode(codeBlock) + .returns(typeVariableName) + .build()); + } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/useragent/BusinessMetricFeatureId.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/useragent/BusinessMetricFeatureId.java index 884f57bf5691..df481f975d50 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/useragent/BusinessMetricFeatureId.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/useragent/BusinessMetricFeatureId.java @@ -22,7 +22,7 @@ /** * An enum class representing a short form of identity providers to record in the UA string. * - * Unimplemented metrics: I,J,K,M,O,S,U-c + * Unimplemented metrics: I,J,K,O,S,U-c * Unsupported metrics (these will never be added): A,H */ @SdkProtectedApi @@ -35,6 +35,7 @@ public enum BusinessMetricFeatureId { RETRY_MODE_ADAPTIVE("F"), S3_TRANSFER("G"), GZIP_REQUEST_COMPRESSION("L"), //TODO(metrics): Not working, compression happens after header + PROTOCOL_RPC_V2_CBOR("M"), ENDPOINT_OVERRIDE("N"), ACCOUNT_ID_MODE_PREFERRED("P"), ACCOUNT_ID_MODE_DISABLED("Q"), diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java new file mode 100644 index 000000000000..b7ccc6ecc15a --- /dev/null +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java @@ -0,0 +1,107 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.awssdk.protocol.tests; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static software.amazon.awssdk.core.useragent.BusinessMetricCollection.METRIC_SEARCH_PATTERN; + +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2AsyncClient; +import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2AsyncClientBuilder; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClientBuilder; + +class ProtocolRpcV2CborUserAgentTest { + private CapturingInterceptor interceptor; + + private static final String USER_AGENT_HEADER_NAME = "User-Agent"; + private static final StaticCredentialsProvider CREDENTIALS_PROVIDER = + StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid")); + + @BeforeEach + public void setup() { + this.interceptor = new CapturingInterceptor(); + } + + @Test + void when_rpcV2CborProtocolIsUsed_correctMetricIsAdded() { + ProtocolSmithyrpcv2AsyncClientBuilder clientBuilder = asyncClientBuilderForRpcV2Cbor(); + + assertThatThrownBy(() -> clientBuilder.build().operationWithNoInputOrOutput(r -> {}).join()) + .hasMessageContaining("stop"); + + String userAgent = assertAndGetUserAgentString(); + assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value())); + } + + @Test + void when_nonRpcV2CborProtocolIsUsed_rpcV2CborMetricIsNotAdded() { + ProtocolRestJsonAsyncClientBuilder clientBuilder = asyncClientBuilderForRestJson(); + + assertThatThrownBy(() -> clientBuilder.build().allTypes(r -> {}).join()) + .hasMessageContaining("stop"); + + String userAgent = assertAndGetUserAgentString(); + assertThat(userAgent).doesNotMatch(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value())); + } + + private String assertAndGetUserAgentString() { + Map> headers = interceptor.context.httpRequest().headers(); + assertThat(headers).containsKey(USER_AGENT_HEADER_NAME); + return headers.get(USER_AGENT_HEADER_NAME).get(0); + } + + private ProtocolSmithyrpcv2AsyncClientBuilder asyncClientBuilderForRpcV2Cbor() { + return ProtocolSmithyrpcv2AsyncClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(CREDENTIALS_PROVIDER) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)); + } + + private ProtocolRestJsonAsyncClientBuilder asyncClientBuilderForRestJson() { + return ProtocolRestJsonAsyncClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(CREDENTIALS_PROVIDER) + .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)); + } + + public static class CapturingInterceptor implements ExecutionInterceptor { + private Context.BeforeTransmission context; + private ExecutionAttributes executionAttributes; + + @Override + public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { + this.context = context; + this.executionAttributes = executionAttributes; + throw new RuntimeException("stop"); + } + + public ExecutionAttributes executionAttributes() { + return executionAttributes; + } + } +} From dab42f52d492487e7fe2e21497533482991a8df1 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 11:37:42 -0700 Subject: [PATCH 2/9] Add Changelog --- .changes/next-release/feature-AWSSDKforJavav2-ee91960.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/next-release/feature-AWSSDKforJavav2-ee91960.json diff --git a/.changes/next-release/feature-AWSSDKforJavav2-ee91960.json b/.changes/next-release/feature-AWSSDKforJavav2-ee91960.json new file mode 100644 index 000000000000..cabc42ee1bd8 --- /dev/null +++ b/.changes/next-release/feature-AWSSDKforJavav2-ee91960.json @@ -0,0 +1,6 @@ +{ + "type": "feature", + "category": "AWS SDK for Java v2", + "contributor": "", + "description": "Add business metrics support for RPC v2 CBOR protocol to track smithy rpcv2 cbor protocol usage." +} From 3b31de51b6920e0e61ea65e088cceadc1b6c510d Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 12:19:01 -0700 Subject: [PATCH 3/9] Updating test --- .../tests/ProtocolRpcV2CborUserAgentTest.java | 88 ++++++++----------- 1 file changed, 37 insertions(+), 51 deletions(-) diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java index b7ccc6ecc15a..12ff781b4f3e 100644 --- a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java @@ -16,92 +16,78 @@ package software.amazon.awssdk.protocol.tests; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static software.amazon.awssdk.core.useragent.BusinessMetricCollection.METRIC_SEARCH_PATTERN; import java.util.List; -import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; +import software.amazon.awssdk.http.AbortableInputStream; +import software.amazon.awssdk.http.HttpExecuteResponse; +import software.amazon.awssdk.http.SdkHttpRequest; +import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2AsyncClient; -import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2AsyncClientBuilder; -import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; -import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClientBuilder; +import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2Client; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.testutils.service.http.MockSyncHttpClient; +import software.amazon.awssdk.utils.StringInputStream; class ProtocolRpcV2CborUserAgentTest { - private CapturingInterceptor interceptor; - private static final String USER_AGENT_HEADER_NAME = "User-Agent"; private static final StaticCredentialsProvider CREDENTIALS_PROVIDER = StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid")); + private MockSyncHttpClient mockHttpClient; + @BeforeEach public void setup() { - this.interceptor = new CapturingInterceptor(); + mockHttpClient = new MockSyncHttpClient(); + mockHttpClient.stubNextResponse(mockResponse()); } @Test void when_rpcV2CborProtocolIsUsed_correctMetricIsAdded() { - ProtocolSmithyrpcv2AsyncClientBuilder clientBuilder = asyncClientBuilderForRpcV2Cbor(); + ProtocolSmithyrpcv2Client client = ProtocolSmithyrpcv2Client.builder() + .region(Region.US_WEST_2) + .credentialsProvider(CREDENTIALS_PROVIDER) + .httpClient(mockHttpClient) + .build(); - assertThatThrownBy(() -> clientBuilder.build().operationWithNoInputOrOutput(r -> {}).join()) - .hasMessageContaining("stop"); + client.operationWithNoInputOrOutput(r -> {}); - String userAgent = assertAndGetUserAgentString(); + String userAgent = getUserAgentFromLastRequest(); assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value())); } @Test void when_nonRpcV2CborProtocolIsUsed_rpcV2CborMetricIsNotAdded() { - ProtocolRestJsonAsyncClientBuilder clientBuilder = asyncClientBuilderForRestJson(); + ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(CREDENTIALS_PROVIDER) + .httpClient(mockHttpClient) + .build(); - assertThatThrownBy(() -> clientBuilder.build().allTypes(r -> {}).join()) - .hasMessageContaining("stop"); + client.allTypes(r -> {}); - String userAgent = assertAndGetUserAgentString(); + String userAgent = getUserAgentFromLastRequest(); assertThat(userAgent).doesNotMatch(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value())); } - private String assertAndGetUserAgentString() { - Map> headers = interceptor.context.httpRequest().headers(); - assertThat(headers).containsKey(USER_AGENT_HEADER_NAME); - return headers.get(USER_AGENT_HEADER_NAME).get(0); - } + private String getUserAgentFromLastRequest() { + SdkHttpRequest lastRequest = mockHttpClient.getLastRequest(); + assertThat(lastRequest).isNotNull(); - private ProtocolSmithyrpcv2AsyncClientBuilder asyncClientBuilderForRpcV2Cbor() { - return ProtocolSmithyrpcv2AsyncClient.builder() - .region(Region.US_WEST_2) - .credentialsProvider(CREDENTIALS_PROVIDER) - .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)); + List userAgentHeaders = lastRequest.headers().get(USER_AGENT_HEADER_NAME); + assertThat(userAgentHeaders).isNotNull().hasSize(1); + return userAgentHeaders.get(0); } - private ProtocolRestJsonAsyncClientBuilder asyncClientBuilderForRestJson() { - return ProtocolRestJsonAsyncClient.builder() - .region(Region.US_WEST_2) - .credentialsProvider(CREDENTIALS_PROVIDER) - .overrideConfiguration(c -> c.addExecutionInterceptor(interceptor)); - } - - public static class CapturingInterceptor implements ExecutionInterceptor { - private Context.BeforeTransmission context; - private ExecutionAttributes executionAttributes; - - @Override - public void beforeTransmission(Context.BeforeTransmission context, ExecutionAttributes executionAttributes) { - this.context = context; - this.executionAttributes = executionAttributes; - throw new RuntimeException("stop"); - } - - public ExecutionAttributes executionAttributes() { - return executionAttributes; - } + private static HttpExecuteResponse mockResponse() { + return HttpExecuteResponse.builder() + .response(SdkHttpResponse.builder().statusCode(200).build()) + .responseBody(AbortableInputStream.create(new StringInputStream("{}"))) + .build(); } } From 67543c6f0eebc42ab2699a0dfe33d5bff62fd1d0 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 13:40:45 -0700 Subject: [PATCH 4/9] Add codegen tests --- .../client/test-rpcv2-async-client-class.java | 40 +++++++++++------ .../codegen/poet/client/test-rpcv2-sync.java | 43 ++++++++++++------- 2 files changed, 54 insertions(+), 29 deletions(-) diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java index 547fe51ec475..7670b1842a75 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java @@ -12,11 +12,13 @@ import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ApiName; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.SdkRequest; @@ -66,6 +68,7 @@ import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolException; +import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.ValidationException; @@ -173,7 +176,7 @@ public CompletableFuture emptyInputOutput(EmptyInputOu .withMarshaller(new EmptyInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(emptyInputOutputRequest)); + .withInput(applyRpcV2CborUserAgent(emptyInputOutputRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -246,7 +249,7 @@ public CompletableFuture float16(Float16Request float16Request) .withProtocolMetadata(protocolMetadata).withMarshaller(new Float16RequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(float16Request)); + .withInput(applyRpcV2CborUserAgent(float16Request))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -321,7 +324,7 @@ public CompletableFuture fractionalSeconds(Fractional .withMarshaller(new FractionalSecondsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(fractionalSecondsRequest)); + .withInput(applyRpcV2CborUserAgent(fractionalSecondsRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -398,7 +401,7 @@ public CompletableFuture greetingWithErrors(Greeting .withMarshaller(new GreetingWithErrorsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(greetingWithErrorsRequest)); + .withInput(applyRpcV2CborUserAgent(greetingWithErrorsRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -472,7 +475,7 @@ public CompletableFuture noInputOutput(NoInputOutputReque .withMarshaller(new NoInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(noInputOutputRequest)); + .withInput(applyRpcV2CborUserAgent(noInputOutputRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -549,7 +552,7 @@ public CompletableFuture operationWithDefaults( .withMarshaller(new OperationWithDefaultsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(operationWithDefaultsRequest)); + .withInput(applyRpcV2CborUserAgent(operationWithDefaultsRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -625,7 +628,7 @@ public CompletableFuture optionalInputOutput( .withMarshaller(new OptionalInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(optionalInputOutputRequest)); + .withInput(applyRpcV2CborUserAgent(optionalInputOutputRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -700,7 +703,7 @@ public CompletableFuture recursiveShapes(RecursiveShape .withMarshaller(new RecursiveShapesRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(recursiveShapesRequest)); + .withInput(applyRpcV2CborUserAgent(recursiveShapesRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -776,7 +779,7 @@ public CompletableFuture rpcV2CborDenseMaps(RpcV2Cbo .withMarshaller(new RpcV2CborDenseMapsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(rpcV2CborDenseMapsRequest)); + .withInput(applyRpcV2CborUserAgent(rpcV2CborDenseMapsRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -851,7 +854,7 @@ public CompletableFuture rpcV2CborLists(RpcV2CborListsRe .withMarshaller(new RpcV2CborListsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(rpcV2CborListsRequest)); + .withInput(applyRpcV2CborUserAgent(rpcV2CborListsRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -928,7 +931,7 @@ public CompletableFuture rpcV2CborSparseMaps( .withMarshaller(new RpcV2CborSparseMapsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(rpcV2CborSparseMapsRequest)); + .withInput(applyRpcV2CborUserAgent(rpcV2CborSparseMapsRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1004,7 +1007,7 @@ public CompletableFuture simpleScalarProperties( .withMarshaller(new SimpleScalarPropertiesRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(simpleScalarPropertiesRequest)); + .withInput(applyRpcV2CborUserAgent(simpleScalarPropertiesRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1080,7 +1083,7 @@ public CompletableFuture sparseNullsOperation( .withMarshaller(new SparseNullsOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(sparseNullsOperationRequest)); + .withInput(applyRpcV2CborUserAgent(sparseNullsOperationRequest))); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1102,6 +1105,15 @@ public final String serviceName() { return SERVICE_NAME; } + private static T applyRpcV2CborUserAgent(T request) { + Consumer userAgentApplier = b -> b.addApiName(ApiName.builder() + .name("sdk-metrics").version("M").build()); + AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() + .map(c -> c.toBuilder().applyMutation(userAgentApplier).build()) + .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(userAgentApplier).build())); + return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); + } + private > T init(T builder) { return builder.clientConfiguration(clientConfiguration) .defaultServiceExceptionSupplier(SmithyRpcV2ProtocolException::builder) @@ -1170,4 +1182,4 @@ private HttpResponseHandler createErrorResponseHandler(Base public void close() { clientHandler.close(); } -} +} \ No newline at end of file diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java index fcda9aa09cb8..5ee92262efb9 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java @@ -7,11 +7,13 @@ import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; +import software.amazon.awssdk.core.ApiName; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.SdkRequest; @@ -62,6 +64,7 @@ import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolException; +import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.ValidationException; @@ -163,7 +166,7 @@ public EmptyInputOutputResponse emptyInputOutput(EmptyInputOutputRequest emptyIn return clientHandler.execute(new ClientExecutionParams() .withOperationName("EmptyInputOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(emptyInputOutputRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(emptyInputOutputRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new EmptyInputOutputRequestMarshaller(protocolFactory))); } finally { @@ -227,7 +230,7 @@ public Float16Response float16(Float16Request float16Request) throws AwsServiceE return clientHandler.execute(new ClientExecutionParams() .withOperationName("Float16").withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) - .withInput(float16Request).withMetricCollector(apiCallMetricCollector) + .withInput(applyRpcV2CborUserAgent(float16Request)).withMetricCollector(apiCallMetricCollector) .withMarshaller(new Float16RequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -291,7 +294,7 @@ public FractionalSecondsResponse fractionalSeconds(FractionalSecondsRequest frac return clientHandler.execute(new ClientExecutionParams() .withOperationName("FractionalSeconds").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(fractionalSecondsRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(fractionalSecondsRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new FractionalSecondsRequestMarshaller(protocolFactory))); } finally { @@ -359,7 +362,7 @@ public GreetingWithErrorsResponse greetingWithErrors(GreetingWithErrorsRequest g return clientHandler.execute(new ClientExecutionParams() .withOperationName("GreetingWithErrors").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(greetingWithErrorsRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(greetingWithErrorsRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new GreetingWithErrorsRequestMarshaller(protocolFactory))); } finally { @@ -423,7 +426,7 @@ public NoInputOutputResponse noInputOutput(NoInputOutputRequest noInputOutputReq return clientHandler.execute(new ClientExecutionParams() .withOperationName("NoInputOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(noInputOutputRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(noInputOutputRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new NoInputOutputRequestMarshaller(protocolFactory))); } finally { @@ -489,8 +492,8 @@ public OperationWithDefaultsResponse operationWithDefaults(OperationWithDefaults return clientHandler.execute(new ClientExecutionParams() .withOperationName("OperationWithDefaults").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(operationWithDefaultsRequest) - .withMetricCollector(apiCallMetricCollector) + .withRequestConfiguration(clientConfiguration) + .withInput(applyRpcV2CborUserAgent(operationWithDefaultsRequest)).withMetricCollector(apiCallMetricCollector) .withMarshaller(new OperationWithDefaultsRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -554,7 +557,7 @@ public OptionalInputOutputResponse optionalInputOutput(OptionalInputOutputReques return clientHandler.execute(new ClientExecutionParams() .withOperationName("OptionalInputOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(optionalInputOutputRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(optionalInputOutputRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new OptionalInputOutputRequestMarshaller(protocolFactory))); } finally { @@ -619,7 +622,7 @@ public RecursiveShapesResponse recursiveShapes(RecursiveShapesRequest recursiveS return clientHandler.execute(new ClientExecutionParams() .withOperationName("RecursiveShapes").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(recursiveShapesRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(recursiveShapesRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RecursiveShapesRequestMarshaller(protocolFactory))); } finally { @@ -685,7 +688,7 @@ public RpcV2CborDenseMapsResponse rpcV2CborDenseMaps(RpcV2CborDenseMapsRequest r return clientHandler.execute(new ClientExecutionParams() .withOperationName("RpcV2CborDenseMaps").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborDenseMapsRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(rpcV2CborDenseMapsRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RpcV2CborDenseMapsRequestMarshaller(protocolFactory))); } finally { @@ -750,7 +753,7 @@ public RpcV2CborListsResponse rpcV2CborLists(RpcV2CborListsRequest rpcV2CborList return clientHandler.execute(new ClientExecutionParams() .withOperationName("RpcV2CborLists").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborListsRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(rpcV2CborListsRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RpcV2CborListsRequestMarshaller(protocolFactory))); } finally { @@ -816,7 +819,7 @@ public RpcV2CborSparseMapsResponse rpcV2CborSparseMaps(RpcV2CborSparseMapsReques return clientHandler.execute(new ClientExecutionParams() .withOperationName("RpcV2CborSparseMaps").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborSparseMapsRequest) + .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(rpcV2CborSparseMapsRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RpcV2CborSparseMapsRequestMarshaller(protocolFactory))); } finally { @@ -882,7 +885,8 @@ public SimpleScalarPropertiesResponse simpleScalarProperties(SimpleScalarPropert .execute(new ClientExecutionParams() .withOperationName("SimpleScalarProperties").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(simpleScalarPropertiesRequest) + .withRequestConfiguration(clientConfiguration) + .withInput(applyRpcV2CborUserAgent(simpleScalarPropertiesRequest)) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new SimpleScalarPropertiesRequestMarshaller(protocolFactory))); } finally { @@ -947,8 +951,8 @@ public SparseNullsOperationResponse sparseNullsOperation(SparseNullsOperationReq return clientHandler.execute(new ClientExecutionParams() .withOperationName("SparseNullsOperation").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(sparseNullsOperationRequest) - .withMetricCollector(apiCallMetricCollector) + .withRequestConfiguration(clientConfiguration) + .withInput(applyRpcV2CborUserAgent(sparseNullsOperationRequest)).withMetricCollector(apiCallMetricCollector) .withMarshaller(new SparseNullsOperationRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -960,6 +964,15 @@ public final String serviceName() { return SERVICE_NAME; } + private static T applyRpcV2CborUserAgent(T request) { + Consumer userAgentApplier = b -> b.addApiName(ApiName.builder() + .name("sdk-metrics").version("M").build()); + AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() + .map(c -> c.toBuilder().applyMutation(userAgentApplier).build()) + .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(userAgentApplier).build())); + return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); + } + private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; From 2eb51876583394ef98f2c0d10800b7da1e53f05d Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 15:10:43 -0700 Subject: [PATCH 5/9] Address PR feedback --- .../protocol/tests/ProtocolRpcV2CborUserAgentTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java index 12ff781b4f3e..15ea3a4db98c 100644 --- a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java +++ b/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java @@ -23,7 +23,6 @@ import org.junit.jupiter.api.Test; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.http.AbortableInputStream; import software.amazon.awssdk.http.HttpExecuteResponse; import software.amazon.awssdk.http.SdkHttpRequest; @@ -58,7 +57,7 @@ void when_rpcV2CborProtocolIsUsed_correctMetricIsAdded() { client.operationWithNoInputOrOutput(r -> {}); String userAgent = getUserAgentFromLastRequest(); - assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value())); + assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply("M")); } @Test @@ -72,7 +71,7 @@ void when_nonRpcV2CborProtocolIsUsed_rpcV2CborMetricIsNotAdded() { client.allTypes(r -> {}); String userAgent = getUserAgentFromLastRequest(); - assertThat(userAgent).doesNotMatch(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value())); + assertThat(userAgent).doesNotMatch(METRIC_SEARCH_PATTERN.apply("M")); } private String getUserAgentFromLastRequest() { From f0531d092bb4e04a02c4de4572014fa099afef4e Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 17:34:40 -0700 Subject: [PATCH 6/9] Address PR feedback --- .../poet/client/specs/JsonProtocolSpec.java | 61 +------------------ .../client/test-rpcv2-async-client-class.java | 38 ++++-------- .../codegen/poet/client/test-rpcv2-sync.java | 43 +++++-------- .../internal/AwsExecutionContextBuilder.java | 18 +++++- 4 files changed, 46 insertions(+), 114 deletions(-) diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java index 8f0fe2210f8e..8e1afb25e8e0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/JsonProtocolSpec.java @@ -25,14 +25,10 @@ import com.squareup.javapoet.TypeName; import com.squareup.javapoet.TypeVariableName; import com.squareup.javapoet.WildcardTypeName; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; import java.util.function.Function; import javax.lang.model.element.Modifier; -import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.eventstream.EventStreamAsyncResponseTransformer; import software.amazon.awssdk.awscore.eventstream.EventStreamTaggedUnionPojoSupplier; import software.amazon.awssdk.awscore.eventstream.RestEventStreamAsyncResponseTransformer; @@ -52,7 +48,6 @@ import software.amazon.awssdk.codegen.poet.client.traits.RequestCompressionTrait; import software.amazon.awssdk.codegen.poet.eventstream.EventStreamUtils; import software.amazon.awssdk.codegen.poet.model.EventStreamSpecHelper; -import software.amazon.awssdk.core.ApiName; import software.amazon.awssdk.core.SdkPojoBuilder; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.async.AsyncRequestBody; @@ -61,7 +56,6 @@ import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.HttpResponseHandler; import software.amazon.awssdk.core.protocol.VoidSdkResponse; -import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.protocols.cbor.AwsCborProtocolFactory; import software.amazon.awssdk.protocols.core.ExceptionMetadata; import software.amazon.awssdk.protocols.json.AwsJsonProtocol; @@ -230,10 +224,7 @@ public CodeBlock executionHandler(OperationModel opModel) { .add(discoveredEndpoint(opModel)) .add(credentialType(opModel, model)) .add(".withRequestConfiguration(clientConfiguration)") - .add(".withInput($L)\n", - model.getMetadata().isRpcV2CborProtocol() ? - "applyRpcV2CborUserAgent(" + opModel.getInput().getVariableName() + ")" : - opModel.getInput().getVariableName()) + .add(".withInput($L)\n", opModel.getInput().getVariableName()) .add(".withMetricCollector(apiCallMetricCollector)") .add(HttpChecksumRequiredTrait.putHttpChecksumAttribute(opModel)) .add(HttpChecksumTrait.create(opModel)); @@ -329,10 +320,7 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper builder.add(RequestCompressionTrait.create(opModel, model)) .add(".withInput($L)$L)", - intermediateModel.getMetadata().isRpcV2CborProtocol() ? - "applyRpcV2CborUserAgent(" + opModel.getInput().getVariableName() + ")" : - opModel.getInput().getVariableName(), - asyncResponseTransformerVariable(isStreaming, isRestJson, opModel)) + opModel.getInput().getVariableName(), asyncResponseTransformerVariable(isStreaming, isRestJson, opModel)) .add(opModel.getEndpointDiscovery() != null ? ");" : ";"); if (opModel.hasStreamingOutput()) { @@ -580,49 +568,4 @@ private String protocolFactoryLiteral(IntermediateModel model, OperationModel op private boolean isRestJson(IntermediateModel model) { return model.getMetadata().getProtocol() == Protocol.REST_JSON; } - - @Override - public List additionalMethods() { - List methods = new ArrayList<>(); - - applyRpcV2CborUserAgentMethod().ifPresent(methods::add); - - return methods; - } - - private Optional applyRpcV2CborUserAgentMethod() { - if (!model.getMetadata().isRpcV2CborProtocol()) { - return Optional.empty(); - } - - TypeVariableName typeVariableName = - TypeVariableName.get("T", poetExtensions.getModelClass(model.getSdkRequestBaseClassName())); - - ParameterizedTypeName parameterizedTypeName = ParameterizedTypeName - .get(ClassName.get(Consumer.class), ClassName.get(AwsRequestOverrideConfiguration.Builder.class)); - - CodeBlock codeBlock = CodeBlock.builder() - .addStatement("$T userAgentApplier = b -> " - + "b.addApiName($T.builder().name($S).version($S).build())", - parameterizedTypeName, ApiName.class, - "sdk-metrics", - BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value()) - .addStatement("$T overrideConfiguration =\n" - + " request.overrideConfiguration().map(c -> c.toBuilder()" - + ".applyMutation(userAgentApplier).build())\n" - + " .orElse((AwsRequestOverrideConfiguration.builder()" - + ".applyMutation(userAgentApplier).build()))", - AwsRequestOverrideConfiguration.class) - .addStatement("return (T) request.toBuilder().overrideConfiguration(overrideConfiguration)" - + ".build()") - .build(); - - return Optional.of(MethodSpec.methodBuilder("applyRpcV2CborUserAgent") - .addModifiers(Modifier.PRIVATE, Modifier.STATIC) - .addParameter(typeVariableName, "request") - .addTypeVariable(typeVariableName) - .addCode(codeBlock) - .returns(typeVariableName) - .build()); - } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java index 7670b1842a75..bd3083b4602b 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-async-client-class.java @@ -12,13 +12,11 @@ import org.slf4j.LoggerFactory; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; -import software.amazon.awssdk.core.ApiName; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.SdkRequest; @@ -68,7 +66,6 @@ import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolException; -import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.ValidationException; @@ -176,7 +173,7 @@ public CompletableFuture emptyInputOutput(EmptyInputOu .withMarshaller(new EmptyInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(emptyInputOutputRequest))); + .withInput(emptyInputOutputRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -249,7 +246,7 @@ public CompletableFuture float16(Float16Request float16Request) .withProtocolMetadata(protocolMetadata).withMarshaller(new Float16RequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(float16Request))); + .withInput(float16Request)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -324,7 +321,7 @@ public CompletableFuture fractionalSeconds(Fractional .withMarshaller(new FractionalSecondsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(fractionalSecondsRequest))); + .withInput(fractionalSecondsRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -401,7 +398,7 @@ public CompletableFuture greetingWithErrors(Greeting .withMarshaller(new GreetingWithErrorsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(greetingWithErrorsRequest))); + .withInput(greetingWithErrorsRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -475,7 +472,7 @@ public CompletableFuture noInputOutput(NoInputOutputReque .withMarshaller(new NoInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(noInputOutputRequest))); + .withInput(noInputOutputRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -552,7 +549,7 @@ public CompletableFuture operationWithDefaults( .withMarshaller(new OperationWithDefaultsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(operationWithDefaultsRequest))); + .withInput(operationWithDefaultsRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -628,7 +625,7 @@ public CompletableFuture optionalInputOutput( .withMarshaller(new OptionalInputOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(optionalInputOutputRequest))); + .withInput(optionalInputOutputRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -703,7 +700,7 @@ public CompletableFuture recursiveShapes(RecursiveShape .withMarshaller(new RecursiveShapesRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(recursiveShapesRequest))); + .withInput(recursiveShapesRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -779,7 +776,7 @@ public CompletableFuture rpcV2CborDenseMaps(RpcV2Cbo .withMarshaller(new RpcV2CborDenseMapsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(rpcV2CborDenseMapsRequest))); + .withInput(rpcV2CborDenseMapsRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -854,7 +851,7 @@ public CompletableFuture rpcV2CborLists(RpcV2CborListsRe .withMarshaller(new RpcV2CborListsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(rpcV2CborListsRequest))); + .withInput(rpcV2CborListsRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -931,7 +928,7 @@ public CompletableFuture rpcV2CborSparseMaps( .withMarshaller(new RpcV2CborSparseMapsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(rpcV2CborSparseMapsRequest))); + .withInput(rpcV2CborSparseMapsRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1007,7 +1004,7 @@ public CompletableFuture simpleScalarProperties( .withMarshaller(new SimpleScalarPropertiesRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(simpleScalarPropertiesRequest))); + .withInput(simpleScalarPropertiesRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1083,7 +1080,7 @@ public CompletableFuture sparseNullsOperation( .withMarshaller(new SparseNullsOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withRequestConfiguration(clientConfiguration).withMetricCollector(apiCallMetricCollector) - .withInput(applyRpcV2CborUserAgent(sparseNullsOperationRequest))); + .withInput(sparseNullsOperationRequest)); CompletableFuture whenCompleted = executeFuture.whenComplete((r, e) -> { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); }); @@ -1105,15 +1102,6 @@ public final String serviceName() { return SERVICE_NAME; } - private static T applyRpcV2CborUserAgent(T request) { - Consumer userAgentApplier = b -> b.addApiName(ApiName.builder() - .name("sdk-metrics").version("M").build()); - AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() - .map(c -> c.toBuilder().applyMutation(userAgentApplier).build()) - .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(userAgentApplier).build())); - return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); - } - private > T init(T builder) { return builder.clientConfiguration(clientConfiguration) .defaultServiceExceptionSupplier(SmithyRpcV2ProtocolException::builder) diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java index 5ee92262efb9..fcda9aa09cb8 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-rpcv2-sync.java @@ -7,13 +7,11 @@ import java.util.function.Function; import software.amazon.awssdk.annotations.Generated; import software.amazon.awssdk.annotations.SdkInternalApi; -import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.awscore.internal.AwsProtocolMetadata; import software.amazon.awssdk.awscore.internal.AwsServiceProtocol; import software.amazon.awssdk.awscore.retry.AwsRetryStrategy; -import software.amazon.awssdk.core.ApiName; import software.amazon.awssdk.core.RequestOverrideConfiguration; import software.amazon.awssdk.core.SdkPlugin; import software.amazon.awssdk.core.SdkRequest; @@ -64,7 +62,6 @@ import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SimpleScalarPropertiesResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolException; -import software.amazon.awssdk.services.smithyrpcv2protocol.model.SmithyRpcV2ProtocolRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationRequest; import software.amazon.awssdk.services.smithyrpcv2protocol.model.SparseNullsOperationResponse; import software.amazon.awssdk.services.smithyrpcv2protocol.model.ValidationException; @@ -166,7 +163,7 @@ public EmptyInputOutputResponse emptyInputOutput(EmptyInputOutputRequest emptyIn return clientHandler.execute(new ClientExecutionParams() .withOperationName("EmptyInputOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(emptyInputOutputRequest)) + .withRequestConfiguration(clientConfiguration).withInput(emptyInputOutputRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new EmptyInputOutputRequestMarshaller(protocolFactory))); } finally { @@ -230,7 +227,7 @@ public Float16Response float16(Float16Request float16Request) throws AwsServiceE return clientHandler.execute(new ClientExecutionParams() .withOperationName("Float16").withProtocolMetadata(protocolMetadata).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withRequestConfiguration(clientConfiguration) - .withInput(applyRpcV2CborUserAgent(float16Request)).withMetricCollector(apiCallMetricCollector) + .withInput(float16Request).withMetricCollector(apiCallMetricCollector) .withMarshaller(new Float16RequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -294,7 +291,7 @@ public FractionalSecondsResponse fractionalSeconds(FractionalSecondsRequest frac return clientHandler.execute(new ClientExecutionParams() .withOperationName("FractionalSeconds").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(fractionalSecondsRequest)) + .withRequestConfiguration(clientConfiguration).withInput(fractionalSecondsRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new FractionalSecondsRequestMarshaller(protocolFactory))); } finally { @@ -362,7 +359,7 @@ public GreetingWithErrorsResponse greetingWithErrors(GreetingWithErrorsRequest g return clientHandler.execute(new ClientExecutionParams() .withOperationName("GreetingWithErrors").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(greetingWithErrorsRequest)) + .withRequestConfiguration(clientConfiguration).withInput(greetingWithErrorsRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new GreetingWithErrorsRequestMarshaller(protocolFactory))); } finally { @@ -426,7 +423,7 @@ public NoInputOutputResponse noInputOutput(NoInputOutputRequest noInputOutputReq return clientHandler.execute(new ClientExecutionParams() .withOperationName("NoInputOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(noInputOutputRequest)) + .withRequestConfiguration(clientConfiguration).withInput(noInputOutputRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new NoInputOutputRequestMarshaller(protocolFactory))); } finally { @@ -492,8 +489,8 @@ public OperationWithDefaultsResponse operationWithDefaults(OperationWithDefaults return clientHandler.execute(new ClientExecutionParams() .withOperationName("OperationWithDefaults").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(applyRpcV2CborUserAgent(operationWithDefaultsRequest)).withMetricCollector(apiCallMetricCollector) + .withRequestConfiguration(clientConfiguration).withInput(operationWithDefaultsRequest) + .withMetricCollector(apiCallMetricCollector) .withMarshaller(new OperationWithDefaultsRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -557,7 +554,7 @@ public OptionalInputOutputResponse optionalInputOutput(OptionalInputOutputReques return clientHandler.execute(new ClientExecutionParams() .withOperationName("OptionalInputOutput").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(optionalInputOutputRequest)) + .withRequestConfiguration(clientConfiguration).withInput(optionalInputOutputRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new OptionalInputOutputRequestMarshaller(protocolFactory))); } finally { @@ -622,7 +619,7 @@ public RecursiveShapesResponse recursiveShapes(RecursiveShapesRequest recursiveS return clientHandler.execute(new ClientExecutionParams() .withOperationName("RecursiveShapes").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(recursiveShapesRequest)) + .withRequestConfiguration(clientConfiguration).withInput(recursiveShapesRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RecursiveShapesRequestMarshaller(protocolFactory))); } finally { @@ -688,7 +685,7 @@ public RpcV2CborDenseMapsResponse rpcV2CborDenseMaps(RpcV2CborDenseMapsRequest r return clientHandler.execute(new ClientExecutionParams() .withOperationName("RpcV2CborDenseMaps").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(rpcV2CborDenseMapsRequest)) + .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborDenseMapsRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RpcV2CborDenseMapsRequestMarshaller(protocolFactory))); } finally { @@ -753,7 +750,7 @@ public RpcV2CborListsResponse rpcV2CborLists(RpcV2CborListsRequest rpcV2CborList return clientHandler.execute(new ClientExecutionParams() .withOperationName("RpcV2CborLists").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(rpcV2CborListsRequest)) + .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborListsRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RpcV2CborListsRequestMarshaller(protocolFactory))); } finally { @@ -819,7 +816,7 @@ public RpcV2CborSparseMapsResponse rpcV2CborSparseMaps(RpcV2CborSparseMapsReques return clientHandler.execute(new ClientExecutionParams() .withOperationName("RpcV2CborSparseMaps").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration).withInput(applyRpcV2CborUserAgent(rpcV2CborSparseMapsRequest)) + .withRequestConfiguration(clientConfiguration).withInput(rpcV2CborSparseMapsRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new RpcV2CborSparseMapsRequestMarshaller(protocolFactory))); } finally { @@ -885,8 +882,7 @@ public SimpleScalarPropertiesResponse simpleScalarProperties(SimpleScalarPropert .execute(new ClientExecutionParams() .withOperationName("SimpleScalarProperties").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(applyRpcV2CborUserAgent(simpleScalarPropertiesRequest)) + .withRequestConfiguration(clientConfiguration).withInput(simpleScalarPropertiesRequest) .withMetricCollector(apiCallMetricCollector) .withMarshaller(new SimpleScalarPropertiesRequestMarshaller(protocolFactory))); } finally { @@ -951,8 +947,8 @@ public SparseNullsOperationResponse sparseNullsOperation(SparseNullsOperationReq return clientHandler.execute(new ClientExecutionParams() .withOperationName("SparseNullsOperation").withProtocolMetadata(protocolMetadata) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) - .withRequestConfiguration(clientConfiguration) - .withInput(applyRpcV2CborUserAgent(sparseNullsOperationRequest)).withMetricCollector(apiCallMetricCollector) + .withRequestConfiguration(clientConfiguration).withInput(sparseNullsOperationRequest) + .withMetricCollector(apiCallMetricCollector) .withMarshaller(new SparseNullsOperationRequestMarshaller(protocolFactory))); } finally { metricPublishers.forEach(p -> p.publish(apiCallMetricCollector.collect())); @@ -964,15 +960,6 @@ public final String serviceName() { return SERVICE_NAME; } - private static T applyRpcV2CborUserAgent(T request) { - Consumer userAgentApplier = b -> b.addApiName(ApiName.builder() - .name("sdk-metrics").version("M").build()); - AwsRequestOverrideConfiguration overrideConfiguration = request.overrideConfiguration() - .map(c -> c.toBuilder().applyMutation(userAgentApplier).build()) - .orElse((AwsRequestOverrideConfiguration.builder().applyMutation(userAgentApplier).build())); - return (T) request.toBuilder().overrideConfiguration(overrideConfiguration).build(); - } - private static List resolveMetricPublishers(SdkClientConfiguration clientConfiguration, RequestOverrideConfiguration requestOverrideConfiguration) { List publishers = null; diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java index 4a71ba7681fb..6b1d304ac6a1 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java @@ -35,6 +35,7 @@ import software.amazon.awssdk.awscore.util.SignerOverrideUtils; import software.amazon.awssdk.core.HttpChecksumConstant; import software.amazon.awssdk.core.RequestOverrideConfiguration; +import software.amazon.awssdk.core.SdkProtocolMetadata; import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.SdkResponse; import software.amazon.awssdk.core.SelectedAuthScheme; @@ -133,7 +134,8 @@ private AwsExecutionContextBuilder() { clientConfig.option(SdkClientOption.REQUEST_CHECKSUM_CALCULATION)) .putAttribute(SdkInternalExecutionAttribute.RESPONSE_CHECKSUM_VALIDATION, clientConfig.option(SdkClientOption.RESPONSE_CHECKSUM_VALIDATION)) - .putAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS, resolveUserAgentBusinessMetrics(clientConfig)) + .putAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS, + resolveUserAgentBusinessMetrics(clientConfig, executionParams)) .putAttribute(AwsExecutionAttribute.AWS_SIGV4A_SIGNING_REGION_SET, clientConfig.option(AwsClientOption.AWS_SIGV4A_SIGNING_REGION_SET)); @@ -350,11 +352,23 @@ private static EndpointProvider resolveEndpointProvider(SdkRequest request, .orElse(clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER)); } - private static BusinessMetricCollection resolveUserAgentBusinessMetrics(SdkClientConfiguration clientConfig) { + private static BusinessMetricCollection + resolveUserAgentBusinessMetrics(SdkClientConfiguration clientConfig, + ClientExecutionParams executionParams) { BusinessMetricCollection businessMetrics = new BusinessMetricCollection(); Optional retryModeMetric = resolveRetryMode(clientConfig.option(RETRY_POLICY), clientConfig.option(RETRY_STRATEGY)); retryModeMetric.ifPresent(businessMetrics::addMetric); + + if (isRpcV2CborProtocol(executionParams.getProtocolMetadata())) { + businessMetrics.addMetric("M"); + } + return businessMetrics; } + + private static boolean isRpcV2CborProtocol(SdkProtocolMetadata protocolMetadata) { + return protocolMetadata != null && + "smithy-rpc-v2-cbor".equals(protocolMetadata.serviceProtocol()); + } } From 90a32b4b460eb852efb74c891c37a3413c94d1ec Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Thu, 16 Oct 2025 17:47:22 -0700 Subject: [PATCH 7/9] Additional changes --- .../awssdk/awscore/internal/AwsExecutionContextBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java index 6b1d304ac6a1..3b62705226d4 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java @@ -57,6 +57,7 @@ import software.amazon.awssdk.core.sync.ResponseTransformer; import software.amazon.awssdk.core.useragent.AdditionalMetadata; import software.amazon.awssdk.core.useragent.BusinessMetricCollection; +import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId; import software.amazon.awssdk.endpoints.EndpointProvider; import software.amazon.awssdk.http.ContentStreamProvider; import software.amazon.awssdk.http.auth.scheme.NoAuthAuthScheme; @@ -352,7 +353,7 @@ private static EndpointProvider resolveEndpointProvider(SdkRequest request, .orElse(clientConfig.option(SdkClientOption.ENDPOINT_PROVIDER)); } - private static BusinessMetricCollection + private static BusinessMetricCollection resolveUserAgentBusinessMetrics(SdkClientConfiguration clientConfig, ClientExecutionParams executionParams) { BusinessMetricCollection businessMetrics = new BusinessMetricCollection(); @@ -361,7 +362,7 @@ private static EndpointProvider resolveEndpointProvider(SdkRequest request, retryModeMetric.ifPresent(businessMetrics::addMetric); if (isRpcV2CborProtocol(executionParams.getProtocolMetadata())) { - businessMetrics.addMetric("M"); + businessMetrics.addMetric(BusinessMetricFeatureId.PROTOCOL_RPC_V2_CBOR.value()); } return businessMetrics; From b3cb48091b298fbf4cf1c3bed1e89696a6123457 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Fri, 17 Oct 2025 14:11:37 -0700 Subject: [PATCH 8/9] Adding test for rpc v2 cbor async client --- test/codegen-generated-classes-test/pom.xml | 6 + .../sdkrpcv2/customization.config | 4 + .../sdkrpcv2/endpoint-rule-set.json | 30 + .../sdkrpcv2/endpoint-tests.json | 5 + .../codegen-resources/sdkrpcv2/service-2.json | 724 ++++++++++++++++++ .../rpcv2cbor/RpcV2CborUserAgentTest.java} | 35 +- 6 files changed, 801 insertions(+), 3 deletions(-) create mode 100644 test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config create mode 100644 test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-rule-set.json create mode 100644 test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-tests.json create mode 100644 test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/service-2.json rename test/{protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java => codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rpcv2cbor/RpcV2CborUserAgentTest.java} (71%) diff --git a/test/codegen-generated-classes-test/pom.xml b/test/codegen-generated-classes-test/pom.xml index d1c4ac3f63e6..1e55037bb0f6 100644 --- a/test/codegen-generated-classes-test/pom.xml +++ b/test/codegen-generated-classes-test/pom.xml @@ -279,6 +279,12 @@ mockito-junit-jupiter test + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + compile + diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config new file mode 100644 index 000000000000..4a57cda840dd --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/customization.config @@ -0,0 +1,4 @@ +{ + "enableGenerateCompiledEndpointRules": true, + "skipEndpointTestGeneration": true +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-rule-set.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-rule-set.json new file mode 100644 index 000000000000..8c3cc3052beb --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-rule-set.json @@ -0,0 +1,30 @@ +{ + "version": "1.3", + "parameters": { + "Region": { + "builtIn": "AWS::Region", + "required": true, + "documentation": "The AWS region used to dispatch the request.", + "type": "String" + } + }, + "rules": [ + { + "conditions": [], + "endpoint": { + "url": "http://localhost/", + "properties": { + "authSchemes": [ + { + "name": "sigv4", + "signingRegion": "{Region}", + "signingName": "jsonrpc" + } + ] + }, + "headers": {} + }, + "type": "endpoint" + } + ] +} diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-tests.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-tests.json new file mode 100644 index 000000000000..f94902ff9d99 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/endpoint-tests.json @@ -0,0 +1,5 @@ +{ + "testCases": [ + ], + "version": "1.0" +} \ No newline at end of file diff --git a/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/service-2.json b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/service-2.json new file mode 100644 index 000000000000..4d3c2ea4a0d7 --- /dev/null +++ b/test/codegen-generated-classes-test/src/main/resources/codegen-resources/sdkrpcv2/service-2.json @@ -0,0 +1,724 @@ +{ + "version": "2.0", + "metadata": { + "apiVersion": "2016-03-11", + "endpointPrefix": "smithyrpcv2", + "jsonVersion": "1.1", + "protocol": "smithy-rpc-v2-cbor", + "protocols": [ + "smithy-rpc-v2-cbor" + ], + "serviceAbbreviation": "SmithyRpcV2ProtocolTests", + "serviceFullName": "Smithy RPCv2 Protocol Tests", + "serviceId": "ProtocolSmithyrpcv2", + "signatureVersion": "v4", + "targetPrefix": "ProtocolTestsSmithyRpcV2Service", + "uid": "smithyrpcv2-2016-03-11" + }, + "operations": { + "GetMetricData": { + "name": "GetMetricData", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "GetMetricDataRequest" + }, + "output": { + "shape": "GetMetricDataResponse" + } + }, + "AllTypes": { + "name": "AllTypes", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "AllTypesStructure" + }, + "output": { + "shape": "AllTypesStructure" + }, + "errors": [ + { + "shape": "EmptyModeledException" + }, + { + "shape": "ImplicitPayloadException" + } + ] + }, + "FurtherNestedContainers": { + "name": "FurtherNestedContainers", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "FurtherNestedContainersStructure" + }, + "output": { + "shape": "FurtherNestedContainersStructure" + } + }, + "IdempotentOperation": { + "name": "IdempotentOperation", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "IdempotentOperationStructure" + }, + "output": { + "shape": "IdempotentOperationStructure" + } + }, + "NestedContainers": { + "name": "NestedContainers", + "http": { + "method": "POST", + "requestUri": "/" + }, + "input": { + "shape": "NestedContainersStructure" + }, + "output": { + "shape": "NestedContainersStructure" + } + }, + "OperationWithNoInputOrOutput": { + "name": "OperationWithNoInputOrOutput", + "http": { + "method": "POST", + "requestUri": "/" + } + }, + "GreetingWithErrors":{ + "name":"GreetingWithErrors", + "http":{ + "method":"POST", + "requestUri":"/" + }, + "output":{"shape":"GreetingWithErrorsOutput"}, + "errors":[ + {"shape":"ComplexError"}, + {"shape":"InvalidGreeting"} + ], + "idempotent":true + } + }, + "shapes": { + "GetMetricDataRequest": { + "type": "structure", + "members": { + "id": { + "shape": "String" + } + } + }, + "GetMetricDataResponse": { + "type": "structure", + "members": { + "id": { + "shape": "String" + }, + "label": { + "shape": "String" + }, + "statusCode": { + "shape": "StatusCode" + }, + "timestamps": { + "shape": "ListOfTimeStamp" + }, + "values": { + "shape": "ListOfDouble" + } + } + }, + "ListOfDouble": { + "type": "list", + "member": { + "shape": "Double" + } + }, + "StatusCode": { + "type": "string", + "enum": [ + "Complete", + "InProgess" + ] + }, + "AllTypesStructure": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + }, + "IntegerMember": { + "shape": "Integer" + }, + "BooleanMember": { + "shape": "Boolean" + }, + "FloatMember": { + "shape": "Float" + }, + "DoubleMember": { + "shape": "Double" + }, + "BigDecimalMember": { + "shape": "NumericValue" + }, + "LongMember": { + "shape": "Long" + }, + "ShortMember": { + "shape": "Short" + }, + "ByteMember": { + "shape": "Byte" + }, + "SimpleList": { + "shape": "ListOfStrings" + }, + "ListOfMaps": { + "shape": "ListOfMapStringToString" + }, + "ListOfStructs": { + "shape": "ListOfSimpleStructs" + }, + "MapOfStringToIntegerList": { + "shape": "MapOfStringToIntegerList" + }, + "MapOfStringToString": { + "shape": "MapOfStringToString" + }, + "MapOfStringToStruct": { + "shape": "MapOfStringToSimpleStruct" + }, + "TimestampMember": { + "shape": "Timestamp" + }, + "StructWithNestedTimestampMember": { + "shape": "StructWithTimestamp" + }, + "TimestampFormatMember": { + "shape": "IsoTimestamp" + }, + "BlobArg": { + "shape": "BlobType" + }, + "StructWithNestedBlob": { + "shape": "StructWithNestedBlobType" + }, + "BlobMap": { + "shape": "BlobMapType" + }, + "ListOfBlobs": { + "shape": "ListOfBlobsType" + }, + "RecursiveStruct": { + "shape": "RecursiveStructType" + }, + "PolymorphicTypeWithSubTypes": { + "shape": "BaseType" + }, + "PolymorphicTypeWithoutSubTypes": { + "shape": "SubTypeOne" + }, + "EnumMember": { + "shape": "EnumType" + }, + "ListOfEnums": { + "shape": "ListOfEnums" + }, + "MapOfEnumToEnum": { + "shape": "MapOfEnumToEnum" + }, + "ListOfTimeStamp": { + "shape": "ListOfTimeStamp" + }, + "MapOfTimeStamp": { + "shape": "MapOfTimeStamp" + }, + "MyDocument": { + "shape": "MyDocument" + }, + "UnionMember": { + "shape": "AllTypesUnionStructure" + } + } + }, + "BaseType": { + "type": "structure", + "members": { + "BaseMember": { + "shape": "String" + } + } + }, + "BlobMapType": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "BlobType" + } + }, + "BlobType": { + "type": "blob" + }, + "Boolean": { + "type": "boolean" + }, + "Double": { + "type": "double" + }, + "EmptyModeledException": { + "type": "structure", + "members": {}, + "exception": true + }, + "EnumType": { + "type": "string", + "enum": [ + "EnumValue1", + "EnumValue2" + ] + }, + "Float": { + "type": "float" + }, + "Short": { + "type": "short" + }, + "Byte": { + "type": "byte" + }, + "FurtherNestedContainersStructure": { + "type": "structure", + "members": { + "ListOfNested": { + "shape": "ListOfNested" + } + } + }, + "IdempotentOperationStructure": { + "type": "structure", + "members": { + "IdempotencyToken": { + "shape": "String", + "idempotencyToken": true + } + } + }, + "ImplicitPayloadException": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + }, + "IntegerMember": { + "shape": "Integer" + }, + "LongMember": { + "shape": "Long" + }, + "ShortMember": { + "shape": "Short" + }, + "DoubleMember": { + "shape": "Double" + }, + "FloatMember": { + "shape": "Float" + }, + "TimestampMember": { + "shape": "Timestamp" + }, + "BooleanMember": { + "shape": "Boolean" + }, + "BlobMember": { + "shape": "BlobType" + }, + "ListMember": { + "shape": "ListOfStrings" + }, + "MapMember": { + "shape": "MapOfStringToString" + }, + "SimpleStructMember": { + "shape": "SimpleStruct" + } + }, + "exception": true + }, + "Integer": { + "type": "integer" + }, + "NumericValue": { + "type": "string", + "pattern": "([0-9]*\\.)?[0-9]+" + }, + "IsoTimestamp": { + "type": "timestamp", + "timestampFormat": "iso8601" + }, + "UnixTimestamp": { + "type": "timestamp", + "timestampFormat": "unixTimestamp" + }, + "ListOfAllTypesStructs": { + "type": "list", + "member": { + "shape": "AllTypesStructure" + } + }, + "ListOfBlobsType": { + "type": "list", + "member": { + "shape": "BlobType" + } + }, + "ListOfEnums": { + "type": "list", + "member": { + "shape": "EnumType" + } + }, + "ListOfIntegers": { + "type": "list", + "member": { + "shape": "Integer" + } + }, + "ListOfListOfListsOfStrings": { + "type": "list", + "member": { + "shape": "ListOfListsOfStrings" + } + }, + "ListOfListsOfAllTypesStructs": { + "type": "list", + "member": { + "shape": "ListOfAllTypesStructs" + } + }, + "ListOfListsOfStrings": { + "type": "list", + "member": { + "shape": "ListOfStrings" + } + }, + "ListOfListsOfStructs": { + "type": "list", + "member": { + "shape": "ListOfSimpleStructs" + } + }, + "ListOfMapStringToString": { + "type": "list", + "member": { + "shape": "MapOfStringToString" + } + }, + "ListOfNested": { + "type": "list", + "member": { + "shape": "NestedContainersStructure" + } + }, + "ListOfSimpleStructs": { + "type": "list", + "member": { + "shape": "SimpleStruct" + } + }, + "ListOfStrings": { + "type": "list", + "member": { + "shape": "String" + } + }, + "Long": { + "type": "long" + }, + "MapOfEnumToEnum": { + "type": "map", + "key": { + "shape": "EnumType" + }, + "value": { + "shape": "EnumType" + } + }, + "MapOfStringToIntegerList": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "ListOfIntegers" + } + }, + "MapOfStringToListOfListsOfStrings": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "ListOfListsOfStrings" + } + }, + "MapOfStringToSimpleStruct": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "SimpleStruct" + } + }, + "MapOfStringToString": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "String" + } + }, + "NestedContainersStructure": { + "type": "structure", + "members": { + "ListOfListsOfStrings": { + "shape": "ListOfListsOfStrings" + }, + "ListOfListsOfStructs": { + "shape": "ListOfListsOfStructs" + }, + "ListOfListsOfAllTypesStructs": { + "shape": "ListOfListsOfAllTypesStructs" + }, + "ListOfListOfListsOfStrings": { + "shape": "ListOfListOfListsOfStrings" + }, + "MapOfStringToListOfListsOfStrings": { + "shape": "MapOfStringToListOfListsOfStrings" + }, + "StringMember": { + "shape": "String" + } + } + }, + "RecursiveListType": { + "type": "list", + "member": { + "shape": "RecursiveStructType" + } + }, + "RecursiveMapType": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "RecursiveStructType" + } + }, + "RecursiveStructType": { + "type": "structure", + "members": { + "NoRecurse": { + "shape": "String" + }, + "RecursiveStruct": { + "shape": "RecursiveStructType" + }, + "RecursiveList": { + "shape": "RecursiveListType" + }, + "RecursiveMap": { + "shape": "RecursiveMapType" + } + } + }, + "SimpleStruct": { + "type": "structure", + "members": { + "StringMember": { + "shape": "String" + } + } + }, + "String": { + "type": "string" + }, + "StructWithNestedBlobType": { + "type": "structure", + "members": { + "NestedBlob": { + "shape": "BlobType" + } + } + }, + "StructWithTimestamp": { + "type": "structure", + "members": { + "NestedTimestamp": { + "shape": "Timestamp" + } + } + }, + "SubTypeOne": { + "type": "structure", + "members": { + "SubTypeOneMember": { + "shape": "String" + } + } + }, + "Timestamp": { + "type": "timestamp" + }, + "ListOfTimeStamp": { + "type": "list", + "member": { + "shape": "UnixTimestamp" + } + }, + "MapOfTimeStamp": { + "type": "map", + "key": { + "shape": "String" + }, + "value": { + "shape": "UnixTimestamp" + } + }, + "MyDocument": { + "type": "structure", + "document": true + }, + "AllTypesUnionStructure": { + "type": "structure", + "union": true, + "members": { + "StringMember": { + "shape": "String" + }, + "IntegerMember": { + "shape": "Integer" + }, + "BooleanMember": { + "shape": "Boolean" + }, + "FloatMember": { + "shape": "Float" + }, + "DoubleMember": { + "shape": "Double" + }, + "LongMember": { + "shape": "Long" + }, + "ShortMember": { + "shape": "Short" + }, + "EnumMember": { + "shape": "EnumType" + }, + "SimpleList": { + "shape": "ListOfStrings" + }, + "ListOfEnums": { + "shape": "ListOfEnums" + }, + "ListOfMaps": { + "shape": "ListOfMapStringToString" + }, + "ListOfStructs": { + "shape": "ListOfSimpleStructs" + }, + "MapOfStringToIntegerList": { + "shape": "MapOfStringToIntegerList" + }, + "MapOfStringToString": { + "shape": "MapOfStringToString" + }, + "MapOfStringToStruct": { + "shape": "MapOfStringToSimpleStruct" + }, + "MapOfEnumToEnum": { + "shape": "MapOfEnumToEnum" + }, + "TimestampMember": { + "shape": "Timestamp" + }, + "StructWithNestedTimestampMember": { + "shape": "StructWithTimestamp" + }, + "BlobArg": { + "shape": "BlobType" + }, + "StructWithNestedBlob": { + "shape": "StructWithNestedBlobType" + }, + "BlobMap": { + "shape": "BlobMapType" + }, + "ListOfBlobs": { + "shape": "ListOfBlobsType" + }, + "RecursiveStruct": { + "shape": "RecursiveStructType" + }, + "PolymorphicTypeWithSubTypes": { + "shape": "BaseType" + }, + "PolymorphicTypeWithoutSubTypes": { + "shape": "SubTypeOne" + }, + "SetPrefixedMember": { + "shape": "String" + }, + "UnionMember": { + "shape": "AllTypesUnionStructure" + } + } + }, + "GreetingWithErrorsOutput":{ + "type":"structure", + "members":{ + "greeting":{"shape":"String"} + } + }, + "ComplexError":{ + "type":"structure", + "members":{ + "TopLevel":{"shape":"String"}, + "Nested":{"shape":"ComplexNestedErrorData"} + }, + "exception":true + }, + "ComplexNestedErrorData":{ + "type":"structure", + "members":{ + "Foo":{"shape":"String"} + } + }, + "InvalidGreeting":{ + "type":"structure", + "members":{ + "Message":{"shape":"String"} + }, + "exception":true + } + } +} diff --git a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rpcv2cbor/RpcV2CborUserAgentTest.java similarity index 71% rename from test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java rename to test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rpcv2cbor/RpcV2CborUserAgentTest.java index 15ea3a4db98c..070158445a35 100644 --- a/test/protocol-tests/src/test/java/software/amazon/awssdk/protocol/tests/ProtocolRpcV2CborUserAgentTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/rpcv2cbor/RpcV2CborUserAgentTest.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.protocol.tests; +package software.amazon.awssdk.services.rpcv2cbor; import static org.assertj.core.api.Assertions.assertThat; import static software.amazon.awssdk.core.useragent.BusinessMetricCollection.METRIC_SEARCH_PATTERN; @@ -28,22 +28,28 @@ import software.amazon.awssdk.http.SdkHttpRequest; import software.amazon.awssdk.http.SdkHttpResponse; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2Client; import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; +import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2AsyncClient; +import software.amazon.awssdk.services.protocolsmithyrpcv2.ProtocolSmithyrpcv2Client; +import software.amazon.awssdk.testutils.service.http.MockAsyncHttpClient; import software.amazon.awssdk.testutils.service.http.MockSyncHttpClient; import software.amazon.awssdk.utils.StringInputStream; -class ProtocolRpcV2CborUserAgentTest { +class RpcV2CborUserAgentTest { private static final String USER_AGENT_HEADER_NAME = "User-Agent"; private static final StaticCredentialsProvider CREDENTIALS_PROVIDER = StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid")); private MockSyncHttpClient mockHttpClient; + private MockAsyncHttpClient mockAsyncHttpClient; @BeforeEach public void setup() { mockHttpClient = new MockSyncHttpClient(); mockHttpClient.stubNextResponse(mockResponse()); + + mockAsyncHttpClient = new MockAsyncHttpClient(); + mockAsyncHttpClient.stubNextResponse(mockResponse()); } @Test @@ -60,6 +66,20 @@ void when_rpcV2CborProtocolIsUsed_correctMetricIsAdded() { assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply("M")); } + @Test + void when_rpcV2CborProtocolIsUsedAsync_correctMetricIsAdded() { + ProtocolSmithyrpcv2AsyncClient asyncClient = ProtocolSmithyrpcv2AsyncClient.builder() + .region(Region.US_WEST_2) + .credentialsProvider(CREDENTIALS_PROVIDER) + .httpClient(mockAsyncHttpClient) + .build(); + + asyncClient.operationWithNoInputOrOutput(r -> {}).join(); + + String userAgent = getUserAgentFromLastAsyncRequest(); + assertThat(userAgent).matches(METRIC_SEARCH_PATTERN.apply("M")); + } + @Test void when_nonRpcV2CborProtocolIsUsed_rpcV2CborMetricIsNotAdded() { ProtocolRestJsonClient client = ProtocolRestJsonClient.builder() @@ -83,6 +103,15 @@ private String getUserAgentFromLastRequest() { return userAgentHeaders.get(0); } + private String getUserAgentFromLastAsyncRequest() { + SdkHttpRequest lastRequest = mockAsyncHttpClient.getLastRequest(); + assertThat(lastRequest).isNotNull(); + + List userAgentHeaders = lastRequest.headers().get(USER_AGENT_HEADER_NAME); + assertThat(userAgentHeaders).isNotNull().hasSize(1); + return userAgentHeaders.get(0); + } + private static HttpExecuteResponse mockResponse() { return HttpExecuteResponse.builder() .response(SdkHttpResponse.builder().statusCode(200).build()) From 1314d4929e7e4456a806ad7292b456a4a9b2e788 Mon Sep 17 00:00:00 2001 From: Saranya Somepalli Date: Fri, 17 Oct 2025 15:00:06 -0700 Subject: [PATCH 9/9] PR feedback --- .../awscore/internal/AwsExecutionContextBuilder.java | 3 ++- test/codegen-generated-classes-test/pom.xml | 11 +++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java index 3b62705226d4..067e48926990 100644 --- a/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java +++ b/core/aws-core/src/main/java/software/amazon/awssdk/awscore/internal/AwsExecutionContextBuilder.java @@ -16,6 +16,7 @@ package software.amazon.awssdk.awscore.internal; import static software.amazon.awssdk.auth.signer.internal.util.SignerMethodResolver.resolveSigningMethodUsed; +import static software.amazon.awssdk.awscore.internal.AwsServiceProtocol.SMITHY_RPC_V2_CBOR; import static software.amazon.awssdk.core.client.config.SdkClientOption.RETRY_POLICY; import static software.amazon.awssdk.core.client.config.SdkClientOption.RETRY_STRATEGY; import static software.amazon.awssdk.core.interceptor.SdkExecutionAttribute.RESOLVED_CHECKSUM_SPECS; @@ -370,6 +371,6 @@ private static EndpointProvider resolveEndpointProvider(SdkRequest request, private static boolean isRpcV2CborProtocol(SdkProtocolMetadata protocolMetadata) { return protocolMetadata != null && - "smithy-rpc-v2-cbor".equals(protocolMetadata.serviceProtocol()); + SMITHY_RPC_V2_CBOR.toString().equals(protocolMetadata.serviceProtocol()); } } diff --git a/test/codegen-generated-classes-test/pom.xml b/test/codegen-generated-classes-test/pom.xml index 1e55037bb0f6..a7717e5b02a3 100644 --- a/test/codegen-generated-classes-test/pom.xml +++ b/test/codegen-generated-classes-test/pom.xml @@ -145,6 +145,11 @@ retries-spi ${awsjavasdk.version} + + software.amazon.awssdk + smithy-rpcv2-protocol + ${awsjavasdk.version} + netty-nio-client software.amazon.awssdk @@ -279,12 +284,6 @@ mockito-junit-jupiter test - - software.amazon.awssdk - smithy-rpcv2-protocol - ${awsjavasdk.version} - compile -