Skip to content
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
15 changes: 14 additions & 1 deletion aws_lambda_powertools/metrics/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@
)
from aws_lambda_powertools.metrics.functions import convert_timestamp_to_emf_format, validate_emf_timestamp
from aws_lambda_powertools.metrics.provider import cold_start
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import (
MAX_DIMENSIONS,
MAX_METRIC_NAME_LENGTH,
MAX_METRICS,
MIN_METRIC_NAME_LENGTH,
)
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricNameError
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
from aws_lambda_powertools.metrics.provider.cold_start import (
reset_cold_start_flag, # noqa: F401 # backwards compatibility
Expand Down Expand Up @@ -129,11 +135,18 @@ def add_metric(

Raises
------
MetricNameError
When metric name does not fall under Cloudwatch constraints
MetricUnitError
When metric unit is not supported by CloudWatch
MetricResolutionError
When metric resolution is not supported by CloudWatch
"""
name = name.strip()
if len(name) < MIN_METRIC_NAME_LENGTH or len(name) > MAX_METRIC_NAME_LENGTH:
raise MetricNameError(
f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
)
if not isinstance(value, numbers.Number):
raise MetricValueError(f"{value} is not a valid number")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@
validate_emf_timestamp,
)
from aws_lambda_powertools.metrics.provider.base import BaseProvider
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import (
MAX_DIMENSIONS,
MAX_METRIC_NAME_LENGTH,
MAX_METRICS,
MIN_METRIC_NAME_LENGTH,
)
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricNameError
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
from aws_lambda_powertools.shared import constants
from aws_lambda_powertools.shared.functions import resolve_env_var_choice
Expand Down Expand Up @@ -137,6 +143,11 @@ def add_metric(
When metric resolution is not supported by CloudWatch
"""

name = name.strip()
if len(name) < MIN_METRIC_NAME_LENGTH or len(name) > MAX_METRIC_NAME_LENGTH:
raise MetricNameError(
f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
)
if not isinstance(value, numbers.Number):
raise MetricValueError(f"{value} is not a valid number")

Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
MAX_DIMENSIONS = 29
MAX_METRICS = 100
MIN_METRIC_NAME_LENGTH = 1
MAX_METRIC_NAME_LENGTH = 255
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
class MetricNameError(Exception):
"""When metric name does not fall under Cloudwatch constraints"""

pass


class MetricUnitError(Exception):
"""When metric unit is not supported by CloudWatch"""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
)
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import (
MAX_DIMENSIONS,
MAX_METRIC_NAME_LENGTH,
MIN_METRIC_NAME_LENGTH,
)
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricNameError

if TYPE_CHECKING:
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.types import (
Expand Down Expand Up @@ -443,6 +446,38 @@ def test_schema_validation_no_namespace(metric, dimension):
my_metric.add_dimension(**dimension)


def test_schema_validation_empty_metric_name(metric, dimension, namespace):
# GIVEN we pass an empty metric name
my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace)
metric["name"] = ""

# WHEN we attempt to add a metric
# THEN it should fail validation and raise MetricNameError
with pytest.raises(
MetricNameError,
match=f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
):
my_metrics.add_metric(**metric)


def test_schema_validation_long_metric_name(metric, dimension, namespace):
# GIVEN we pass a metric name outside the maximum length constraint
my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace)
metric[
"name"
] = """Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
ultricies nec, pellentesque eu, pretium quis,."""

# WHEN we attempt to serialize a valid EMF object
# THEN it should fail validation and raise SchemaValidationError
with pytest.raises(
MetricNameError,
match=f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
):
my_metrics.add_metric(**metric)


def test_schema_validation_incorrect_metric_value(metric, dimension, namespace):
# GIVEN we pass an incorrect metric value (non-numeric)
metric["value"] = "some_value"
Expand Down