diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java index b7045285fd95..084c9415ed8d 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientClass.java @@ -32,6 +32,7 @@ import java.net.URI; import java.nio.ByteBuffer; import java.util.List; +import java.util.Optional; import java.util.concurrent.Executor; import java.util.stream.Collectors; import javax.lang.model.element.Modifier; @@ -61,11 +62,17 @@ import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRefreshCache; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRequest; +import software.amazon.awssdk.core.internal.util.MetricUtils; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory; import software.amazon.awssdk.utils.CompletableFutureUtils; import software.amazon.awssdk.utils.FunctionalUtils; public final class AsyncClientClass extends AsyncClientInterface { + private static final String PUBLISHER_NAME = "metricPublisher"; + private static final String METRIC_COLLECTOR_NAME = "apiCallMetricCollector"; private final IntermediateModel model; private final PoetExtensions poetExtensions; private final ClassName className; @@ -190,9 +197,18 @@ private MethodSpec closeMethod() { protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, OperationModel opModel) { builder.addModifiers(Modifier.PUBLIC) - .addAnnotation(Override.class) - .beginControlFlow("try") - .addCode(ClientClassUtils.callApplySignerOverrideMethod(opModel)) + .addAnnotation(Override.class); + + builder.addStatement("$1T $2N = $1T.create($3S)", + MetricCollector.class, METRIC_COLLECTOR_NAME, "ApiCall"); + builder.beginControlFlow("try"); + + builder.addStatement("$N.reportMetric($T.$L, $S)", METRIC_COLLECTOR_NAME, CoreMetric.class, "SERVICE_ID", + model.getMetadata().getServiceId()); + builder.addStatement("$N.reportMetric($T.$L, $S)", METRIC_COLLECTOR_NAME, CoreMetric.class, "OPERATION_NAME", + opModel.getOperationName()); + + builder.addCode(ClientClassUtils.callApplySignerOverrideMethod(opModel)) .addCode(ClientClassUtils.addEndpointTraitCode(opModel)) .addCode(protocolSpec.responseHandler(model, opModel)); protocolSpec.errorResponseHandler(opModel).ifPresent(builder::addCode); @@ -224,8 +240,17 @@ protected MethodSpec.Builder operationBody(MethodSpec.Builder builder, Operation "() -> $N.exceptionOccurred(t))", paramName); } - return builder.addStatement("return $T.failedFuture(t)", CompletableFutureUtils.class) - .endControlFlow(); + builder.addStatement("$T<$T> $N = $T.resolvePublisher(clientConfiguration, $N.overrideConfiguration().orElse(null))", + Optional.class, + MetricPublisher.class, + PUBLISHER_NAME, + MetricUtils.class, + opModel.getInput().getVariableName()) + .addStatement("$N.ifPresent(p -> p.publish($N.collect()))", PUBLISHER_NAME, "apiCallMetricCollector") + .addStatement("return $T.failedFuture(t)", CompletableFutureUtils.class) + .endControlFlow(); + + return builder; } @Override diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java index 3b36a1e330f2..d9eeabfad3f9 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/AsyncClientInterface.java @@ -47,7 +47,6 @@ import software.amazon.awssdk.core.SdkClient; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; -import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.regions.providers.DefaultAwsRegionProviderChain; public class AsyncClientInterface implements ClassSpec { @@ -285,12 +284,6 @@ private MethodSpec traditionalMethod(OperationModel opModel) { .addParameter(requestType, opModel.getInput().getVariableName()) .addJavadoc(opModel.getDocs(model, ClientType.ASYNC)); - - String metricCollectorName = "apiCallMetricCollector"; - - builder.addStatement("$1T $2N = $1T.create($3S)", - MetricCollector.class, metricCollectorName, "ApiCall"); - if (opModel.hasStreamingInput()) { builder.addParameter(ClassName.get(AsyncRequestBody.class), "requestBody"); } else if (opModel.hasEventStreamInput()) { 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 1dd17e93ea4c..3a68c19482a2 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 @@ -28,6 +28,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; 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; @@ -266,6 +267,8 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper asyncResponseTransformerVariable(isStreaming, isRestJson, opModel)); String whenComplete = whenCompleteBody(opModel, customerResponseHandler); if (!whenComplete.isEmpty()) { + builder.addStatement("$T requestOverrideConfig = $L.overrideConfiguration().orElse(null)", + AwsRequestOverrideConfiguration.class, opModel.getInput().getVariableName()); builder.add("executeFuture$L;", whenComplete); } if (opModel.hasEventStreamOutput()) { @@ -326,7 +329,7 @@ private String whenCompleteBody(OperationModel operationModel, String responseHa return streamingOutputWhenComplete(responseHandlerName); } else { // Non streaming can just return the future as is - return ""; + return publishMetricsWhenComplete(); } } @@ -336,6 +339,7 @@ private String whenCompleteBody(OperationModel operationModel, String responseHa * {@link EventStreamAsyncResponseTransformer}. Failure is notified via the normal future (the one returned by the client * handler). * + * * @param responseHandlerName Variable name of response handler customer passed in. * @return whenComplete to append to future. */ @@ -347,12 +351,12 @@ private String eventStreamOutputWhenComplete(String responseHandlerName) { + " } finally {" + " future.completeExceptionally(e);" + " }" - + " }%n" - + "})", responseHandlerName); + + " }" + + "%s" + + "})", responseHandlerName, publishMetrics()); } - @Override public Optional createErrorResponseHandler() { ClassName httpResponseHandler = ClassName.get(HttpResponseHandler.class); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java index 38ba7afc1f8f..3cd7191e455e 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/ProtocolSpec.java @@ -155,7 +155,8 @@ default String streamingOutputWhenComplete(String responseHandlerName) { + " runAndLogError(log, \"Exception thrown in exceptionOccurred callback, ignoring\", () " + "-> %s.exceptionOccurred(e));%n" + " }%n" - + "})", responseHandlerName); + + "%s" + + "})", responseHandlerName, publishMetrics()); } @@ -177,4 +178,16 @@ default TypeName executeFutureValueType(OperationModel opModel, PoetExtensions p default TypeName getPojoResponseType(OperationModel opModel, PoetExtensions poetExtensions) { return poetExtensions.getModelClass(opModel.getReturnType().getReturnType()); } + + default String publishMetricsWhenComplete() { + return String.format(".whenComplete((r, e) -> {%n" + + "%s%n" + + "})", publishMetrics()); + } + + default String publishMetrics() { + return "Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, " + + "requestOverrideConfig);\n" + + "metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect()));"; + } } diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java index f5a1763a4d1f..46aa35bcf7a0 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/QueryProtocolSpec.java @@ -24,6 +24,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; import javax.lang.model.element.Modifier; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.awscore.exception.AwsServiceException; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.OperationModel; @@ -154,9 +155,12 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper "errorResponseHandler", opModel.getInput().getVariableName(), opModel.hasStreamingOutput() ? ", asyncResponseTransformer" : ""); - + builder.addStatement("$T requestOverrideConfig = $L.overrideConfiguration().orElse(null)", + AwsRequestOverrideConfiguration.class, opModel.getInput().getVariableName()); if (opModel.hasStreamingOutput()) { builder.add("executeFuture$L;", streamingOutputWhenComplete("asyncResponseTransformer")); + } else { + builder.add("executeFuture$L;", publishMetricsWhenComplete()); } builder.addStatement("return executeFuture"); return builder.build(); diff --git a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java index 9eacd267a14c..a543a0fad876 100644 --- a/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java +++ b/codegen/src/main/java/software/amazon/awssdk/codegen/poet/client/specs/XmlProtocolSpec.java @@ -20,6 +20,7 @@ import com.squareup.javapoet.ParameterizedTypeName; import com.squareup.javapoet.TypeName; import java.util.Optional; +import software.amazon.awssdk.awscore.AwsRequestOverrideConfiguration; import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel; import software.amazon.awssdk.codegen.model.intermediate.OperationModel; import software.amazon.awssdk.codegen.poet.PoetExtensions; @@ -169,8 +170,12 @@ public CodeBlock asyncExecutionHandler(IntermediateModel intermediateModel, Oper opModel.getInput().getVariableName(), opModel.hasStreamingOutput() ? ", asyncResponseTransformer" : ""); + builder.addStatement("$T requestOverrideConfig = $L.overrideConfiguration().orElse(null)", + AwsRequestOverrideConfiguration.class, opModel.getInput().getVariableName()); if (opModel.hasStreamingOutput()) { builder.add("executeFuture$L;", streamingOutputWhenComplete("asyncResponseTransformer")); + } else { + builder.add("executeFuture$L;", publishMetricsWhenComplete()); } builder.addStatement("return executeFuture"); return builder.build(); diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-async-client-class.java index 2b0c659a467f..0a0f07dfbffc 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-async-client-class.java @@ -3,6 +3,7 @@ import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; import java.nio.ByteBuffer; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -33,11 +34,14 @@ import software.amazon.awssdk.core.client.handler.AttachHttpMetadataResponseHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.internal.util.MetricUtils; +import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.protocol.VoidSdkResponse; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; import software.amazon.awssdk.core.signer.Signer; import software.amazon.awssdk.core.util.VersionInfo; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.protocols.core.ExceptionMetadata; import software.amazon.awssdk.protocols.json.AwsJsonProtocol; import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory; @@ -154,6 +158,8 @@ public final String serviceName() { public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); String hostPrefix = "{StringMember}-foo."; Validate.paramNotBlank(aPostOperationRequest.stringMember(), "StringMember"); String resolvedHostExpression = String.format("%s-foo.", aPostOperationRequest.stringMember()); @@ -172,8 +178,17 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = aPostOperationRequest.overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, aPostOperationRequest + .overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -206,6 +221,8 @@ public CompletableFuture aPostOperationWithOut APostOperationWithOutputRequest aPostOperationWithOutputRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -221,8 +238,18 @@ public CompletableFuture aPostOperationWithOut .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(aPostOperationWithOutputRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = aPostOperationWithOutputRequest.overrideConfiguration() + .orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + aPostOperationWithOutputRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -251,6 +278,8 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest Publisher requestStream, EventStreamOperationResponseHandler asyncResponseHandler) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperation"); eventStreamOperationRequest = applySignerOverride(eventStreamOperationRequest, EventStreamAws4Signer.create()); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -293,6 +322,8 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest .withFullDuplex(true).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withInput(eventStreamOperationRequest), restAsyncResponseTransformer); + AwsRequestOverrideConfiguration requestOverrideConfig = eventStreamOperationRequest.overrideConfiguration().orElse( + null); executeFuture.whenComplete((r, e) -> { if (e != null) { try { @@ -301,11 +332,17 @@ public CompletableFuture eventStreamOperation(EventStreamOperationRequest future.completeExceptionally(e); } } + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); }); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + eventStreamOperationRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -336,6 +373,8 @@ public CompletableFuture eventStreamO Publisher requestStream) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperationWithOnlyInput"); eventStreamOperationWithOnlyInputRequest = applySignerOverride(eventStreamOperationWithOnlyInputRequest, EventStreamAws4Signer.create()); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) @@ -360,8 +399,18 @@ public CompletableFuture eventStreamO .withAsyncRequestBody(software.amazon.awssdk.core.async.AsyncRequestBody.fromPublisher(adapted)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(eventStreamOperationWithOnlyInputRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = eventStreamOperationWithOnlyInputRequest + .overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + eventStreamOperationWithOnlyInputRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -392,6 +441,8 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( EventStreamOperationWithOnlyOutputResponseHandler asyncResponseHandler) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "EventStreamOperationWithOnlyOutput"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -427,6 +478,8 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( .withMarshaller(new EventStreamOperationWithOnlyOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(eventStreamOperationWithOnlyOutputRequest), restAsyncResponseTransformer); + AwsRequestOverrideConfiguration requestOverrideConfig = eventStreamOperationWithOnlyOutputRequest + .overrideConfiguration().orElse(null); executeFuture.whenComplete((r, e) -> { if (e != null) { try { @@ -435,11 +488,17 @@ public CompletableFuture eventStreamOperationWithOnlyOutput( future.completeExceptionally(e); } } + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); }); return CompletableFutureUtils.forwardExceptionTo(future, executeFuture); } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseHandler.exceptionOccurred(t)); + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + eventStreamOperationWithOnlyOutputRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -472,6 +531,8 @@ public CompletableFuture getWithoutRequiredMe GetWithoutRequiredMembersRequest getWithoutRequiredMembersRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "GetWithoutRequiredMembers"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -487,8 +548,18 @@ public CompletableFuture getWithoutRequiredMe .withMarshaller(new GetWithoutRequiredMembersRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(getWithoutRequiredMembersRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = getWithoutRequiredMembersRequest.overrideConfiguration() + .orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + getWithoutRequiredMembersRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -518,6 +589,8 @@ public CompletableFuture paginatedOpera PaginatedOperationWithResultKeyRequest paginatedOperationWithResultKeyRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithResultKey"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -533,8 +606,18 @@ public CompletableFuture paginatedOpera .withMarshaller(new PaginatedOperationWithResultKeyRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(paginatedOperationWithResultKeyRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = paginatedOperationWithResultKeyRequest + .overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + paginatedOperationWithResultKeyRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -561,7 +644,7 @@ public CompletableFuture paginatedOpera * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
@@ -571,19 +654,19 @@ public CompletableFuture paginatedOpera
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -641,6 +724,8 @@ public CompletableFuture paginatedOp PaginatedOperationWithoutResultKeyRequest paginatedOperationWithoutResultKeyRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "PaginatedOperationWithoutResultKey"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -656,8 +741,18 @@ public CompletableFuture paginatedOp .withMarshaller(new PaginatedOperationWithoutResultKeyRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(paginatedOperationWithoutResultKeyRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = paginatedOperationWithoutResultKeyRequest + .overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + paginatedOperationWithoutResultKeyRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -684,7 +779,7 @@ public CompletableFuture paginatedOp * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithoutResultKeyPublisher publisher = client.paginatedOperationWithoutResultKeyPaginator(request);
@@ -694,19 +789,19 @@ public CompletableFuture paginatedOp
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithoutResultKeyPublisher publisher = client.paginatedOperationWithoutResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -769,6 +864,8 @@ public CompletableFuture streamingInputOperatio StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -787,8 +884,18 @@ public CompletableFuture streamingInputOperatio .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = streamingInputOperationRequest.overrideConfiguration() + .orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + streamingInputOperationRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -828,6 +935,8 @@ public CompletableFuture streamingInputOutputOperation( AsyncResponseTransformer asyncResponseTransformer) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOutputOperation"); streamingInputOutputOperationRequest = applySignerOverride(streamingInputOutputOperationRequest, Aws4UnsignedPayloadSigner.create()); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) @@ -851,16 +960,24 @@ public CompletableFuture streamingInputOutputOperation( .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withAsyncRequestBody(requestBody).withInput(streamingInputOutputOperationRequest), asyncResponseTransformer); + AwsRequestOverrideConfiguration requestOverrideConfig = streamingInputOutputOperationRequest.overrideConfiguration() + .orElse(null); executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseTransformer.exceptionOccurred(e)); } + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); }); return executeFuture; } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseTransformer.exceptionOccurred(t)); + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + streamingInputOutputOperationRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -895,6 +1012,8 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer asyncResponseTransformer) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Json Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(true) .isPayloadJson(false).build(); @@ -910,16 +1029,24 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(streamingOutputOperationRequest), asyncResponseTransformer); + AwsRequestOverrideConfiguration requestOverrideConfig = streamingOutputOperationRequest.overrideConfiguration() + .orElse(null); executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseTransformer.exceptionOccurred(e)); } + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); }); return executeFuture; } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseTransformer.exceptionOccurred(t)); + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + streamingOutputOperationRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java index da4ca5d9f07b..728e1842e8ab 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-endpoint-discovery-async.java @@ -3,11 +3,13 @@ import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; import java.net.URI; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; 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.config.AwsClientOption; import software.amazon.awssdk.awscore.client.handler.AwsAsyncClientHandler; import software.amazon.awssdk.awscore.exception.AwsServiceException; @@ -18,7 +20,10 @@ import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRefreshCache; import software.amazon.awssdk.core.endpointdiscovery.EndpointDiscoveryRequest; import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.internal.util.MetricUtils; +import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.protocols.json.AwsJsonProtocol; import software.amazon.awssdk.protocols.json.AwsJsonProtocolFactory; import software.amazon.awssdk.protocols.json.BaseAwsJsonProtocolFactory; @@ -92,6 +97,8 @@ public final String serviceName() { public CompletableFuture describeEndpoints(DescribeEndpointsRequest describeEndpointsRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "AwsEndpointDiscoveryTest"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "DescribeEndpoints"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -107,8 +114,17 @@ public CompletableFuture describeEndpoints(DescribeEn .withMarshaller(new DescribeEndpointsRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(describeEndpointsRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = describeEndpointsRequest.overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + describeEndpointsRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -136,6 +152,8 @@ public CompletableFuture testDiscovery TestDiscoveryIdentifiersRequiredRequest testDiscoveryIdentifiersRequiredRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "AwsEndpointDiscoveryTest"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "TestDiscoveryIdentifiersRequired"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -159,8 +177,18 @@ public CompletableFuture testDiscovery .withMarshaller(new TestDiscoveryIdentifiersRequiredRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .discoveredEndpoint(cachedEndpoint).withInput(testDiscoveryIdentifiersRequiredRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = testDiscoveryIdentifiersRequiredRequest + .overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + testDiscoveryIdentifiersRequiredRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -187,6 +215,8 @@ public CompletableFuture testDiscoveryOptional( TestDiscoveryOptionalRequest testDiscoveryOptionalRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "AwsEndpointDiscoveryTest"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "TestDiscoveryOptional"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -210,8 +240,18 @@ public CompletableFuture testDiscoveryOptional( .withMarshaller(new TestDiscoveryOptionalRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .discoveredEndpoint(cachedEndpoint).withInput(testDiscoveryOptionalRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = testDiscoveryOptionalRequest.overrideConfiguration().orElse( + null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + testDiscoveryOptionalRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -238,6 +278,8 @@ public CompletableFuture testDiscoveryRequired( TestDiscoveryRequiredRequest testDiscoveryRequiredRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "AwsEndpointDiscoveryTest"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "TestDiscoveryRequired"); JsonOperationMetadata operationMetadata = JsonOperationMetadata.builder().hasStreamingSuccessResponse(false) .isPayloadJson(true).build(); @@ -261,8 +303,18 @@ public CompletableFuture testDiscoveryRequired( .withMarshaller(new TestDiscoveryRequiredRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .discoveredEndpoint(cachedEndpoint).withInput(testDiscoveryRequiredRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = testDiscoveryRequiredRequest.overrideConfiguration().orElse( + null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + testDiscoveryRequiredRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface.java index 0024827d14a9..e97f69cd5896 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-json-async-client-interface.java @@ -8,7 +8,6 @@ import software.amazon.awssdk.core.SdkClient; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; -import software.amazon.awssdk.metrics.MetricCollector; import software.amazon.awssdk.services.json.model.APostOperationRequest; import software.amazon.awssdk.services.json.model.APostOperationResponse; import software.amazon.awssdk.services.json.model.APostOperationWithOutputRequest; @@ -86,7 +85,6 @@ static JsonAsyncClientBuilder builder() { * API Documentation */ default CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -148,7 +146,6 @@ default CompletableFuture aPostOperation(Consumer aPostOperationWithOutput( APostOperationWithOutputRequest aPostOperationWithOutputRequest) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -209,7 +206,6 @@ default CompletableFuture aPostOperationWithOu */ default CompletableFuture eventStreamOperation(EventStreamOperationRequest eventStreamOperationRequest, Publisher requestStream, EventStreamOperationResponseHandler asyncResponseHandler) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -268,7 +264,6 @@ default CompletableFuture eventStreamOperation( default CompletableFuture eventStreamOperationWithOnlyInput( EventStreamOperationWithOnlyInputRequest eventStreamOperationWithOnlyInputRequest, Publisher requestStream) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -329,7 +324,6 @@ default CompletableFuture eventStream default CompletableFuture eventStreamOperationWithOnlyOutput( EventStreamOperationWithOnlyOutputRequest eventStreamOperationWithOnlyOutputRequest, EventStreamOperationWithOnlyOutputResponseHandler asyncResponseHandler) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -392,7 +386,6 @@ default CompletableFuture eventStreamOperationWithOnlyOutput( */ default CompletableFuture getWithoutRequiredMembers( GetWithoutRequiredMembersRequest getWithoutRequiredMembersRequest) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -454,7 +447,6 @@ default CompletableFuture getWithoutRequiredM */ default CompletableFuture paginatedOperationWithResultKey( PaginatedOperationWithResultKeyRequest paginatedOperationWithResultKeyRequest) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -535,7 +527,7 @@ default CompletableFuture paginatedOper * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
@@ -545,19 +537,19 @@ default CompletableFuture paginatedOper
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -610,7 +602,7 @@ default PaginatedOperationWithResultKeyPublisher paginatedOperationWithResultKey * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
@@ -620,19 +612,19 @@ default PaginatedOperationWithResultKeyPublisher paginatedOperationWithResultKey
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -687,7 +679,7 @@ default PaginatedOperationWithResultKeyPublisher paginatedOperationWithResultKey * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
@@ -697,19 +689,19 @@ default PaginatedOperationWithResultKeyPublisher paginatedOperationWithResultKey
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithResultKeyPublisher publisher = client.paginatedOperationWithResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -771,7 +763,6 @@ default PaginatedOperationWithResultKeyPublisher paginatedOperationWithResultKey */ default CompletableFuture paginatedOperationWithoutResultKey( PaginatedOperationWithoutResultKeyRequest paginatedOperationWithoutResultKeyRequest) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -829,7 +820,7 @@ default CompletableFuture paginatedO * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithoutResultKeyPublisher publisher = client.paginatedOperationWithoutResultKeyPaginator(request);
@@ -839,19 +830,19 @@ default CompletableFuture paginatedO
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithoutResultKeyPublisher publisher = client.paginatedOperationWithoutResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -906,7 +897,7 @@ default PaginatedOperationWithoutResultKeyPublisher paginatedOperationWithoutRes * The following are few ways to use the response class: *

* 1) Using the subscribe helper method - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithoutResultKeyPublisher publisher = client.paginatedOperationWithoutResultKeyPaginator(request);
@@ -916,19 +907,19 @@ default PaginatedOperationWithoutResultKeyPublisher paginatedOperationWithoutRes
      * 
* * 2) Using a custom subscriber - * + * *
      * {@code
      * software.amazon.awssdk.services.json.paginators.PaginatedOperationWithoutResultKeyPublisher publisher = client.paginatedOperationWithoutResultKeyPaginator(request);
      * publisher.subscribe(new Subscriber() {
-     * 
+     *
      * public void onSubscribe(org.reactivestreams.Subscriber subscription) { //... };
-     * 
-     * 
+     *
+     *
      * public void onNext(software.amazon.awssdk.services.json.model.PaginatedOperationWithoutResultKeyResponse response) { //... };
      * });}
      * 
- * + * * As the response is a publisher, it can work well with third party reactive streams implementations like RxJava2. *

* Please notice that the configuration of MaxResults won't limit the number of results you get with the @@ -994,7 +985,6 @@ default PaginatedOperationWithoutResultKeyPublisher paginatedOperationWithoutRes */ default CompletableFuture streamingInputOperation( StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -1131,7 +1121,6 @@ default CompletableFuture streamingInputOperati default CompletableFuture streamingInputOutputOperation( StreamingInputOutputOperationRequest streamingInputOutputOperationRequest, AsyncRequestBody requestBody, AsyncResponseTransformer asyncResponseTransformer) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } @@ -1282,7 +1271,6 @@ default CompletableFuture streamingInputO default CompletableFuture streamingOutputOperation( StreamingOutputOperationRequest streamingOutputOperationRequest, AsyncResponseTransformer asyncResponseTransformer) { - MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); throw new UnsupportedOperationException(); } diff --git a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java index e96ac5147355..c8b53faf5172 100644 --- a/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java +++ b/codegen/src/test/resources/software/amazon/awssdk/codegen/poet/client/test-query-async-client-class.java @@ -2,11 +2,13 @@ import static software.amazon.awssdk.utils.FunctionalUtils.runAndLogError; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.slf4j.Logger; 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.core.async.AsyncRequestBody; @@ -15,8 +17,11 @@ import software.amazon.awssdk.core.client.handler.AsyncClientHandler; import software.amazon.awssdk.core.client.handler.ClientExecutionParams; import software.amazon.awssdk.core.http.HttpResponseHandler; +import software.amazon.awssdk.core.internal.util.MetricUtils; +import software.amazon.awssdk.core.metrics.CoreMetric; import software.amazon.awssdk.core.runtime.transform.AsyncStreamingRequestMarshaller; import software.amazon.awssdk.metrics.MetricCollector; +import software.amazon.awssdk.metrics.MetricPublisher; import software.amazon.awssdk.protocols.core.ExceptionMetadata; import software.amazon.awssdk.protocols.query.AwsQueryProtocolFactory; import software.amazon.awssdk.services.query.model.APostOperationRequest; @@ -89,6 +94,8 @@ public final String serviceName() { public CompletableFuture aPostOperation(APostOperationRequest aPostOperationRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperation"); String hostPrefix = "foo-"; String resolvedHostExpression = "foo-"; @@ -103,8 +110,17 @@ public CompletableFuture aPostOperation(APostOperationRe .withMarshaller(new APostOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .hostPrefixExpression(resolvedHostExpression).withInput(aPostOperationRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = aPostOperationRequest.overrideConfiguration().orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, aPostOperationRequest + .overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -137,6 +153,8 @@ public CompletableFuture aPostOperationWithOut APostOperationWithOutputRequest aPostOperationWithOutputRequest) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "APostOperationWithOutput"); HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(APostOperationWithOutputResponse::builder); @@ -149,8 +167,18 @@ public CompletableFuture aPostOperationWithOut .withMarshaller(new APostOperationWithOutputRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(aPostOperationWithOutputRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = aPostOperationWithOutputRequest.overrideConfiguration() + .orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + aPostOperationWithOutputRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -184,6 +212,8 @@ public CompletableFuture streamingInputOperatio StreamingInputOperationRequest streamingInputOperationRequest, AsyncRequestBody requestBody) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingInputOperation"); HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(StreamingInputOperationResponse::builder); @@ -199,8 +229,18 @@ public CompletableFuture streamingInputOperatio .asyncRequestBody(requestBody).build()).withResponseHandler(responseHandler) .withErrorResponseHandler(errorResponseHandler).withAsyncRequestBody(requestBody) .withInput(streamingInputOperationRequest)); + AwsRequestOverrideConfiguration requestOverrideConfig = streamingInputOperationRequest.overrideConfiguration() + .orElse(null); + executeFuture.whenComplete((r, e) -> { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); + }); return executeFuture; } catch (Throwable t) { + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + streamingInputOperationRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } @@ -235,6 +275,8 @@ public CompletableFuture streamingOutputOperation( AsyncResponseTransformer asyncResponseTransformer) { MetricCollector apiCallMetricCollector = MetricCollector.create("ApiCall"); try { + apiCallMetricCollector.reportMetric(CoreMetric.SERVICE_ID, "Query Service"); + apiCallMetricCollector.reportMetric(CoreMetric.OPERATION_NAME, "StreamingOutputOperation"); HttpResponseHandler responseHandler = protocolFactory .createResponseHandler(StreamingOutputOperationResponse::builder); @@ -247,16 +289,24 @@ public CompletableFuture streamingOutputOperation( .withMarshaller(new StreamingOutputOperationRequestMarshaller(protocolFactory)) .withResponseHandler(responseHandler).withErrorResponseHandler(errorResponseHandler) .withInput(streamingOutputOperationRequest), asyncResponseTransformer); + AwsRequestOverrideConfiguration requestOverrideConfig = streamingOutputOperationRequest.overrideConfiguration() + .orElse(null); executeFuture.whenComplete((r, e) -> { if (e != null) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseTransformer.exceptionOccurred(e)); } + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + requestOverrideConfig); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); }); return executeFuture; } catch (Throwable t) { runAndLogError(log, "Exception thrown in exceptionOccurred callback, ignoring", () -> asyncResponseTransformer.exceptionOccurred(t)); + Optional metricPublisher = MetricUtils.resolvePublisher(clientConfiguration, + streamingOutputOperationRequest.overrideConfiguration().orElse(null)); + metricPublisher.ifPresent(p -> p.publish(apiCallMetricCollector.collect())); return CompletableFutureUtils.failedFuture(t); } } diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java index dcd0554cdde5..629b57524685 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java @@ -26,6 +26,7 @@ import software.amazon.awssdk.core.SdkRequest; import software.amazon.awssdk.core.client.config.SdkClientConfiguration; import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.utils.OptionalUtils; import software.amazon.awssdk.utils.Pair; /** @@ -44,6 +45,7 @@ private MetricUtils() { * @param requestConfig The request override configuration. * @return The metric publisher to use. */ + //TODO: remove this and use the overload instead public static Optional resolvePublisher(SdkClientConfiguration clientConfig, SdkRequest requestConfig) { Optional requestOverride = requestConfig.overrideConfiguration() @@ -54,6 +56,22 @@ public static Optional resolvePublisher(SdkClientConfiguration return Optional.ofNullable(clientConfig.option(METRIC_PUBLISHER)); } + /** + * Resolve the correct metric publisher to use. The publisher set on the request always takes precedence. + * + * @param clientConfig The client configuration. + * @param requestConfig The request override configuration. + * @return The metric publisher to use. + */ + public static Optional resolvePublisher(SdkClientConfiguration clientConfig, + RequestOverrideConfiguration requestConfig) { + if (requestConfig != null) { + return OptionalUtils.firstPresent(requestConfig.metricPublisher(), () -> clientConfig.option(METRIC_PUBLISHER)); + } + + return Optional.ofNullable(clientConfig.option(METRIC_PUBLISHER)); + } + /** * Measure the duration of the given callable. * diff --git a/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java b/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java index 857a607b6de1..e0aa69d59a0e 100644 --- a/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java +++ b/core/sdk-core/src/main/java/software/amazon/awssdk/core/metrics/CoreMetric.java @@ -76,7 +76,7 @@ public final class CoreMetric { /** * The exception thrown during request execution. Note this may be a service - * error that has been unmarshalled, or a clientside exception. + * error that has been unmarshalled, or a client side exception. */ public static final SdkMetric EXCEPTION = metric("Exception", Throwable.class); diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/AsyncCoreMetricsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/AsyncCoreMetricsTest.java new file mode 100644 index 000000000000..73d52ba22b38 --- /dev/null +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/AsyncCoreMetricsTest.java @@ -0,0 +1,158 @@ +/* + * 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.services.metrics; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import java.io.IOException; +import java.net.URI; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; +import software.amazon.awssdk.core.metrics.CoreMetric; +import software.amazon.awssdk.metrics.MetricCollection; +import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonAsyncClient; +import software.amazon.awssdk.services.protocolrestjson.model.ProtocolRestJsonException; + +@RunWith(MockitoJUnitRunner.class) +public class AsyncCoreMetricsTest { + private static final String SERVICE_ID = "AmazonProtocolRestJson"; + private static final String REQUEST_ID = "req-id"; + private static final String EXTENDED_REQUEST_ID = "extended-id"; + + private static ProtocolRestJsonAsyncClient client; + + @Rule + public WireMockRule wireMock = new WireMockRule(0); + + @Mock + private AwsCredentialsProvider mockCredentialsProvider; + + @Mock + private MetricPublisher mockPublisher; + + @Before + public void setup() throws IOException { + client = ProtocolRestJsonAsyncClient.builder() + .credentialsProvider(mockCredentialsProvider) + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .overrideConfiguration(c -> c.metricPublisher(mockPublisher)) + .build(); + + when(mockCredentialsProvider.resolveCredentials()).thenAnswer(invocation -> { + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + return AwsBasicCredentials.create("foo", "bar"); + }); + } + + @After + public void teardown() { + if (client != null) { + client.close(); + } + client = null; + } + + @Test + public void apiCall_noConfiguredPublisher_succeeds() { + stubSuccessfulResponse(); + ProtocolRestJsonAsyncClient noPublisher = ProtocolRestJsonAsyncClient.builder() + .endpointOverride(URI.create("http://localhost:" + wireMock.port())) + .build(); + + noPublisher.allTypes().join(); + } + + @Test + public void apiCall_publisherOverriddenOnRequest_requestPublisherTakesPrecedence() { + stubSuccessfulResponse(); + MetricPublisher requestMetricPublisher = mock(MetricPublisher.class); + + client.allTypes(r -> r.overrideConfiguration(o -> o.metricPublisher(requestMetricPublisher))).join(); + + verify(requestMetricPublisher).publish(any(MetricCollection.class)); + verifyZeroInteractions(mockPublisher); + } + + @Test + public void apiCall_operationSuccessful_addsMetrics() { + stubSuccessfulResponse(); + client.allTypes().join(); + + ArgumentCaptor collectionCaptor = ArgumentCaptor.forClass(MetricCollection.class); + verify(mockPublisher).publish(collectionCaptor.capture()); + + MetricCollection capturedCollection = collectionCaptor.getValue(); + + assertThat(capturedCollection.name()).isEqualTo("ApiCall"); + assertThat(capturedCollection.metricValues(CoreMetric.SERVICE_ID)) + .containsExactly(SERVICE_ID); + assertThat(capturedCollection.metricValues(CoreMetric.OPERATION_NAME)) + .containsExactly("AllTypes"); + } + + @Test + public void apiCall_operationFailed_addsMetrics() { + stubErrorResponse(); + assertThatThrownBy(() -> client.allTypes().join()).hasCauseInstanceOf(ProtocolRestJsonException.class); + + ArgumentCaptor collectionCaptor = ArgumentCaptor.forClass(MetricCollection.class); + verify(mockPublisher).publish(collectionCaptor.capture()); + + MetricCollection capturedCollection = collectionCaptor.getValue(); + + assertThat(capturedCollection.name()).isEqualTo("ApiCall"); + assertThat(capturedCollection.metricValues(CoreMetric.SERVICE_ID)) + .containsExactly(SERVICE_ID); + assertThat(capturedCollection.metricValues(CoreMetric.OPERATION_NAME)) + .containsExactly("AllTypes"); + } + + private void stubSuccessfulResponse() { + stubFor(post(anyUrl()) + .willReturn(aResponse().withStatus(200) + .withBody("{}"))); + } + + private void stubErrorResponse() { + stubFor(post(anyUrl()) + .willReturn(aResponse().withStatus(500) + .withBody("{}"))); + } +} diff --git a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/CoreMetricsTest.java b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java similarity index 98% rename from test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/CoreMetricsTest.java rename to test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java index 4192ac63aa48..0937b423ade6 100644 --- a/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/protocolrestjson/CoreMetricsTest.java +++ b/test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.awssdk.services.protocolrestjson; +package software.amazon.awssdk.services.metrics; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; @@ -44,6 +44,7 @@ import software.amazon.awssdk.http.SdkHttpFullResponse; import software.amazon.awssdk.metrics.MetricCollection; import software.amazon.awssdk.metrics.MetricPublisher; +import software.amazon.awssdk.services.protocolrestjson.ProtocolRestJsonClient; import software.amazon.awssdk.services.protocolrestjson.model.EmptyModeledException; @RunWith(MockitoJUnitRunner.class)