Skip to content

Commit 62766e7

Browse files
feat(metrics): support to set default dimension in EphemeralMetrics (#2748)
metrics: add default dimension into EphemeralMetrics
1 parent 2c44207 commit 62766e7

File tree

4 files changed

+85
-5
lines changed

4 files changed

+85
-5
lines changed

aws_lambda_powertools/metrics/metrics.py

+41
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,46 @@ class EphemeralMetrics(MetricManager):
128128
- Create the same metrics with different dimensions more than once
129129
"""
130130

131+
_dimensions: Dict[str, str] = {}
132+
_default_dimensions: Dict[str, Any] = {}
133+
131134
def __init__(self, service: Optional[str] = None, namespace: Optional[str] = None):
135+
self.default_dimensions = self._default_dimensions
136+
self.dimension_set = self._dimensions
137+
138+
self.dimension_set.update(**self._default_dimensions)
132139
super().__init__(namespace=namespace, service=service)
140+
141+
def set_default_dimensions(self, **dimensions) -> None:
142+
"""Persist dimensions across Lambda invocations
143+
144+
Parameters
145+
----------
146+
dimensions : Dict[str, Any], optional
147+
metric dimensions as key=value
148+
149+
Example
150+
-------
151+
**Sets some default dimensions that will always be present across metrics and invocations**
152+
153+
from aws_lambda_powertools import Metrics
154+
155+
metrics = Metrics(namespace="ServerlessAirline", service="payment")
156+
metrics.set_default_dimensions(environment="demo", another="one")
157+
158+
@metrics.log_metrics()
159+
def lambda_handler():
160+
return True
161+
"""
162+
for name, value in dimensions.items():
163+
self.add_dimension(name, value)
164+
165+
self.default_dimensions.update(**dimensions)
166+
167+
def clear_default_dimensions(self) -> None:
168+
self.default_dimensions.clear()
169+
170+
def clear_metrics(self) -> None:
171+
super().clear_metrics()
172+
# re-add default dimensions
173+
self.set_default_dimensions(**self.default_dimensions)

aws_lambda_powertools/shared/user_agent.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def register_feature_to_session(session, feature):
112112
def register_feature_to_botocore_session(botocore_session, feature):
113113
"""
114114
Register the given feature string to the event system of the provided botocore session
115-
115+
116116
Please notice this function is for patching botocore session and is different from
117117
previous one which is for patching boto3 session
118118
@@ -127,7 +127,7 @@ def register_feature_to_botocore_session(botocore_session, feature):
127127
------
128128
AttributeError
129129
If the provided session does not have an event system.
130-
130+
131131
Examples
132132
--------
133133
**register data-masking user-agent to botocore session**
@@ -139,7 +139,7 @@ def register_feature_to_botocore_session(botocore_session, feature):
139139
>>> session = botocore.session.Session()
140140
>>> register_feature_to_botocore_session(botocore_session=session, feature="data-masking")
141141
>>> key_provider = StrictAwsKmsMasterKeyProvider(key_ids=self.keys, botocore_session=session)
142-
142+
143143
"""
144144
try:
145145
botocore_session.register(TARGET_SDK_EVENT, _create_feature_function(feature))

docs/core/metrics.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -274,12 +274,11 @@ You can use `EphemeralMetrics` class when looking to isolate multiple instances
274274

275275
**Differences between `EphemeralMetrics` and `Metrics`**
276276

277-
`EphemeralMetrics` has only two differences while keeping nearly the exact same set of features:
277+
`EphemeralMetrics` has only one difference while keeping nearly the exact same set of features:
278278

279279
| Feature | Metrics | EphemeralMetrics |
280280
| ----------------------------------------------------------------------------------------------------------- | ------- | ---------------- |
281281
| **Share data across instances** (metrics, dimensions, metadata, etc.) | Yes | - |
282-
| **[Default dimensions](#adding-default-dimensions) that persists across Lambda invocations** (metric flush) | Yes | - |
283282

284283
!!! question "Why not changing the default `Metrics` behaviour to not share data across instances?"
285284

tests/functional/test_metrics.py

+40
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,46 @@ def test_metrics_reuse_metadata_set(metric, dimension, namespace):
11151115
assert my_metrics_2.metadata_set == my_metrics.metadata_set
11161116

11171117

1118+
def test_log_ephemeral_metrics_with_default_dimensions(capsys, metrics, dimensions, namespace):
1119+
# GIVEN Metrics is initialized
1120+
my_metrics = EphemeralMetrics(namespace=namespace)
1121+
default_dimensions = {"environment": "test", "log_group": "/lambda/test"}
1122+
1123+
# WHEN we utilize log_metrics with default dimensions to serialize
1124+
# and flush metrics and clear all metrics and dimensions from memory
1125+
# at the end of a function execution
1126+
@my_metrics.log_metrics(default_dimensions=default_dimensions)
1127+
def lambda_handler(evt, ctx):
1128+
for metric in metrics:
1129+
my_metrics.add_metric(**metric)
1130+
1131+
lambda_handler({}, {})
1132+
first_invocation = capture_metrics_output(capsys)
1133+
1134+
lambda_handler({}, {})
1135+
second_invocation = capture_metrics_output(capsys)
1136+
1137+
# THEN we should have default dimensions in both outputs
1138+
assert "environment" in first_invocation
1139+
assert "environment" in second_invocation
1140+
1141+
1142+
def test_ephemeral_metrics_isolated_data_set_with_default_dimension(metric, dimension, namespace, capsys):
1143+
# GIVEN two EphemeralMetrics instances are initialized
1144+
# One with default dimension and another without
1145+
my_metrics = EphemeralMetrics(namespace=namespace)
1146+
my_metrics.set_default_dimensions(dev="powertools")
1147+
isolated_metrics = EphemeralMetrics(namespace=namespace)
1148+
1149+
# WHEN metrics added to the both instances
1150+
my_metrics.add_metric(**metric)
1151+
isolated_metrics.add_metric(**metric)
1152+
1153+
# THEN the second instance should not have dimensions
1154+
assert my_metrics.metric_set == isolated_metrics.metric_set
1155+
assert my_metrics.dimension_set != isolated_metrics.dimension_set
1156+
1157+
11181158
def test_ephemeral_metrics_isolates_data_set(metric, dimension, namespace, metadata):
11191159
# GIVEN two EphemeralMetrics instances are initialized
11201160
my_metrics = EphemeralMetrics(namespace=namespace)

0 commit comments

Comments
 (0)