Skip to content

Commit dcd61f3

Browse files
feat(metrics): add runtime validations for the metric name (#7026)
* Added runtime validation for the metric name * Updated the tests to test the EMFMetricProvider --------- Co-authored-by: Swopnil Dangol <[email protected]>
1 parent 3688010 commit dcd61f3

File tree

5 files changed

+69
-2
lines changed

5 files changed

+69
-2
lines changed

aws_lambda_powertools/metrics/base.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@
2525
)
2626
from aws_lambda_powertools.metrics.functions import convert_timestamp_to_emf_format, validate_emf_timestamp
2727
from aws_lambda_powertools.metrics.provider import cold_start
28-
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
28+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import (
29+
MAX_DIMENSIONS,
30+
MAX_METRIC_NAME_LENGTH,
31+
MAX_METRICS,
32+
MIN_METRIC_NAME_LENGTH,
33+
)
34+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricNameError
2935
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
3036
from aws_lambda_powertools.metrics.provider.cold_start import (
3137
reset_cold_start_flag, # noqa: F401 # backwards compatibility
@@ -129,11 +135,18 @@ def add_metric(
129135
130136
Raises
131137
------
138+
MetricNameError
139+
When metric name does not fall under Cloudwatch constraints
132140
MetricUnitError
133141
When metric unit is not supported by CloudWatch
134142
MetricResolutionError
135143
When metric resolution is not supported by CloudWatch
136144
"""
145+
name = name.strip()
146+
if len(name) < MIN_METRIC_NAME_LENGTH or len(name) > MAX_METRIC_NAME_LENGTH:
147+
raise MetricNameError(
148+
f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
149+
)
137150
if not isinstance(value, numbers.Number):
138151
raise MetricValueError(f"{value} is not a valid number")
139152

aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@
2020
validate_emf_timestamp,
2121
)
2222
from aws_lambda_powertools.metrics.provider.base import BaseProvider
23-
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import MAX_DIMENSIONS, MAX_METRICS
23+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import (
24+
MAX_DIMENSIONS,
25+
MAX_METRIC_NAME_LENGTH,
26+
MAX_METRICS,
27+
MIN_METRIC_NAME_LENGTH,
28+
)
29+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricNameError
2430
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.metric_properties import MetricResolution, MetricUnit
2531
from aws_lambda_powertools.shared import constants
2632
from aws_lambda_powertools.shared.functions import resolve_env_var_choice
@@ -137,6 +143,11 @@ def add_metric(
137143
When metric resolution is not supported by CloudWatch
138144
"""
139145

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
MAX_DIMENSIONS = 29
22
MAX_METRICS = 100
3+
MIN_METRIC_NAME_LENGTH = 1
4+
MAX_METRIC_NAME_LENGTH = 255

aws_lambda_powertools/metrics/provider/cloudwatch_emf/exceptions.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
class MetricNameError(Exception):
2+
"""When metric name does not fall under Cloudwatch constraints"""
3+
4+
pass
5+
6+
17
class MetricUnitError(Exception):
28
"""When metric unit is not supported by CloudWatch"""
39

tests/functional/metrics/required_dependencies/test_metrics_cloudwatch_emf.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@
2424
)
2525
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.constants import (
2626
MAX_DIMENSIONS,
27+
MAX_METRIC_NAME_LENGTH,
28+
MIN_METRIC_NAME_LENGTH,
2729
)
30+
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.exceptions import MetricNameError
2831

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

445448

449+
def test_schema_validation_empty_metric_name(metric, dimension, namespace):
450+
# GIVEN we pass an empty metric name
451+
my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace)
452+
metric["name"] = ""
453+
454+
# WHEN we attempt to add a metric
455+
# THEN it should fail validation and raise MetricNameError
456+
with pytest.raises(
457+
MetricNameError,
458+
match=f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
459+
):
460+
my_metrics.add_metric(**metric)
461+
462+
463+
def test_schema_validation_long_metric_name(metric, dimension, namespace):
464+
# GIVEN we pass a metric name outside the maximum length constraint
465+
my_metrics = AmazonCloudWatchEMFProvider(namespace=namespace)
466+
metric[
467+
"name"
468+
] = """Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa.
469+
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis,
470+
ultricies nec, pellentesque eu, pretium quis,."""
471+
472+
# WHEN we attempt to serialize a valid EMF object
473+
# THEN it should fail validation and raise SchemaValidationError
474+
with pytest.raises(
475+
MetricNameError,
476+
match=f"The metric name should be between {MIN_METRIC_NAME_LENGTH} and {MAX_METRIC_NAME_LENGTH} characters",
477+
):
478+
my_metrics.add_metric(**metric)
479+
480+
446481
def test_schema_validation_incorrect_metric_value(metric, dimension, namespace):
447482
# GIVEN we pass an incorrect metric value (non-numeric)
448483
metric["value"] = "some_value"

0 commit comments

Comments
 (0)