Skip to content

Commit 9124236

Browse files
authored
Adding endpoint and account ID business metrics values to user agent … (#5699)
* Adding endpoint and account ID business metrics values to user agent string * Only try to add endpoint override metric if metric object exists
1 parent 73fc9e9 commit 9124236

File tree

10 files changed

+189
-25
lines changed

10 files changed

+189
-25
lines changed

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointParamsKnowledgeIndex.java

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,17 @@
2323
import com.squareup.javapoet.MethodSpec;
2424
import com.squareup.javapoet.ParameterizedTypeName;
2525
import com.squareup.javapoet.TypeName;
26+
import com.squareup.javapoet.TypeSpec;
2627
import com.squareup.javapoet.TypeVariableName;
2728
import java.util.EnumMap;
2829
import java.util.Map;
2930
import java.util.Optional;
3031
import javax.lang.model.element.Modifier;
32+
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
3133
import software.amazon.awssdk.awscore.client.config.AwsClientOption;
3234
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode;
3335
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointModeResolver;
36+
import software.amazon.awssdk.awscore.internal.useragent.BusinessMetricsUtils;
3437
import software.amazon.awssdk.codegen.internal.Utils;
3538
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
3639
import software.amazon.awssdk.codegen.model.internal.LocalParameter;
@@ -39,6 +42,9 @@
3942
import software.amazon.awssdk.core.SelectedAuthScheme;
4043
import software.amazon.awssdk.core.client.config.SdkClientConfiguration;
4144
import software.amazon.awssdk.core.client.config.SdkClientOption;
45+
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
46+
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
47+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
4248
import software.amazon.awssdk.identity.spi.AwsCredentialsIdentity;
4349
import software.amazon.awssdk.identity.spi.Identity;
4450
import software.amazon.awssdk.utils.CompletableFutureUtils;
@@ -163,11 +169,51 @@ private Map<BuiltInParameter, LocalParameter> builtInsForClientBuilder(Map<Strin
163169
return actualParams;
164170
}
165171

166-
public Optional<MethodSpec> accountIdFromIdentityMethod() {
172+
public void addAccountIdMethodsIfPresent(TypeSpec.Builder b) {
167173
if (!hasAccountIdEndpointModeBuiltIn()) {
168-
return Optional.empty();
174+
return;
169175
}
170176

177+
b.addMethod(resolveAndRecordAccountIdFromIdentityMethod());
178+
b.addMethod(accountIdFromIdentityMethod());
179+
b.addMethod(recordAccountIdEndpointModeMethod());
180+
}
181+
182+
public MethodSpec recordAccountIdEndpointModeMethod() {
183+
MethodSpec.Builder builder = MethodSpec.methodBuilder("recordAccountIdEndpointMode")
184+
.addModifiers(PRIVATE, STATIC)
185+
.addParameter(ExecutionAttributes.class, "executionAttributes")
186+
.returns(String.class);
187+
builder.addStatement("$T mode = executionAttributes.getAttribute($T.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE)",
188+
AccountIdEndpointMode.class, AwsExecutionAttribute.class);
189+
190+
builder.addStatement("$T.resolveAccountIdEndpointModeMetric(mode)"
191+
+ ".ifPresent(m -> executionAttributes.getAttribute($T.BUSINESS_METRICS).addMetric(m))",
192+
BusinessMetricsUtils.class, SdkInternalExecutionAttribute.class);
193+
194+
builder.addStatement("return mode.name().toLowerCase()");
195+
196+
return builder.build();
197+
}
198+
199+
public MethodSpec resolveAndRecordAccountIdFromIdentityMethod() {
200+
MethodSpec.Builder builder = MethodSpec.methodBuilder("resolveAndRecordAccountIdFromIdentity")
201+
.addModifiers(PRIVATE, STATIC)
202+
.addParameter(ExecutionAttributes.class, "executionAttributes")
203+
.returns(String.class);
204+
builder.addStatement("$T accountId = accountIdFromIdentity(executionAttributes.getAttribute($T.SELECTED_AUTH_SCHEME))",
205+
String.class, SdkInternalExecutionAttribute.class);
206+
207+
builder.addStatement("executionAttributes.getAttribute($T.BUSINESS_METRICS).addMetric($T.RESOLVED_ACCOUNT_ID.value())",
208+
SdkInternalExecutionAttribute.class, BusinessMetricFeatureId.class);
209+
210+
builder.addStatement("return accountId");
211+
212+
return builder.build();
213+
}
214+
215+
216+
public MethodSpec accountIdFromIdentityMethod() {
171217
ParameterizedTypeName paramType = ParameterizedTypeName.get(ClassName.get(SelectedAuthScheme.class),
172218
TypeVariableName.get("T"));
173219

@@ -184,6 +230,6 @@ public Optional<MethodSpec> accountIdFromIdentityMethod() {
184230
builder.addStatement("accountId = (($T) identity).accountId().orElse(null)", AwsCredentialsIdentity.class);
185231
builder.endControlFlow();
186232
builder.addStatement("return accountId");
187-
return Optional.of(builder.build());
233+
return builder.build();
188234
}
189235
}

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules/EndpointResolverInterceptorSpec.java

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public TypeSpec poetSpec() {
155155
b.addMethod(signerProviderMethod());
156156
}
157157

158-
endpointParamsKnowledgeIndex.accountIdFromIdentityMethod().ifPresent(b::addMethod);
158+
endpointParamsKnowledgeIndex.addAccountIdMethodsIfPresent(b);
159159
return b.build();
160160
}
161161

@@ -303,13 +303,10 @@ private MethodSpec ruleParams() {
303303
b.addStatement(endpointProviderUtilsSetter("endpointBuiltIn", setter));
304304
break;
305305
case AWS_AUTH_ACCOUNT_ID:
306-
b.addStatement("builder.$N(accountIdFromIdentity(executionAttributes.getAttribute($T.SELECTED_AUTH_SCHEME)))",
307-
setter, SdkInternalExecutionAttribute.class);
306+
b.addStatement("builder.$N(resolveAndRecordAccountIdFromIdentity(executionAttributes))", setter);
308307
break;
309308
case AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE:
310-
b.addStatement("builder.$N(executionAttributes.getAttribute($T.$N).name().toLowerCase())",
311-
setter, AwsExecutionAttribute.class,
312-
model.getNamingStrategy().getEnumValueName(m.getBuiltInEnum().name()));
309+
b.addStatement("builder.$N(recordAccountIdEndpointMode(executionAttributes))", setter);
313310
break;
314311
case AWS_S3_USE_GLOBAL_ENDPOINT:
315312
b.addStatement("builder.$N(executionAttributes.getAttribute($T.$N))",

codegen/src/main/resources/software/amazon/awssdk/codegen/rules/AwsEndpointProviderUtils.java.resource

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import software.amazon.awssdk.core.exception.SdkClientException;
1010
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
1111
import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
1212
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
13+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
1314
import software.amazon.awssdk.endpoints.Endpoint;
1415
import software.amazon.awssdk.http.SdkHttpRequest;
1516
import software.amazon.awssdk.regions.Region;
@@ -43,6 +44,8 @@ public final class AwsEndpointProviderUtils {
4344
*/
4445
public static String endpointBuiltIn(ExecutionAttributes executionAttributes) {
4546
if (endpointIsOverridden(executionAttributes)) {
47+
executionAttributes.getOptionalAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).ifPresent(
48+
metric -> metric.addMetric(BusinessMetricFeatureId.ENDPOINT_OVERRIDE.value()));
4649
return invokeSafely(() -> {
4750
URI endpointOverride = executionAttributes.getAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER)
4851
.clientEndpoint();

codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor-preSra.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import software.amazon.awssdk.auth.signer.Aws4Signer;
1111
import software.amazon.awssdk.auth.signer.SignerLoader;
1212
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
13+
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode;
1314
import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
1415
import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
1516
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
1617
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
18+
import software.amazon.awssdk.awscore.internal.useragent.BusinessMetricsUtils;
1719
import software.amazon.awssdk.awscore.util.SignerOverrideUtils;
1820
import software.amazon.awssdk.core.SdkRequest;
1921
import software.amazon.awssdk.core.SelectedAuthScheme;
@@ -25,6 +27,7 @@
2527
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
2628
import software.amazon.awssdk.core.metrics.CoreMetric;
2729
import software.amazon.awssdk.core.signer.Signer;
30+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2831
import software.amazon.awssdk.endpoints.Endpoint;
2932
import software.amazon.awssdk.http.SdkHttpRequest;
3033
import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
@@ -118,10 +121,8 @@ public static QueryEndpointParams ruleParams(SdkRequest request, ExecutionAttrib
118121
builder.region(AwsEndpointProviderUtils.regionBuiltIn(executionAttributes));
119122
builder.useDualStackEndpoint(AwsEndpointProviderUtils.dualStackEnabledBuiltIn(executionAttributes));
120123
builder.useFipsEndpoint(AwsEndpointProviderUtils.fipsEnabledBuiltIn(executionAttributes));
121-
builder.accountId(accountIdFromIdentity(executionAttributes
122-
.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)));
123-
builder.accountIdEndpointMode(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE)
124-
.name().toLowerCase());
124+
builder.accountId(resolveAndRecordAccountIdFromIdentity(executionAttributes));
125+
builder.accountIdEndpointMode(recordAccountIdEndpointMode(executionAttributes));
125126
setClientContextParams(builder, executionAttributes);
126127
setContextParams(builder, executionAttributes.getAttribute(AwsExecutionAttribute.OPERATION_NAME), request);
127128
setStaticContextParams(builder, executionAttributes.getAttribute(AwsExecutionAttribute.OPERATION_NAME));
@@ -249,6 +250,14 @@ private Supplier<Signer> signerProvider(EndpointAuthScheme authScheme) {
249250
throw SdkClientException.create("Don't know how to create signer for auth scheme: " + authScheme.name());
250251
}
251252

253+
private static String resolveAndRecordAccountIdFromIdentity(ExecutionAttributes executionAttributes) {
254+
String accountId = accountIdFromIdentity(executionAttributes
255+
.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME));
256+
executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(
257+
BusinessMetricFeatureId.RESOLVED_ACCOUNT_ID.value());
258+
return accountId;
259+
}
260+
252261
private static <T extends Identity> String accountIdFromIdentity(SelectedAuthScheme<T> selectedAuthScheme) {
253262
T identity = CompletableFutureUtils.joinLikeSync(selectedAuthScheme.identity());
254263
String accountId = null;
@@ -257,4 +266,11 @@ private static <T extends Identity> String accountIdFromIdentity(SelectedAuthSch
257266
}
258267
return accountId;
259268
}
269+
270+
private static String recordAccountIdEndpointMode(ExecutionAttributes executionAttributes) {
271+
AccountIdEndpointMode mode = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE);
272+
BusinessMetricsUtils.resolveAccountIdEndpointModeMetric(mode).ifPresent(
273+
m -> executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(m));
274+
return mode.name().toLowerCase();
275+
}
260276
}

codegen/src/test/resources/software/amazon/awssdk/codegen/poet/rules/endpoint-resolve-interceptor.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@
77
import software.amazon.awssdk.annotations.Generated;
88
import software.amazon.awssdk.annotations.SdkInternalApi;
99
import software.amazon.awssdk.awscore.AwsExecutionAttribute;
10+
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode;
1011
import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
1112
import software.amazon.awssdk.awscore.endpoints.authscheme.EndpointAuthScheme;
1213
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
1314
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
15+
import software.amazon.awssdk.awscore.internal.useragent.BusinessMetricsUtils;
1416
import software.amazon.awssdk.core.SdkRequest;
1517
import software.amazon.awssdk.core.SelectedAuthScheme;
1618
import software.amazon.awssdk.core.exception.SdkClientException;
@@ -20,6 +22,7 @@
2022
import software.amazon.awssdk.core.interceptor.SdkExecutionAttribute;
2123
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
2224
import software.amazon.awssdk.core.metrics.CoreMetric;
25+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
2326
import software.amazon.awssdk.endpoints.Endpoint;
2427
import software.amazon.awssdk.http.SdkHttpRequest;
2528
import software.amazon.awssdk.http.auth.aws.signer.AwsV4HttpSigner;
@@ -101,10 +104,8 @@ public static QueryEndpointParams ruleParams(SdkRequest request, ExecutionAttrib
101104
builder.region(AwsEndpointProviderUtils.regionBuiltIn(executionAttributes));
102105
builder.useDualStackEndpoint(AwsEndpointProviderUtils.dualStackEnabledBuiltIn(executionAttributes));
103106
builder.useFipsEndpoint(AwsEndpointProviderUtils.fipsEnabledBuiltIn(executionAttributes));
104-
builder.accountId(accountIdFromIdentity(executionAttributes
105-
.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME)));
106-
builder.accountIdEndpointMode(executionAttributes.getAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE)
107-
.name().toLowerCase());
107+
builder.accountId(resolveAndRecordAccountIdFromIdentity(executionAttributes));
108+
builder.accountIdEndpointMode(recordAccountIdEndpointMode(executionAttributes));
108109
setClientContextParams(builder, executionAttributes);
109110
setContextParams(builder, executionAttributes.getAttribute(AwsExecutionAttribute.OPERATION_NAME), request);
110111
setStaticContextParams(builder, executionAttributes.getAttribute(AwsExecutionAttribute.OPERATION_NAME));
@@ -223,6 +224,14 @@ private static Optional<String> hostPrefix(String operationName, SdkRequest requ
223224
}
224225
}
225226

