Skip to content

Commit 08a0a7b

Browse files
refactor(metrics): move from protocol to ABC; split provider tests (#2934)
1 parent b0a3658 commit 08a0a7b

File tree

11 files changed

+358
-549
lines changed

11 files changed

+358
-549
lines changed

aws_lambda_powertools/metrics/base.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
MetricValueError,
1818
SchemaValidationError,
1919
)
20-
from aws_lambda_powertools.metrics.provider.cloudwatch_emf import cold_start
21-
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cold_start import (
22-
reset_cold_start_flag, # noqa: F401 # backwards compatibility
23-
)
20+
from aws_lambda_powertools.metrics.provider import cold_start
2421
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
2522
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
23+
from aws_lambda_powertools.metrics.provider.cold_start import (
24+
reset_cold_start_flag, # noqa: F401 # backwards compatibility
25+
)
2626
from aws_lambda_powertools.metrics.types import MetricNameUnitResolution
2727
from aws_lambda_powertools.shared import constants
2828
from aws_lambda_powertools.shared.functions import resolve_env_var_choice
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from __future__ import annotations
2+
3+
from typing import List
4+
5+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import (
6+
MetricResolutionError,
7+
MetricUnitError,
8+
)
9+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
10+
11+
12+
def extract_cloudwatch_metric_resolution_value(metric_resolutions: List, resolution: int | MetricResolution) -> int:
13+
"""Return metric value from CloudWatch metric unit whether that's str or MetricResolution enum
14+
15+
Parameters
16+
----------
17+
unit : Union[int, MetricResolution]
18+
Metric resolution
19+
20+
Returns
21+
-------
22+
int
23+
Metric resolution value must be 1 or 60
24+
25+
Raises
26+
------
27+
MetricResolutionError
28+
When metric resolution is not supported by CloudWatch
29+
"""
30+
if isinstance(resolution, MetricResolution):
31+
return resolution.value
32+
33+
if isinstance(resolution, int) and resolution in metric_resolutions:
34+
return resolution
35+
36+
raise MetricResolutionError(
37+
f"Invalid metric resolution '{resolution}', expected either option: {metric_resolutions}", # noqa: E501
38+
)
39+
40+
41+
def extract_cloudwatch_metric_unit_value(metric_units: List, metric_valid_options: List, unit: str | MetricUnit) -> str:
42+
"""Return metric value from CloudWatch metric unit whether that's str or MetricUnit enum
43+
44+
Parameters
45+
----------
46+
unit : Union[str, MetricUnit]
47+
Metric unit
48+
49+
Returns
50+
-------
51+
str
52+
Metric unit value (e.g. "Seconds", "Count/Second")
53+
54+
Raises
55+
------
56+
MetricUnitError
57+
When metric unit is not supported by CloudWatch
58+
"""
59+
60+
if isinstance(unit, str):
61+
if unit in metric_valid_options:
62+
unit = MetricUnit[unit].value
63+
64+
if unit not in metric_units:
65+
raise MetricUnitError(
66+
f"Invalid metric unit '{unit}', expected either option: {metric_valid_options}",
67+
)
68+
69+
if isinstance(unit, MetricUnit):
70+
unit = unit.value
71+
72+
return unit

aws_lambda_powertools/metrics/metrics.py

+4-129
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
# NOTE: keeps for compatibility
22
from __future__ import annotations
33

4-
from typing import Any, Callable, Dict, Optional, Union
4+
from typing import Any, Callable, Dict, Optional
55

66
from aws_lambda_powertools.metrics.base import MetricResolution, MetricUnit
77
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import AmazonCloudWatchEMFProvider
8+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.types import CloudWatchEMFOutput
89

910

1011
class Metrics:
11-
"""Metrics create an EMF object with up to 100 metrics
12+
"""Metrics create an CloudWatch EMF object with up to 100 metrics
1213
1314
Use Metrics when you need to create multiple metrics that have
1415
dimensions in common (e.g. service_name="payment").
@@ -115,7 +116,7 @@ def serialize_metric_set(
115116
metrics: Dict | None = None,
116117
dimensions: Dict | None = None,
117118
metadata: Dict | None = None,
118-
) -> Dict:
119+
) -> CloudWatchEMFOutput:
119120
return self.provider.serialize_metric_set(metrics=metrics, dimensions=dimensions, metadata=metadata)
120121

121122
def add_metadata(self, key: str, value: Any) -> None:
@@ -138,15 +139,6 @@ def log_metrics(
138139
default_dimensions=default_dimensions,
139140
)
140141

