Skip to content

Commit 565f594

Browse files
authored
Add support for tracking business metrics from resolved endpoints (#6263)
* Ignore unknown properties in endpoint tests * Add support for tracking business metrics from resolved endpoints * Remove unused import * Fix syntax error + add functional test * Improve comments + fix test * Cleanups from PR + expand tests
1 parent 4688cec commit 565f594

19 files changed

+1350
-4
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "feature",
3+
"category": "AWS SDK for Java V2",
4+
"contributor": "",
5+
"description": "Add support for tracking business metrics from resolved endpoints."
6+
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,8 @@ public TypeSpec poetSpec() {
160160
}
161161

162162
endpointParamsKnowledgeIndex.addAccountIdMethodsIfPresent(b);
163+
164+
b.addMethod(setMetricValuesMethod());
163165
return b.build();
164166
}
165167

@@ -255,6 +257,7 @@ private MethodSpec modifyRequestMethod(String endpointAuthSchemeStrategyFieldNam
255257
}
256258

257259
b.addStatement("executionAttributes.putAttribute(SdkInternalExecutionAttribute.RESOLVED_ENDPOINT, endpoint)");
260+
b.addStatement("setMetricValues(endpoint, executionAttributes)");
258261
b.addStatement("return result");
259262
b.endControlFlow();
260263
b.beginControlFlow("catch ($T e)", CompletionException.class);
@@ -905,4 +908,19 @@ private MethodSpec constructorMethodSpec(String endpointAuthSchemeFieldName) {
905908
b.addStatement("this.$N = $N.endpointAuthSchemeStrategy()", endpointAuthSchemeFieldName, factoryLocalVarName);
906909
return b.build();
907910
}
911+
912+
private MethodSpec setMetricValuesMethod() {
913+
MethodSpec.Builder b = MethodSpec.methodBuilder("setMetricValues")
914+
.addModifiers(Modifier.PRIVATE)
915+
.addParameter(Endpoint.class, "endpoint")
916+
.addParameter(ExecutionAttributes.class, "executionAttributes")
917+
.returns(void.class);
918+
919+
b.beginControlFlow("if (endpoint.attribute($T.METRIC_VALUES) != null)", AwsEndpointAttribute.class);
920+
b.addStatement("executionAttributes.getOptionalAttribute($T.BUSINESS_METRICS).ifPresent("
921+
+ "metrics -> endpoint.attribute($T.METRIC_VALUES).forEach(v -> metrics.addMetric(v)))",
922+
SdkInternalExecutionAttribute.class, AwsEndpointAttribute.class);
923+
b.endControlFlow();
924+
return b.build();
925+
}
908926
}

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

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import java.util.List;
3131
import java.util.Map;
3232
import java.util.Optional;
33+
import org.slf4j.Logger;
34+
import org.slf4j.LoggerFactory;
3335
import software.amazon.awssdk.awscore.endpoints.AwsEndpointAttribute;
3436
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4AuthScheme;
3537
import software.amazon.awssdk.awscore.endpoints.authscheme.SigV4aAuthScheme;
@@ -45,6 +47,8 @@
4547
import software.amazon.awssdk.utils.StringUtils;
4648