227+
private static String resolveAndRecordAccountIdFromIdentity(ExecutionAttributes executionAttributes) {
228+
String accountId = accountIdFromIdentity(executionAttributes
229+
.getAttribute(SdkInternalExecutionAttribute.SELECTED_AUTH_SCHEME));
230+
executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(
231+
BusinessMetricFeatureId.RESOLVED_ACCOUNT_ID.value());
232+
return accountId;
233+
}
234+
226235
private static <T extends Identity> String accountIdFromIdentity(SelectedAuthScheme<T> selectedAuthScheme) {
227236
T identity = CompletableFutureUtils.joinLikeSync(selectedAuthScheme.identity());
228237
String accountId = null;
@@ -231,4 +240,11 @@ private static <T extends Identity> String accountIdFromIdentity(SelectedAuthSch
231240
}
232241
return accountId;
233242
}
243+
244+
private static String recordAccountIdEndpointMode(ExecutionAttributes executionAttributes) {
245+
AccountIdEndpointMode mode = executionAttributes.getAttribute(AwsExecutionAttribute.AWS_AUTH_ACCOUNT_ID_ENDPOINT_MODE);
246+
BusinessMetricsUtils.resolveAccountIdEndpointModeMetric(mode).ifPresent(
247+
m -> executionAttributes.getAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS).addMetric(m));
248+
return mode.name().toLowerCase();
249+
}
234250
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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.awscore.internal.useragent;
17+
18+
import java.util.Optional;
19+
import software.amazon.awssdk.annotations.SdkInternalApi;
20+
import software.amazon.awssdk.awscore.endpoints.AccountIdEndpointMode;
21+
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
22+
23+
@SdkInternalApi
24+
public final class BusinessMetricsUtils {
25+
private BusinessMetricsUtils() {
26+
}
27+
28+
public static Optional<String> resolveAccountIdEndpointModeMetric(AccountIdEndpointMode accountIdEndpointMode) {
29+
if (accountIdEndpointMode == AccountIdEndpointMode.PREFERRED) {
30+
return Optional.of(BusinessMetricFeatureId.ACCOUNT_ID_MODE_PREFERRED.value());
31+
}
32+
if (accountIdEndpointMode == AccountIdEndpointMode.REQUIRED) {
33+
return Optional.of(BusinessMetricFeatureId.ACCOUNT_ID_MODE_REQUIRED.value());
34+
}
35+
if (accountIdEndpointMode == AccountIdEndpointMode.DISABLED) {
36+
return Optional.of(BusinessMetricFeatureId.ACCOUNT_ID_MODE_DISABLED.value());
37+
}
38+
return Optional.empty();
39+
}
40+
}

