Skip to content

Commit 07b0746

Browse files
committed
Create CollectionStages for SERVICE_ENDPOINT
1 parent ff09daf commit 07b0746

File tree

10 files changed

+169
-11
lines changed

10 files changed

+169
-11
lines changed

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonAsyncHttpClient.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncBeforeTransmissionExecutionInterceptorsStage;
3737
import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncExecutionFailureExceptionReportingStage;
3838
import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncRetryableStage;
39+
import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncServiceEndpointMetricCollectionStage;
3940
import software.amazon.awssdk.core.internal.http.pipeline.stages.AsyncSigningStage;
4041
import software.amazon.awssdk.core.internal.http.pipeline.stages.MakeAsyncHttpRequestStage;
4142
import software.amazon.awssdk.core.internal.http.pipeline.stages.MakeRequestImmutableStage;
@@ -180,7 +181,8 @@ public <OutputT> CompletableFuture<OutputT> execute(
180181
.then(async(() -> new AfterExecutionInterceptorsStage<>()))
181182
.wrappedWith(AsyncExecutionFailureExceptionReportingStage::new)
182183
.wrappedWith(AsyncApiCallTimeoutTrackingStage::new)
183-
.wrappedWith(AsyncApiCallMetricCollectionStage::new)::build)::build)
184+
.wrappedWith(AsyncApiCallMetricCollectionStage::new)
185+
.wrappedWith(AsyncServiceEndpointMetricCollectionStage::new)::build)::build)
184186
.build(httpClientDependencies)
185187
.execute(request, createRequestExecutionDependencies());
186188
} catch (RuntimeException e) {

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/AmazonSyncHttpClient.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import software.amazon.awssdk.core.internal.http.pipeline.stages.MergeCustomHeadersStage;
4444
import software.amazon.awssdk.core.internal.http.pipeline.stages.MergeCustomQueryParamsStage;
4545
import software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage;
46+
import software.amazon.awssdk.core.internal.http.pipeline.stages.ServiceEndpointAttemptMetricCollectionStage;
47+
import software.amazon.awssdk.core.internal.http.pipeline.stages.ServiceEndpointMetricCollectionStage;
4648
import software.amazon.awssdk.core.internal.http.pipeline.stages.SigningStage;
4749
import software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage;
4850
import software.amazon.awssdk.core.internal.http.pipeline.stages.UnwrapResponseContainer;
@@ -182,10 +184,13 @@ public <OutputT> OutputT execute(HttpResponseHandler<Response<OutputT>> response
182184
.wrappedWith(ApiCallAttemptTimeoutTrackingStage::new)
183185
.wrappedWith(TimeoutExceptionHandlingStage::new)
184186
.wrappedWith((deps, wrapped) -> new ApiCallAttemptMetricCollectionStage<>(wrapped))
187+
.wrappedWith((deps, wrapped) ->
188+
new ServiceEndpointAttemptMetricCollectionStage<>(wrapped))
185189
.wrappedWith(RetryableStage::new)::build)
186190
.wrappedWith(StreamManagingStage::new)
187191
.wrappedWith(ApiCallTimeoutTrackingStage::new)::build)
188192
.wrappedWith((deps, wrapped) -> new ApiCallMetricCollectionStage<>(wrapped))
193+
.wrappedWith((deps, wrapped) -> new ServiceEndpointMetricCollectionStage<>(wrapped))
189194
.then(() -> new UnwrapResponseContainer<>())
190195
.then(() -> new AfterExecutionInterceptorsStage<>())
191196
.wrappedWith(ExecutionFailureExceptionReportingStage::new)

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/ApiCallAttemptMetricCollectionStage.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package software.amazon.awssdk.core.internal.http.pipeline.stages;
1717

1818
import static software.amazon.awssdk.core.internal.util.MetricUtils.collectHttpMetrics;
19-
import static software.amazon.awssdk.core.internal.util.MetricUtils.collectHttpRequestMetrics;
2019
import static software.amazon.awssdk.core.internal.util.MetricUtils.createAttemptMetricsCollector;
2120

