Skip to content

Commit b1d3056

Browse files
author
Stephen-Bao
committed
Disallow duplicate dimension sets
1 parent bc46f91 commit b1d3056

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

aws_embedded_metrics/logger/metrics_context.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from aws_embedded_metrics.constants import MAX_DIMENSION_SET_SIZE
1818
from aws_embedded_metrics.exceptions import DimensionSetExceededError
1919
from aws_embedded_metrics.logger.metric import Metric
20-
from typing import List, Dict, Any
20+
from typing import List, Dict, Any, Set
2121

2222

2323
class MetricsContext(object):
@@ -79,6 +79,12 @@ def put_dimensions(self, dimensions: Dict[str, str]) -> None:
7979

8080
self.validate_dimension_set(dimensions)
8181

82+
# Duplicate dimension sets are removed before being added to the end of the collection.
83+
# This ensures only latest dimension value is used as a target member on the root EMF node.
84+
# This operation is O(n^2), but acceptable given sets are capped at 30 dimensions
85+
incoming_keys: Set = set(dimensions.keys())
86+
self.dimensions = list(filter(lambda dim: (set(dim.keys()) != incoming_keys), self.dimensions))
87+
8288
self.dimensions.append(dimensions)
8389

8490
def set_dimensions(self, dimensionSets: List[Dict[str, str]]) -> None:

tests/logger/test_metrics_context.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,77 @@ def test_put_dimension_adds_to_dimensions():
5454
assert context.dimensions == [dimension_set]
5555

5656

57+
def test_put_dimensions_accept_multiple_unique_dimensions():
58+
# arrange
59+
context = MetricsContext()
60+
dimension1 = {fake.word(): fake.word()}
61+
dimension2 = {fake.word(): fake.word()}
62+
63+
# act
64+
context.put_dimensions(dimension1)
65+
context.put_dimensions(dimension2)
66+
67+
# assert
68+
assert len(context.get_dimensions()) == 2
69+
assert context.get_dimensions()[0] == dimension1
70+
assert context.get_dimensions()[1] == dimension2
71+
72+
73+
def test_put_dimension_prevent_duplicate_dimensions():
74+
# arrange
75+
context = MetricsContext()
76+
pair1 = [fake.word(), fake.word()]
77+
pair2 = [fake.word(), fake.word()]
78+
79+
dimension1 = {pair1[0]: pair1[1]}
80+
dimension2 = {pair2[0]: pair2[1]}
81+
dimension3 = {pair1[0]: pair1[1], pair2[0]: pair2[1]}
82+
83+
# act
84+
context.put_dimensions(dimension1)
85+
context.put_dimensions(dimension2)
86+
context.put_dimensions(dimension1)
87+
context.put_dimensions(dimension3)
88+
context.put_dimensions(dimension2)
89+
context.put_dimensions(dimension3)
90+
91+
# assert
92+
assert len(context.get_dimensions()) == 3
93+
assert context.get_dimensions()[0] == dimension1
94+
assert context.get_dimensions()[1] == dimension2
95+
assert context.get_dimensions()[2] == dimension3
96+
97+
98+
def test_put_dimension_sort_duplicate_dimensions():
99+
# arrange
100+
context = MetricsContext()
101+
key1 = fake.word()
102+
key2 = fake.word()
103+
val1 = fake.word()
104+
val2 = fake.word()
105+
106+
dimension1 = {key1: val1}
107+
dimension2 = {key2: val2}
108+
dimension3 = {key1: val2}
109+
dimension4 = {key2: val1}
110+
dimension5 = {key1: val1, key2: val2}
111+
dimension6 = {key1: val2, key2: val1}
112+
113+
# act
114+
context.put_dimensions(dimension1)
115+
context.put_dimensions(dimension2)
116+
context.put_dimensions(dimension5)
117+
context.put_dimensions(dimension3)
118+
context.put_dimensions(dimension4)
119+
context.put_dimensions(dimension6)
120+
121+
# assert
122+
assert len(context.get_dimensions()) == 3
123+
assert context.get_dimensions()[0] == dimension3
124+
assert context.get_dimensions()[1] == dimension4
125+
assert context.get_dimensions()[2] == dimension6
126+
127+
57128
def test_get_dimensions_returns_only_custom_dimensions_if_no_default_dimensions_not_set():
58129
# arrange
59130
context = MetricsContext()

0 commit comments

Comments
 (0)