Skip to content

Commit 68ab8f5

Browse files
aaronlnaAaron Michael Lambmarkkuhn
authored
fix: prevent putDimensions from storing duplicate dimensions (#88)
* fix: prevent putDimensions from storing duplicate dimensions This is the Java-equivalent bug-fix for prior issue in Node: awslabs/aws-embedded-metrics-node#20 New conditions check for any matching dimension set before skipping put dimensions. This prevents duplicates from being stored. [TESTING] Unit test updated to address edge case; multiple dimension sets of variable size are added and checked. Ran integration tests using Docker and compared results in CloudWatch. * fix: change putDimensions to update/sort existing dimension sets when duplicate This change ensures new dimension key-values are used for the EMF root node by removing duplicate dimension sets and adding input dimension set to the end of the collection. Example: ``` [ { "keyA": "value1" }, { "keyA": "value2" }, ] // expected target member: { "keyA": "value2" } ``` [TESTING] Updated unit tests to check for this case wherein putDimensions may be triggered using various dimension set lengths, values, and order. * Update src/test/java/software/amazon/cloudwatchlogs/emf/model/MetricDirectiveTest.java * Update src/test/java/software/amazon/cloudwatchlogs/emf/model/MetricDirectiveTest.java Co-authored-by: Aaron Michael Lamb <[email protected]> Co-authored-by: Mark Kuhn <[email protected]>
1 parent 4c242fc commit 68ab8f5

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

src/main/java/software/amazon/cloudwatchlogs/emf/model/MetricDirective.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,16 @@ class MetricDirective {
5151
shouldUseDefaultDimension = true;
5252
}
5353

54+
/**
55+
* Adds a dimension set to the end of the collection.
56+
*
57+
* @param dimensionSet
58+
*/
5459
void putDimensionSet(DimensionSet dimensionSet) {
60+
// Duplicate dimensions sets are removed before being added to the end of the collection.
61+
// This ensures only latest dimension value is used as a target member on the root EMF node.
62+
// This operation is O(n^2), but acceptable given sets are capped at 10 dimensions
63+
dimensions.removeIf(dim -> dim.getDimensionKeys().equals(dimensionSet.getDimensionKeys()));
5564
dimensions.add(dimensionSet);
5665
}
5766

src/test/java/software/amazon/cloudwatchlogs/emf/model/MetricDirectiveTest.java

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public void testPutDimensions() throws JsonProcessingException {
102102
}
103103

104104
@Test
105-
public void testPutMultipleDimensionSets() throws JsonProcessingException {
105+
public void testPutDimensionSetWhenMultipleDimensionSets() throws JsonProcessingException {
106106
MetricDirective metricDirective = new MetricDirective();
107107
metricDirective.putDimensionSet(DimensionSet.of("Region", "us-east-1"));
108108
metricDirective.putDimensionSet(DimensionSet.of("Instance", "inst-1"));
@@ -114,6 +114,57 @@ public void testPutMultipleDimensionSets() throws JsonProcessingException {
114114
"{\"Dimensions\":[[\"Region\"],[\"Instance\"]],\"Metrics\":[],\"Namespace\":\"aws-embedded-metrics\"}");
115115
}
116116

117+
@Test
118+
public void testPutDimensionSetWhenDuplicateDimensionSets() throws JsonProcessingException {
119+
MetricDirective metricDirective = new MetricDirective();
120+
metricDirective.putDimensionSet(new DimensionSet());
121+
metricDirective.putDimensionSet(DimensionSet.of("Region", "us-east-1"));
122+
metricDirective.putDimensionSet(
123+
DimensionSet.of("Region", "us-east-1", "Instance", "inst-1"));
124+
metricDirective.putDimensionSet(
125+
DimensionSet.of("Instance", "inst-1", "Region", "us-east-1"));
126+
metricDirective.putDimensionSet(DimensionSet.of("Instance", "inst-1"));
127+
metricDirective.putDimensionSet(new DimensionSet());
128+
metricDirective.putDimensionSet(DimensionSet.of("Region", "us-east-1"));
129+
metricDirective.putDimensionSet(
130+
DimensionSet.of("Region", "us-east-1", "Instance", "inst-1"));
131+
metricDirective.putDimensionSet(
132+
DimensionSet.of("Instance", "inst-1", "Region", "us-east-1"));
133+
metricDirective.putDimensionSet(DimensionSet.of("Instance", "inst-1"));
134+
135+
String serializedMetricDirective = objectMapper.writeValueAsString(metricDirective);
136+
137+
assertEquals(
138+
"{\"Dimensions\":[[],[\"Region\"],[\"Instance\",\"Region\"],[\"Instance\"]],\"Metrics\":[],\"Namespace\":\"aws-embedded-metrics\"}",
139+
serializedMetricDirective);
140+
}
141+
142+
@Test
143+
public void testPutDimensionSetWhenDuplicateDimensionSetsWillSortCorrectly()
144+
throws JsonProcessingException {
145+
MetricDirective metricDirective = new MetricDirective();
146+
metricDirective.putDimensionSet(new DimensionSet());
147+
metricDirective.putDimensionSet(DimensionSet.of("Region", "us-east-1"));
148+
metricDirective.putDimensionSet(
149+
DimensionSet.of("Region", "us-east-1", "Instance", "inst-1"));
150+
metricDirective.putDimensionSet(
151+
DimensionSet.of("Instance", "inst-1", "Region", "us-east-1"));
152+
metricDirective.putDimensionSet(DimensionSet.of("Instance", "inst-1"));
153+
metricDirective.putDimensionSet(
154+
DimensionSet.of("Region", "us-east-1", "Instance", "inst-1"));
155+
metricDirective.putDimensionSet(
156+
DimensionSet.of("Instance", "inst-1", "Region", "us-east-1"));
157+
metricDirective.putDimensionSet(DimensionSet.of("Instance", "inst-1"));
158+
metricDirective.putDimensionSet(DimensionSet.of("Region", "us-east-1"));
159+
metricDirective.putDimensionSet(new DimensionSet());
160+
161+
String serializedMetricDirective = objectMapper.writeValueAsString(metricDirective);
162+
163+
assertEquals(
164+
"{\"Dimensions\":[[\"Instance\",\"Region\"],[\"Instance\"],[\"Region\"],[]],\"Metrics\":[],\"Namespace\":\"aws-embedded-metrics\"}",
165+
serializedMetricDirective);
166+
}
167+
117168
@Test
118169
public void testGetDimensionAfterSetDimensions() {
119170
MetricDirective metricDirective = new MetricDirective();

0 commit comments

Comments
 (0)