2221
import java.time.Duration;
@@ -48,8 +47,6 @@ public Response<OutputT> execute(SdkHttpFullRequest input, RequestExecutionConte
4847
context.attemptMetricCollector(apiCallAttemptMetrics);
4948
reportBackoffDelay(context);
5049

51-
collectHttpRequestMetrics(apiCallAttemptMetrics, input);
52-
5350
Response<OutputT> response = wrapped.execute(input, context);
5451

5552
collectHttpMetrics(apiCallAttemptMetrics, response.httpResponse());

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/http/pipeline/stages/AsyncApiCallAttemptMetricCollectionStage.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package software.amazon.awssdk.core.internal.http.pipeline.stages;
1717

1818
import static software.amazon.awssdk.core.internal.util.MetricUtils.collectHttpMetrics;
19-
import static software.amazon.awssdk.core.internal.util.MetricUtils.collectHttpRequestMetrics;
2019
import static software.amazon.awssdk.core.internal.util.MetricUtils.createAttemptMetricsCollector;
2120

2221
import java.time.Duration;
@@ -53,8 +52,6 @@ public CompletableFuture<Response<OutputT>> execute(SdkHttpFullRequest input,
5352
context.attemptMetricCollector(apiCallAttemptMetrics);
5453
reportBackoffDelay(context);
5554

56-
collectHttpRequestMetrics(apiCallAttemptMetrics, input);
57-
5855
CompletableFuture<Response<OutputT>> executeFuture = wrapped.execute(input, context);
5956
CompletableFuture<Response<OutputT>> metricsCollectedFuture = executeFuture.whenComplete((r, t) -> {
6057
if (t == null) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.core.internal.http.pipeline.stages;
17+
18+
import java.util.concurrent.CompletableFuture;
19+
import software.amazon.awssdk.annotations.SdkInternalApi;
20+
import software.amazon.awssdk.core.internal.http.RequestExecutionContext;
21+
import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline;
22+
import software.amazon.awssdk.core.metrics.CoreMetric;
23+
import software.amazon.awssdk.http.SdkHttpFullRequest;
24+
import software.amazon.awssdk.metrics.MetricCollector;
25+
import software.amazon.awssdk.utils.CompletableFutureUtils;
26+
27+
/**
28+
* Wrapper pipeline that tracks the {@link CoreMetric#SERVICE_ENDPOINT} metric.
29+
*/
30+
@SdkInternalApi
31+
public final class AsyncServiceEndpointMetricCollectionStage<OutputT> implements RequestPipeline<SdkHttpFullRequest,
32+
CompletableFuture<OutputT>> {
33+
private final RequestPipeline<SdkHttpFullRequest, CompletableFuture<OutputT>> wrapped;
34+
35+
public AsyncServiceEndpointMetricCollectionStage(RequestPipeline<SdkHttpFullRequest, CompletableFuture<OutputT>> wrapped) {
36+
this.wrapped = wrapped;
37+
}
38+
39+
@Override
40+
public CompletableFuture<OutputT> execute(SdkHttpFullRequest input, RequestExecutionContext context) throws Exception {
41+
MetricCollector metricCollector = context.executionContext().metricCollector();
42+
43+
CompletableFuture<OutputT> future = new CompletableFuture<>();
44+
45+
CompletableFuture<OutputT> executeFuture = wrapped.execute(input, context);
46+
47+
executeFuture.whenComplete((r, t) -> {
48+
metricCollector.reportMetric(CoreMetric.SERVICE_ENDPOINT, input.getUri());
49+
50+
if (t != null) {
51+
future.completeExceptionally(t);
52+
} else {
53+
future.complete(r);
54+
}
55+
});
56+
57+
return CompletableFutureUtils.forwardExceptionTo(future, executeFuture);
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.core.internal.http.pipeline.stages;
17+
18+
import static software.amazon.awssdk.core.internal.util.MetricUtils.collectServiceEndpointMetrics;
19+
import static software.amazon.awssdk.core.internal.util.MetricUtils.createAttemptMetricsCollector;
20+
21+
import software.amazon.awssdk.annotations.SdkInternalApi;
22+
import software.amazon.awssdk.core.Response;
23+
import software.amazon.awssdk.core.internal.http.RequestExecutionContext;
24+
import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline;
25+
import software.amazon.awssdk.core.internal.http.pipeline.RequestToResponsePipeline;
26+
import software.amazon.awssdk.http.SdkHttpFullRequest;
27+
import software.amazon.awssdk.metrics.MetricCollector;
28+
29+
/**
30+
* Wrapper pipeline that initializes and tracks the API call attempt metric collection. This wrapper and any wrapped
31+
* stages will track API call attempt metrics.
32+
*/
33+
@SdkInternalApi
34+
public final class ServiceEndpointAttemptMetricCollectionStage<OutputT> implements RequestToResponsePipeline<OutputT> {
35+
private final RequestPipeline<SdkHttpFullRequest, Response<OutputT>> wrapped;
36+
37+
public ServiceEndpointAttemptMetricCollectionStage(RequestPipeline<SdkHttpFullRequest, Response<OutputT>> wrapped) {
38+
this.wrapped = wrapped;
39+
}
40+
41+
@Override
42+
public Response<OutputT> execute(SdkHttpFullRequest input, RequestExecutionContext context) throws Exception {
43+
MetricCollector apiCallAttemptMetrics = createAttemptMetricsCollector(context);
44+
context.attemptMetricCollector(apiCallAttemptMetrics);
45+
46+
Response<OutputT> response = wrapped.execute(input, context);
47+
48+
collectServiceEndpointMetrics(apiCallAttemptMetrics, input);
49+
50+
return response;
51+
}
52+
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.core.internal.http.pipeline.stages;
17+
18+
import software.amazon.awssdk.annotations.SdkInternalApi;
19+
import software.amazon.awssdk.core.Response;
20+
import software.amazon.awssdk.core.internal.http.RequestExecutionContext;
21+
import software.amazon.awssdk.core.internal.http.pipeline.RequestPipeline;
22+
import software.amazon.awssdk.core.internal.http.pipeline.RequestToResponsePipeline;
23+
import software.amazon.awssdk.core.metrics.CoreMetric;
24+
import software.amazon.awssdk.http.SdkHttpFullRequest;
25+
import software.amazon.awssdk.metrics.MetricCollector;
26+
27+
/**
28+
* Wrapper pipeline that tracks the {@link CoreMetric#SERVICE_ENDPOINT} metric.
29+
*/
30+
@SdkInternalApi
31+
public class ServiceEndpointMetricCollectionStage<OutputT> implements RequestToResponsePipeline<OutputT> {
32+
private final RequestPipeline<SdkHttpFullRequest, Response<OutputT>> wrapped;
33+
34+
public ServiceEndpointMetricCollectionStage(RequestPipeline<SdkHttpFullRequest, Response<OutputT>> wrapped) {
35+
this.wrapped = wrapped;
36+
}
37+
38+
@Override
39+
public Response<OutputT> execute(SdkHttpFullRequest input, RequestExecutionContext context) throws Exception {
40+
MetricCollector metricCollector = context.executionContext().metricCollector();
41+
metricCollector.reportMetric(CoreMetric.SERVICE_ENDPOINT, input.getUri());
42+
43+
return wrapped.execute(input, context);
44+
}
45+
}

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/util/MetricUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public static <T> Pair<T, Duration> measureDurationUnsafe(Callable<T> c) throws
6666
return Pair.of(result, d);
6767
}
6868

69-
public static void collectHttpRequestMetrics(MetricCollector metricCollector, SdkHttpFullRequest httpRequest) {
69+
public static void collectServiceEndpointMetrics(MetricCollector metricCollector, SdkHttpFullRequest httpRequest) {
7070
if (metricCollector != null && !(metricCollector instanceof NoOpMetricCollector) && httpRequest != null) {
7171
metricCollector.reportMetric(CoreMetric.SERVICE_ENDPOINT, httpRequest.getUri());
7272
}

test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/CoreMetricsTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import java.io.ByteArrayInputStream;
2626
import java.io.IOException;
27+
import java.net.URI;
2728
import java.time.Duration;
2829
import java.util.List;
2930
import java.util.stream.Collectors;

test/codegen-generated-classes-test/src/test/java/software/amazon/awssdk/services/metrics/async/BaseAsyncCoreMetricsTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.time.Duration;
2929
import java.util.concurrent.CompletableFuture;
3030
import java.util.function.Supplier;
31-
import org.junit.Ignore;
3231
import org.junit.Test;
3332
import org.junit.runner.RunWith;
3433
import org.mockito.ArgumentCaptor;
@@ -201,8 +200,8 @@ private void verifyApiCallCollection(MetricCollection capturedCollection) {
201200
.isGreaterThanOrEqualTo(Duration.ZERO);
202201
assertThat(capturedCollection.metricValues(CoreMetric.API_CALL_DURATION).get(0))
203202
.isGreaterThan(FIXED_DELAY);
204-
assertThat(capturedCollection.metricValues(CoreMetric.SERVICE_ENDPOINT).get(0))
205-
.isEqualTo(URI.create("http://localhost"));
203+
assertThat(capturedCollection.metricValues(CoreMetric.SERVICE_ENDPOINT).get(0)).toString()
204+
.startsWith("http://localhost");
206205
}
207206

208207
void stubSuccessfulResponse() {

0 commit comments

Comments
 (0)