diff --git a/python/HISTORY.md b/python/HISTORY.md index 8001c9bba2c..69d85ad9f25 100644 --- a/python/HISTORY.md +++ b/python/HISTORY.md @@ -1,7 +1,27 @@ # HISTORY +## May 1st + +**0.8.1** + +* Fix metric unit casting logic if one passes plain string (value or key) +* Fix `MetricUnit` enum values for + - `BytesPerSecond` + - `KilobytesPerSecond` + - `MegabytesPerSecond` + - `GigabytesPerSecond` + - `TerabytesPerSecond` + - `BitsPerSecond` + - `KilobitsPerSecond` + - `MegabitsPerSecond` + - `GigabitsPerSecond` + - `TerabitsPerSecond` + - `CountPerSecond` + ## April 24th +**0.8.0** + * Introduces `Logger` for stuctured logging as a replacement for `logger_setup` * Introduces `Logger.inject_lambda_context` decorator as a replacement for `logger_inject_lambda_context` * Raise `DeprecationWarning` exception for both `logger_setup`, `logger_inject_lambda_context` diff --git a/python/aws_lambda_powertools/helper/models.py b/python/aws_lambda_powertools/helper/models.py index 424e5bf3aef..16a5df3669e 100644 --- a/python/aws_lambda_powertools/helper/models.py +++ b/python/aws_lambda_powertools/helper/models.py @@ -89,17 +89,17 @@ class MetricUnit(Enum): Terabits = "Terabits" Percent = "Percent" Count = "Count" - BytesPerSecond = "Second" - KilobytesPerSecond = "Second" - MegabytesPerSecond = "Second" - GigabytesPerSecond = "Second" - TerabytesPerSecond = "Second" - BitsPerSecond = "Second" - KilobitsPerSecond = "Second" - MegabitsPerSecond = "Second" - GigabitsPerSecond = "Second" - TerabitsPerSecond = "Second" - CountPerSecond = "Second" + BytesPerSecond = "Bytes/Second" + KilobytesPerSecond = "Kilobytes/Second" + MegabytesPerSecond = "Megabytes/Second" + GigabytesPerSecond = "Gigabytes/Second" + TerabytesPerSecond = "Terabytes/Second" + BitsPerSecond = "Bits/Second" + KilobitsPerSecond = "Kilobits/Second" + MegabitsPerSecond = "Megabits/Second" + GigabitsPerSecond = "Gigabits/Second" + TerabitsPerSecond = "Terabits/Second" + CountPerSecond = "Count/Second" def build_metric_unit_from_str(unit: Union[str, MetricUnit]) -> MetricUnit: diff --git a/python/aws_lambda_powertools/metrics/base.py b/python/aws_lambda_powertools/metrics/base.py index 8d561abf71d..38e513f19a8 100644 --- a/python/aws_lambda_powertools/metrics/base.py +++ b/python/aws_lambda_powertools/metrics/base.py @@ -53,6 +53,8 @@ def __init__(self, metric_set: Dict[str, str] = None, dimension_set: Dict = None self.metric_set = metric_set or {} self.dimension_set = dimension_set or {} self.namespace = os.getenv("POWERTOOLS_METRICS_NAMESPACE") or namespace + self._metric_units = [unit.value for unit in MetricUnit] + self._metric_unit_options = list(MetricUnit.__members__) def add_namespace(self, name: str): """Adds given metric namespace @@ -105,14 +107,8 @@ def add_metric(self, name: str, unit: MetricUnit, value: Union[float, int]): if not isinstance(value, numbers.Number): raise MetricValueError(f"{value} is not a valid number") - if not isinstance(unit, MetricUnit): - try: - unit = MetricUnit[unit] - except KeyError: - unit_options = list(MetricUnit.__members__) - raise MetricUnitError(f"Invalid metric unit '{unit}', expected either option: {unit_options}") - - metric = {"Unit": unit.value, "Value": float(value)} + unit = self.__extract_metric_unit_value(unit=unit) + metric = {"Unit": unit, "Value": float(value)} logger.debug(f"Adding metric: {name} with {metric}") self.metric_set[name] = metric @@ -205,3 +201,36 @@ def add_dimension(self, name: str, value: str): """ logger.debug(f"Adding dimension: {name}:{value}") self.dimension_set[name] = value + + def __extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str: + """Return metric value from metric unit whether that's str or MetricUnit enum + + Parameters + ---------- + unit : Union[str, MetricUnit] + Metric unit + + Returns + ------- + str + Metric unit value (e.g. "Seconds", "Count/Second") + + Raises + ------ + MetricUnitError + When metric unit is not supported by CloudWatch + """ + + if isinstance(unit, str): + if unit in self._metric_unit_options: + unit = MetricUnit[unit].value + + if unit not in self._metric_units: # str correta + raise MetricUnitError( + f"Invalid metric unit '{unit}', expected either option: {self._metric_unit_options}" + ) + + if isinstance(unit, MetricUnit): + unit = unit.value + + return unit diff --git a/python/pyproject.toml b/python/pyproject.toml index 8b21c9dce86..99a3564ca22 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "aws_lambda_powertools" -version = "0.8.0" +version = "0.8.1" description = "Python utilities for AWS Lambda functions including but not limited to tracing, logging and custom metric" authors = ["Amazon Web Services"] classifiers=[ diff --git a/python/tests/functional/test_metrics.py b/python/tests/functional/test_metrics.py index 703c8788ac1..7c6990668bc 100644 --- a/python/tests/functional/test_metrics.py +++ b/python/tests/functional/test_metrics.py @@ -303,3 +303,28 @@ def lambda_handler(evt, context): with pytest.raises(SchemaValidationError): lambda_handler({}, {}) + + +def test_all_metric_units_string(metric, dimension, namespace): + + # metric unit as MetricUnit key e.g. "Seconds", "BytesPerSecond" + for unit in MetricUnit: + metric["unit"] = unit.name + with single_metric(**metric) as my_metric: + my_metric.add_dimension(**dimension) + my_metric.add_namespace(**namespace) + + with pytest.raises(MetricUnitError): + metric["unit"] = "seconds" + with single_metric(**metric) as my_metric: + my_metric.add_dimension(**dimension) + my_metric.add_namespace(**namespace) + + all_metric_units = [unit.value for unit in MetricUnit] + + # metric unit as MetricUnit value e.g. "Seconds", "Bytes/Second" + for unit in all_metric_units: + metric["unit"] = unit + with single_metric(**metric) as my_metric: + my_metric.add_dimension(**dimension) + my_metric.add_namespace(**namespace)