141-
def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int:
142-
return self.provider._extract_metric_resolution_value(resolution=resolution)
143-
144-
def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str:
145-
return self.provider._extract_metric_unit_value(unit=unit)
146-
147-
def _add_cold_start_metric(self, context: Any) -> None:
148-
self.provider._add_cold_start_metric(context=context)
149-
150142
def set_default_dimensions(self, **dimensions) -> None:
151143
self.provider.set_default_dimensions(**dimensions)
152144
"""Persist dimensions across Lambda invocations
@@ -208,120 +200,3 @@ def service(self, service):
208200
# we can quickly revert and duplicate code while using self.provider
209201

210202
EphemeralMetrics = AmazonCloudWatchEMFProvider
211-
212-
# noqa: ERA001
213-
# class EphemeralMetrics(MetricManager):
214-
# """Non-singleton version of Metrics to not persist metrics across instances
215-
#
216-
# NOTE: This is useful when you want to:
217-
#
218-
# - Create metrics for distinct namespaces
219-
# - Create the same metrics with different dimensions more than once
220-
# """
221-
#
222-
# # _dimensions: Dict[str, str] = {}
223-
# _default_dimensions: Dict[str, Any] = {}
224-
#
225-
# def __init__(
226-
# self,
227-
# service: str | None = None,
228-
# namespace: str | None = None,
229-
# provider: AmazonCloudWatchEMFProvider | None = None,
230-
# ):
231-
# super().__init__(namespace=namespace, service=service)
232-
#
233-
# self.default_dimensions = self._default_dimensions
234-
# # # self.dimension_set = self._dimensions
235-
# # self.dimension_set.update(**self._default_dimensions)
236-
#
237-
# self.provider = provider or AmazonCloudWatchEMFProvider(
238-
# namespace=namespace,
239-
# service=service,
240-
# metric_set=self.metric_set,
241-
# metadata_set=self.metadata_set,
242-
# dimension_set=self.dimension_set,
243-
# default_dimensions=self._default_dimensions,
244-
# )
245-
#
246-
# def add_metric(
247-
# self,
248-
# name: str,
249-
# unit: MetricUnit | str,
250-
# value: float,
251-
# resolution: MetricResolution | int = 60,
252-
# ) -> None:
253-
# return self.provider.add_metric(name=name, unit=unit, value=value, resolution=resolution)
254-
#
255-
# def add_dimension(self, name: str, value: str) -> None:
256-
# return self.provider.add_dimension(name=name, value=value)
257-
#
258-
# def serialize_metric_set(
259-
# self,
260-
# metrics: Dict | None = None,
261-
# dimensions: Dict | None = None,
262-
# metadata: Dict | None = None,
263-
# ) -> Dict:
264-
# return self.provider.serialize_metric_set(metrics=metrics, dimensions=dimensions, metadata=metadata)
265-
#
266-
# def add_metadata(self, key: str, value: Any) -> None:
267-
# self.provider.add_metadata(key=key, value=value)
268-
#
269-
# def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:
270-
# self.provider.flush_metrics(raise_on_empty_metrics=raise_on_empty_metrics)
271-
#
272-
# def log_metrics(
273-
# self,
274-
# lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
275-
# capture_cold_start_metric: bool = False,
276-
# raise_on_empty_metrics: bool = False,
277-
# default_dimensions: Dict[str, str] | None = None,
278-
# ):
279-
# return self.provider.log_metrics(
280-
# lambda_handler=lambda_handler,
281-
# capture_cold_start_metric=capture_cold_start_metric,
282-
# raise_on_empty_metrics=raise_on_empty_metrics,
283-
# default_dimensions=default_dimensions,
284-
# )
285-
#
286-
# def _extract_metric_resolution_value(self, resolution: Union[int, MetricResolution]) -> int:
287-
# return self.provider._extract_metric_resolution_value(resolution=resolution)
288-
#
289-
# def _extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str:
290-
# return self.provider._extract_metric_unit_value(unit=unit)
291-
#
292-
# def _add_cold_start_metric(self, context: Any) -> None:
293-
# return self.provider._add_cold_start_metric(context=context)
294-
#
295-
# def set_default_dimensions(self, **dimensions) -> None:
296-
# """Persist dimensions across Lambda invocations
297-
#
298-
# Parameters
299-
# ----------
300-
# dimensions : Dict[str, Any], optional
301-
# metric dimensions as key=value
302-
#
303-
# Example
304-
# -------
305-
# **Sets some default dimensions that will always be present across metrics and invocations**
306-
#
307-
# from aws_lambda_powertools import Metrics
308-
#
309-
# metrics = Metrics(namespace="ServerlessAirline", service="payment")
310-
# metrics.set_default_dimensions(environment="demo", another="one")
311-
#
312-
# @metrics.log_metrics()
313-
# def lambda_handler():
314-
# return True
315-
# """
316-
# return self.provider.set_default_dimensions(**dimensions)
317-
#
318-
# def clear_default_dimensions(self) -> None:
319-
# self.default_dimensions.clear()
320-
#
321-
# def clear_metrics(self) -> None:
322-
# self.provider.clear_metrics()
323-
# # re-add default dimensions
324-
# self.set_default_dimensions(**self.default_dimensions)
325-
#
326-
327-
# __all__ = []
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
from aws_lambda_powertools.metrics.provider.base import MetricsBase, MetricsProviderBase
1+
from aws_lambda_powertools.metrics.provider.base import BaseProvider
22

33
__all__ = [
4-
"MetricsBase",
5-
"MetricsProviderBase",
4+
"BaseProvider",
65
]

0 commit comments

Comments
 (0)