Skip to content

Commit e89d63b

Browse files
committed
fix(#11): preserve context across flushes
1 parent 6cf02e6 commit e89d63b

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

aws_embedded_metrics/logger/metrics_context.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,17 @@ def create_copy_with_context(self) -> "MetricsContext":
125125
new_properties: Dict = {}
126126
new_properties.update(self.properties)
127127

128+
# dimensions added with put_dimension will not be copied.
129+
# the reason for this is so that you can flush the same scope multiple
130+
# times without stacking new dimensions. Example:
131+
#
132+
# @metric_scope
133+
# def my_func(metrics):
134+
# metrics.put_dimensions(...)
135+
#
136+
# my_func()
137+
# my_func()
128138
new_dimensions: List[Dict] = []
129-
new_dimensions = new_dimensions + self.dimensions
130139

131140
new_default_dimensions: Dict = {}
132141
new_default_dimensions.update(self.default_dimensions)

aws_embedded_metrics/logger/metrics_logger.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ async def flush(self) -> None:
4141

4242
# accept and reset the context
4343
sink.accept(self.context)
44-
self.context = MetricsContext.empty()
44+
self.context = self.context.create_copy_with_context()
4545

4646
def __configureContextForEnvironment(self, env: Environment) -> None:
4747
default_dimensions = {

tests/logger/test_metrics_context.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def test_create_copy_with_context_copies_properties():
197197
assert context.properties is not new_context.properties
198198

199199

200-
def test_create_copy_with_context_copies_dimensions():
200+
def test_create_copy_with_context_does_not_copy_dimensions():
201201
# arrange
202202
context = MetricsContext()
203203
dimension_key = fake.word()
@@ -208,8 +208,7 @@ def test_create_copy_with_context_copies_dimensions():
208208
new_context = context.create_copy_with_context()
209209

210210
# assert
211-
assert context.dimensions == new_context.dimensions
212-
assert context.dimensions is not new_context.dimensions
211+
assert len(new_context.dimensions) == 0
213212

214213

215214
def test_create_copy_with_context_copies_default_dimensions():
@@ -225,6 +224,20 @@ def test_create_copy_with_context_copies_default_dimensions():
225224
assert context.default_dimensions is not new_context.default_dimensions
226225

227226

227+
def test_create_copy_with_context_does_not_copy_metrics():
228+
# arrange
229+
context = MetricsContext()
230+
prop_key = fake.word()
231+
prop_value = fake.word()
232+
context.set_property(prop_key, prop_value)
233+
234+
# act
235+
new_context = context.create_copy_with_context()
236+
237+
# assert
238+
assert len(new_context.metrics) == 0
239+
240+
228241
def test_set_dimensions_overwrites_all_dimensions():
229242
# arrange
230243
context = MetricsContext()
@@ -238,3 +251,20 @@ def test_set_dimensions_overwrites_all_dimensions():
238251

239252
# assert
240253
assert context.dimensions == expected_dimensions
254+
255+
256+
def test_create_copy_with_context_does_not_repeat_dimensions():
257+
# arrange
258+
context = MetricsContext()
259+
expected_dimensions = {fake.word(): fake.word()}
260+
261+
custom = {fake.word(): fake.word()}
262+
context.set_default_dimensions(expected_dimensions)
263+
context.put_dimensions(custom)
264+
265+
new_context = context.create_copy_with_context()
266+
new_context.set_default_dimensions(expected_dimensions)
267+
new_context.put_dimensions(custom)
268+
269+
# assert
270+
assert len(new_context.get_dimensions()) == 1

tests/logger/test_metrics_logger.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,39 @@ async def test_can_set_namespace(mocker):
180180
assert context.namespace == expected_value
181181

182182

183+
@pytest.mark.asyncio
184+
async def test_context_is_preserved_across_flushes(mocker):
185+
# arrange
186+
expected_namespace = "Namespace"
187+
metric_key = "Metric"
188+
expected_dimension_key = "Dim"
189+
expected_property_key = "Prop"
190+
expected_value = "Value"
191+
192+
logger, sink, env = get_logger_and_sink(mocker)
193+
194+
logger.set_namespace(expected_namespace)
195+
logger.set_property(expected_property_key, expected_value)
196+
logger.set_dimensions({expected_dimension_key: expected_value})
197+
198+
# act
199+
logger.put_metric(metric_key, 0)
200+
await logger.flush()
201+
202+
context = sink.accept.call_args[0][0]
203+
assert context.namespace == expected_namespace
204+
assert context.properties[expected_property_key] == expected_value
205+
assert context.metrics[metric_key].values == [0]
206+
207+
logger.put_metric(metric_key, 1)
208+
await logger.flush()
209+
210+
context = sink.accept.call_args[0][0]
211+
assert context.namespace == expected_namespace
212+
assert context.properties[expected_property_key] == expected_value
213+
assert context.metrics[metric_key].values == [1]
214+
215+
183216
# Test helper methods
184217

185218

0 commit comments

Comments
 (0)