Skip to content

Commit 14e00cc

Browse files
feat(metrics): add default_dimensions to single_metric (#1880)
Co-authored-by: Ruben Fonseca <[email protected]>
1 parent 21c1b2b commit 14e00cc

File tree

5 files changed

+87
-1
lines changed

5 files changed

+87
-1
lines changed

aws_lambda_powertools/metrics/base.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,11 @@ def add_metric(self, name: str, unit: Union[MetricUnit, str], value: float) -> N
463463

464464
@contextmanager
465465
def single_metric(
466-
name: str, unit: MetricUnit, value: float, namespace: Optional[str] = None
466+
name: str,
467+
unit: MetricUnit,
468+
value: float,
469+
namespace: Optional[str] = None,
470+
default_dimensions: Optional[Dict[str, str]] = None,
467471
) -> Generator[SingleMetric, None, None]:
468472
"""Context manager to simplify creation of a single metric
469473
@@ -516,6 +520,11 @@ def single_metric(
516520
try:
517521
metric: SingleMetric = SingleMetric(namespace=namespace)
518522
metric.add_metric(name=name, unit=unit, value=value)
523+
524+
if default_dimensions:
525+
for dim_name, dim_value in default_dimensions.items():
526+
metric.add_dimension(name=dim_name, value=dim_value)
527+
519528
yield metric
520529
metric_set = metric.serialize_metric_set()
521530
finally:

docs/core/metrics.md

+14
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,20 @@ CloudWatch EMF uses the same dimensions across all your metrics. Use `single_met
216216
--8<-- "examples/metrics/src/single_metric_output.json"
217217
```
218218

219+
By default it will skip all previously defined dimensions including default dimensions. Use `default_dimensions` keyword argument if you want to reuse default dimensions or specify custom dimensions from a dictionary.
220+
221+
=== "single_metric_default_dimensions_inherit.json"
222+
223+
```json hl_lines="10 15"
224+
--8<-- "examples/metrics/src/single_metric_default_dimensions_inherit.py"
225+
```
226+
227+
=== "single_metric_default_dimensions.py"
228+
229+
```python hl_lines="12"
230+
--8<-- "examples/metrics/src/single_metric_default_dimensions.py"
231+
```
232+
219233
### Flushing metrics manually
220234

221235
If you prefer not to use `log_metrics` because you might want to encapsulate additional logic when doing so, you can manually flush and clear metrics as follows:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import os
2+
3+
from aws_lambda_powertools import single_metric
4+
from aws_lambda_powertools.metrics import MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
9+
10+
def lambda_handler(event: dict, context: LambdaContext):
11+
with single_metric(
12+
name="RecordsCount", unit=MetricUnit.Count, value=10, default_dimensions={"environment": STAGE}
13+
) as metric:
14+
metric.add_dimension(name="TableName", value="Users")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import os
2+
3+
from aws_lambda_powertools import single_metric
4+
from aws_lambda_powertools.metrics import Metrics, MetricUnit
5+
from aws_lambda_powertools.utilities.typing import LambdaContext
6+
7+
STAGE = os.getenv("STAGE", "dev")
8+
9+
metrics = Metrics()
10+
metrics.set_default_dimensions(environment=STAGE)
11+
12+
13+
def lambda_handler(event: dict, context: LambdaContext):
14+
with single_metric(
15+
name="RecordsCount", unit=MetricUnit.Count, value=10, default_dimensions=metrics.default_dimensions
16+
) as metric:
17+
metric.add_dimension(name="TableName", value="Users")

tests/functional/test_metrics.py

+32
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,38 @@ def test_single_metric_logs_one_metric_only(capsys, metric, dimension, namespace
156156
assert expected == output
157157

158158

159+
def test_single_metric_default_dimensions(capsys, metric, dimension, namespace):
160+
# GIVEN we provide default dimensions
161+
# WHEN using single_metric context manager
162+
default_dimensions = {dimension["name"]: dimension["value"]}
163+
with single_metric(namespace=namespace, default_dimensions=default_dimensions, **metric) as my_metric:
164+
my_metric.add_metric(name="second_metric", unit="Count", value=1)
165+
166+
output = capture_metrics_output(capsys)
167+
expected = serialize_single_metric(metric=metric, dimension=dimension, namespace=namespace)
168+
169+
# THEN we should have default dimension added to the metric
170+
remove_timestamp(metrics=[output, expected])
171+
assert expected == output
172+
173+
174+
def test_single_metric_default_dimensions_inherit(capsys, metric, dimension, namespace):
175+
# GIVEN we provide Metrics default dimensions
176+
# WHEN using single_metric context manager
177+
metrics = Metrics()
178+
default_dimensions = {dimension["name"]: dimension["value"]}
179+
metrics.set_default_dimensions(**default_dimensions)
180+
with single_metric(namespace=namespace, default_dimensions=metrics.default_dimensions, **metric) as my_metric:
181+
my_metric.add_metric(name="second_metric", unit="Count", value=1)
182+
183+
output = capture_metrics_output(capsys)
184+
expected = serialize_single_metric(metric=metric, dimension=dimension, namespace=namespace)
185+
186+
# THEN we should have default dimension added to the metric
187+
remove_timestamp(metrics=[output, expected])
188+
assert expected == output
189+
190+
159191
def test_log_metrics(capsys, metrics, dimensions, namespace):
160192
# GIVEN Metrics is initialized
161193
my_metrics = Metrics(namespace=namespace)

0 commit comments

Comments
 (0)