Skip to content

Commit c5a9b3f

Browse files
author
cakepietoast
authored
fix: cast dimension value to str to avoid issue where EMF silently fails (#52)
* fix: cast dimension value to str to avoid issue where EMF silently fails to collect the metrics * fix: correct type hint in fixture * fix: remove surplus assertions and logic from new test * chore: fix formatting
1 parent 3f51e20 commit c5a9b3f

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

Diff for: aws_lambda_powertools/metrics/base.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,14 @@ def add_dimension(self, name: str, value: str):
203203
Dimension value
204204
"""
205205
logger.debug(f"Adding dimension: {name}:{value}")
206-
self.dimension_set[name] = value
206+
207+
# Cast value to str according to EMF spec
208+
# Majority of values are expected to be string already, so
209+
# checking before casting improves performance in most cases
210+
if isinstance(value, str):
211+
self.dimension_set[name] = value
212+
else:
213+
self.dimension_set[name] = str(value)
207214

208215
def __extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str:
209216
"""Return metric value from metric unit whether that's str or MetricUnit enum

Diff for: tests/functional/test_metrics.py

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from typing import Dict, List
2+
from typing import Any, Dict, List
33

44
import pytest
55

@@ -48,6 +48,14 @@ def dimensions() -> List[Dict[str, str]]:
4848
]
4949

5050

51+
@pytest.fixture
52+
def non_str_dimensions() -> List[Dict[str, Any]]:
53+
return [
54+
{"name": "test_dimension", "value": True},
55+
{"name": "test_dimension_2", "value": 3},
56+
]
57+
58+
5159
@pytest.fixture
5260
def namespace() -> Dict[str, str]:
5361
return {"name": "test_namespace"}
@@ -380,3 +388,27 @@ def lambda_handler(evt, context):
380388

381389
# THEN metric set should be empty after function has been run
382390
assert my_metrics.metric_set == {}
391+
392+
393+
def test_log_metrics_non_string_dimension_values(capsys, metrics, non_str_dimensions, namespace):
394+
# GIVEN Metrics is initialized and dimensions with non-string values are added
395+
my_metrics = Metrics()
396+
my_metrics.add_namespace(**namespace)
397+
for metric in metrics:
398+
my_metrics.add_metric(**metric)
399+
for dimension in non_str_dimensions:
400+
my_metrics.add_dimension(**dimension)
401+
402+
# WHEN we utilize log_metrics to serialize
403+
# and flush all metrics at the end of a function execution
404+
@my_metrics.log_metrics
405+
def lambda_handler(evt, ctx):
406+
return True
407+
408+
lambda_handler({}, {})
409+
output = json.loads(capsys.readouterr().out.strip())
410+
411+
# THEN we should have no exceptions
412+
# and dimension values hould be serialized as strings
413+
for dimension in non_str_dimensions:
414+
assert isinstance(output[dimension["name"]], str)

0 commit comments

Comments
 (0)