core/sdk-core/src/main/java/software/amazon/awssdk/core/useragent/BusinessMetricFeatureId.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
/**
2323
* An enum class representing a short form of identity providers to record in the UA string.
2424
*
25-
* Unimplemented metrics: I,J,K,M-c,e-[latest]
25+
* Unimplemented metrics: I,J,K,M,O,S,U-c,e-[latest]
2626
* Unsupported metrics (these will never be added): A,H
2727
*/
2828
@SdkProtectedApi
@@ -35,6 +35,11 @@ public enum BusinessMetricFeatureId {
3535
RETRY_MODE_ADAPTIVE("F"),
3636
S3_TRANSFER("G"),
3737
GZIP_REQUEST_COMPRESSION("L"), //TODO(metrics): Not working, compression happens after header
38+
ENDPOINT_OVERRIDE("N"),
39+
ACCOUNT_ID_MODE_PREFERRED("P"),
40+
ACCOUNT_ID_MODE_DISABLED("Q"),
41+
ACCOUNT_ID_MODE_REQUIRED("R"),
42+
RESOLVED_ACCOUNT_ID("T"),
3843
DDB_MAPPER("d"),
3944
UNKNOWN("Unknown");
4045

services/dynamodb/src/test/java/software/amazon/awssdk/services/dynamodb/PaginatorInUserAgentTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,13 @@
3232
import org.junit.Test;
3333
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
3434
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
35+
import software.amazon.awssdk.core.ClientEndpointProvider;
36+
import software.amazon.awssdk.core.interceptor.ExecutionAttributes;
37+
import software.amazon.awssdk.core.interceptor.SdkInternalExecutionAttribute;
38+
import software.amazon.awssdk.core.useragent.BusinessMetricCollection;
3539
import software.amazon.awssdk.core.useragent.BusinessMetricFeatureId;
3640
import software.amazon.awssdk.regions.Region;
41+
import software.amazon.awssdk.services.dynamodb.endpoints.internal.AwsEndpointProviderUtils;
3742
import software.amazon.awssdk.services.dynamodb.paginators.QueryPublisher;
3843

3944
public class PaginatorInUserAgentTest {
@@ -78,6 +83,19 @@ public void syncPaginator_shouldHavePaginatorUserAgent() throws IOException {
7883
matching(METRIC_SEARCH_PATTERN.apply(BusinessMetricFeatureId.PAGINATOR.value()))));
7984
}
8085

86+
@Test
87+
public void syncPaginator_shuldHavePaginatorUserAgent() throws IOException {
88+
ExecutionAttributes executionAttributes = new ExecutionAttributes();
89+
BusinessMetricCollection newmetrics = new BusinessMetricCollection();
90+
newmetrics.addMetric("R");
91+
92+
ClientEndpointProvider wohoo = ClientEndpointProvider.forEndpointOverride(URI.create("http://wohoo"));
93+
executionAttributes.putAttribute(SdkInternalExecutionAttribute.BUSINESS_METRICS, newmetrics);
94+
executionAttributes.putAttribute(SdkInternalExecutionAttribute.CLIENT_ENDPOINT_PROVIDER, wohoo);
95+
String s = AwsEndpointProviderUtils.endpointBuiltIn(executionAttributes);
96+
System.out.println(s);
97+
}
98+
8199
@Test
82100
public void asyncPaginator_shouldHavePaginatorUserAgent() throws IOException {
83101
stubFor(any(urlEqualTo("/"))

0 commit comments

Comments
 (0)