Skip to content

refactor(metrics): optimize validation and serialization #307

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions aws_lambda_powertools/metrics/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@

from ..shared import constants
from ..shared.functions import resolve_env_var_choice
from ..shared.lazy_import import LazyLoader
from .exceptions import MetricUnitError, MetricValueError, SchemaValidationError
from .schema import CLOUDWATCH_EMF_SCHEMA

fastjsonschema = LazyLoader("fastjsonschema", globals(), "fastjsonschema")
logger = logging.getLogger(__name__)

MAX_METRICS = 100
MAX_DIMENSIONS = 9


class MetricUnit(Enum):
Expand Down Expand Up @@ -180,6 +178,12 @@ def serialize_metric_set(self, metrics: Dict = None, dimensions: Dict = None, me
if self.service and not self.dimension_set.get("service"):
self.dimension_set["service"] = self.service

if len(metrics) == 0:
raise SchemaValidationError("Must contain at least one metric.")

if self.namespace is None:
raise SchemaValidationError("Must contain a metric namespace.")

logger.debug({"details": "Serializing metrics", "metrics": metrics, "dimensions": dimensions})

metric_names_and_units: List[Dict[str, str]] = [] # [ { "Name": "metric_name", "Unit": "Count" } ]
Expand Down Expand Up @@ -209,12 +213,6 @@ def serialize_metric_set(self, metrics: Dict = None, dimensions: Dict = None, me
**metric_names_and_values, # "single_metric": 1.0
}

try:
logger.debug("Validating serialized metrics against CloudWatch EMF schema")
fastjsonschema.validate(definition=CLOUDWATCH_EMF_SCHEMA, data=embedded_metrics_object)
except fastjsonschema.JsonSchemaException as e:
message = f"Invalid format. Error: {e.message}, Invalid item: {e.name}" # noqa: B306, E501
raise SchemaValidationError(message)
return embedded_metrics_object

def add_dimension(self, name: str, value: str):
Expand All @@ -234,7 +232,10 @@ def add_dimension(self, name: str, value: str):
Dimension value
"""
logger.debug(f"Adding dimension: {name}:{value}")

if len(self.dimension_set) == 9:
raise SchemaValidationError(
f"Maximum number of dimensions exceeded ({MAX_DIMENSIONS}): Unable to add dimension {name}."
)
# Cast value to str according to EMF spec
# Majority of values are expected to be string already, so
# checking before casting improves performance in most cases
Expand Down Expand Up @@ -295,7 +296,7 @@ def __extract_metric_unit_value(self, unit: Union[str, MetricUnit]) -> str:
if unit in self._metric_unit_options:
unit = MetricUnit[unit].value

if unit not in self._metric_units: # str correta
if unit not in self._metric_units:
raise MetricUnitError(
f"Invalid metric unit '{unit}', expected either option: {self._metric_unit_options}"
)
Expand Down
10 changes: 7 additions & 3 deletions aws_lambda_powertools/metrics/metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,12 @@ def single_metric(name: str, unit: MetricUnit, value: float, namespace: str = No

Raises
------
e
Propagate error received
MetricUnitError
When metric metric isn't supported by CloudWatch
MetricValueError
When metric value isn't a number
SchemaValidationError
When metric object fails EMF schema validation
"""
metric_set = None
try:
Expand All @@ -112,4 +116,4 @@ def single_metric(name: str, unit: MetricUnit, value: float, namespace: str = No
yield metric
metric_set: Dict = metric.serialize_metric_set()
finally:
print(json.dumps(metric_set))
print(json.dumps(metric_set, separators=(",", ":")))
16 changes: 11 additions & 5 deletions aws_lambda_powertools/metrics/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,19 @@ def do_something():

Parameters
----------
MetricManager : MetricManager
Inherits from `aws_lambda_powertools.metrics.base.MetricManager`
service : str, optional
service name to be used as metric dimension, by default "service_undefined"
namespace : str
Namespace for metrics

Raises
------
e
Propagate error received
MetricUnitError
When metric metric isn't supported by CloudWatch
MetricValueError
When metric value isn't a number
SchemaValidationError
When metric object fails EMF schema validation
"""

_metrics = {}
Expand Down Expand Up @@ -150,7 +156,7 @@ def decorate(event, context):
else:
metrics = self.serialize_metric_set()
self.clear_metrics()
print(json.dumps(metrics))
print(json.dumps(metrics, separators=(",", ":")))

return response

Expand Down
94 changes: 0 additions & 94 deletions aws_lambda_powertools/metrics/schema.py

This file was deleted.

Loading