4749
public final class TestGeneratorUtils {
50+
private static final Logger log = LoggerFactory.getLogger(TestGeneratorUtils.class);
51+
4852
private TestGeneratorUtils() {
4953
}
5054

@@ -111,16 +115,40 @@ private static void addEndpointAttributeBlock(CodeBlock.Builder builder, String
111115
Map<String, KeyTypePair> knownEndpointAttributes) {
112116
if ("authSchemes".equals(attrName)) {
113117
addAuthSchemesBlock(builder, attrValue);
118+
} else if ("metricValues".equals(attrName)) {
119+
addMetricValuesBlock(builder, attrValue);
114120
} else if (knownEndpointAttributes.containsKey(attrName)) {
115121
addAttributeBlock(builder, attrValue, knownEndpointAttributes.get(attrName));
116122
} else {
117-
throw new RuntimeException(
118-
String.format("Encountered unknown expected endpoint attribute: %s. Known attributes: %s.",
123+
log.warn("Ignoring unknown expected endpoint attribute: {}. Known attributes: {}.",
119124
attrName,
120-
knownEndpointAttributes));
125+
knownEndpointAttributes);
121126
}
122127
}
123128

129+
private static void addMetricValuesBlock(CodeBlock.Builder builder, TreeNode attrValue) {
130+
CodeBlock keyExpr = CodeBlock.builder()
131+
.add("$T.METRIC_VALUES", AwsEndpointAttribute.class)
132+
.build();
133+
134+
CodeBlock.Builder schemesListExpr = CodeBlock.builder()
135+
.add("$T.asList(", Arrays.class);
136+
137+
JrsArray schemesArray = (JrsArray) attrValue;
138+
139+
Iterator<JrsValue> elementsIter = schemesArray.elements();
140+
while (elementsIter.hasNext()) {
141+
schemesListExpr.add("$S", elementsIter.next().asText());
142+
143+
if (elementsIter.hasNext()) {
144+
schemesListExpr.add(",");
145+
}
146+
}
147+
schemesListExpr.add(")");
148+
149+
builder.add(".putAttribute($L, $L)", keyExpr, schemesListExpr.build());
150+
}
151+
124152
private static void addAttributeBlock(CodeBlock.Builder builder, TreeNode attrValue, KeyTypePair keyType) {
125153
CodeBlock keyExpr = CodeBlock.builder()
126154
.add("$L", keyType.getKey())

codegen/src/main/java/software/amazon/awssdk/codegen/poet/rules2/CodeGeneratorVisitor.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ public Void visitPropertiesExpression(PropertiesExpression e) {
353353
properties.forEach((k, v) -> {
354354
if ("authSchemes".equals(k)) {
355355
addAuthSchemesBlock(v);
356+
} else if ("metricValues".equals(k)) {
357+
addMetricValuesBlock(v);
356358
} else if (knownEndpointAttributes.containsKey(k)) {
357359
addAttributeBlock(k, v);
358360
} else {
@@ -436,6 +438,12 @@ private ClassName authSchemeClass(String name) {
436438
}
437439
}
438440

441+
private void addMetricValuesBlock(RuleExpression v) {
442+
builder.add(".putAttribute($T.METRIC_VALUES, ", AwsEndpointAttribute.class);
443+
v.accept(this);
444+
builder.add(")");
445+
}
446+
439447
private void addAttributeBlock(String k, RuleExpression v) {
440448
KeyTypePair keyType = knownEndpointAttributes.get(k);
441449
ClassConstant classConstant = parseClassConstant(keyType.getKey());

codegen/src/test/java/software/amazon/awssdk/codegen/poet/ClientTestModels.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,27 @@ public static IntermediateModel queryServiceModelsWithUnknownEndpointProperties(
192192
File endpointRuleSetModel =
193193
new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set-unknown-properties.json").getFile());
194194
File endpointTestsModel =
195-
new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests.json").getFile());
195+
new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests-unknown-properties.json").getFile());
196+
197+
C2jModels models = C2jModels
198+
.builder()
199+
.serviceModel(getServiceModel(serviceModel))
200+
.waitersModel(getWaiters(waitersModel))
201+
.customizationConfig(CustomizationConfig.create())
202+
.endpointRuleSetModel(getEndpointRuleSet(endpointRuleSetModel))
203+
.endpointTestSuiteModel(getEndpointTestSuite(endpointTestsModel))
204+
.build();
205+
206+
return new IntermediateModelBuilder(models).build();
207+
}
208+
209+
public static IntermediateModel queryServiceModelsWithUnknownEndpointMetricValues() {
210+
File serviceModel = new File(ClientTestModels.class.getResource("client/c2j/query/service-2.json").getFile());
211+
File waitersModel = new File(ClientTestModels.class.getResource("client/c2j/query/waiters-2.json").getFile());
212+
File endpointRuleSetModel =
213+
new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-rule-set-metric-values.json").getFile());
214+
File endpointTestsModel =
215+
new File(ClientTestModels.class.getResource("client/c2j/query/endpoint-tests-metric-values.json").getFile());
196216

197217
C2jModels models = C2jModels
198218
.builder()

codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointProviderCompiledRulesClassSpecTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,11 @@ void endpointProviderClassWithUriCache() {
5151
new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUriCache());
5252
assertThat(endpointProviderSpec, generatesTo("endpoint-provider-uri-cache-class.java"));
5353
}
54+
55+
@Test
56+
void endpointProviderClassWithMetricValues() {
57+
ClassSpec endpointProviderSpec =
58+
new EndpointProviderSpec2(ClientTestModels.queryServiceModelsWithUnknownEndpointMetricValues());
59+
assertThat(endpointProviderSpec, generatesTo("endpoint-provider-metric-values-class.java"));
60+
}
5461
}

codegen/src/test/java/software/amazon/awssdk/codegen/poet/rules/EndpointRulesClientTestSpecTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,16 @@ public void endpointProviderTestClassWithStringArray() {
3434
ClassSpec endpointProviderSpec = new EndpointProviderTestSpec(ClientTestModels.stringArrayServiceModels());
3535
assertThat(endpointProviderSpec, generatesTo("endpoint-rules-stringarray-test-class.java"));
3636
}
37+
38+
@Test
39+
public void endpointProviderTestClassWithUnknownProperties() {
40+
ClassSpec endpointProviderSpec = new EndpointProviderTestSpec(ClientTestModels.queryServiceModelsWithUnknownEndpointProperties());
41+
assertThat(endpointProviderSpec, generatesTo("endpoint-rules-unknown-property-test-class.java"));
42+
}
43+
44+
@Test
45+
public void endpointProviderTestClassWithMetricValues() {
46+
ClassSpec endpointProviderSpec = new EndpointProviderTestSpec(ClientTestModels.queryServiceModelsWithUnknownEndpointMetricValues());
47+
assertThat(endpointProviderSpec, generatesTo("endpoint-rules-metric-values-test-class.java"));
48+
}
3749
}

0 commit comments

Comments
 (0)