Skip to content

Commit d4f8a19

Browse files
committed
fix: split ColdStart metric to its own EMF blob #125
1 parent c9252c7 commit d4f8a19

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

Diff for: aws_lambda_powertools/metrics/metrics.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import warnings
55
from typing import Any, Callable
66

7-
from .base import MetricManager
7+
from .base import MetricManager, MetricUnit
8+
from .metric import single_metric
89

910
logger = logging.getLogger(__name__)
1011

@@ -167,6 +168,7 @@ def __add_cold_start_metric(self, context: Any):
167168
global is_cold_start
168169
if is_cold_start:
169170
logger.debug("Adding cold start metric and function_name dimension")
170-
self.add_metric(name="ColdStart", value=1, unit="Count")
171-
self.add_dimension(name="function_name", value=context.function_name)
172-
is_cold_start = False
171+
with single_metric(name="ColdStart", unit=MetricUnit.Count, value=1, namespace=self.namespace) as metric:
172+
metric.add_dimension(name="function_name", value=context.function_name)
173+
metric.add_dimension(name="service", value=self.service)
174+
is_cold_start = False

Diff for: tests/functional/test_metrics.py

+38-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77

88
from aws_lambda_powertools import Metrics, single_metric
99
from aws_lambda_powertools.metrics import MetricUnit, MetricUnitError, MetricValueError, SchemaValidationError
10+
from aws_lambda_powertools.metrics import metrics as metrics_global
1011
from aws_lambda_powertools.metrics.base import MetricManager
1112

1213

1314
@pytest.fixture(scope="function", autouse=True)
1415
def reset_metric_set():
1516
metrics = Metrics()
1617
metrics.clear_metrics()
18+
metrics_global.is_cold_start = True # ensure each test has cold start
1719
yield
1820

1921

@@ -112,6 +114,10 @@ def capture_metrics_output(capsys):
112114
return json.loads(capsys.readouterr().out.strip())
113115

114116

117+
def capture_metrics_output_multiple_emf_objects(capsys):
118+
return [json.loads(line.strip()) for line in capsys.readouterr().out.split("\n") if line]
119+
120+
115121
def test_single_metric_logs_one_metric_only(capsys, metric, dimension, namespace):
116122
# GIVEN we try adding more than one metric
117123
# WHEN using single_metric context manager
@@ -495,7 +501,7 @@ def lambda_handler(evt, context):
495501

496502
LambdaContext = namedtuple("LambdaContext", "function_name")
497503
lambda_handler({}, LambdaContext("example_fn"))
498-
_ = capture_metrics_output(capsys) # ignore first stdout captured
504+
_, _ = capture_metrics_output_multiple_emf_objects(capsys) # ignore first stdout captured
499505

500506
# THEN ColdStart metric and function_name dimension should be logged once
501507
lambda_handler({}, LambdaContext("example_fn"))
@@ -630,3 +636,34 @@ def test_serialize_metric_set_metric_definition(metric, dimension, namespace, se
630636
assert "Timestamp" in metric_definition_output["_aws"]
631637
remove_timestamp(metrics=[metric_definition_output, expected_metric_definition])
632638
assert metric_definition_output == expected_metric_definition
639+
640+
641+
def test_log_metrics_capture_cold_start_metric_separately(capsys, namespace, service, metric, dimension):
642+
# GIVEN Metrics is initialized
643+
my_metrics = Metrics(service=service, namespace=namespace)
644+
645+
# WHEN log_metrics is used with capture_cold_start_metric
646+
@my_metrics.log_metrics(capture_cold_start_metric=True)
647+
def lambda_handler(evt, context):
648+
my_metrics.add_metric(**metric)
649+
my_metrics.add_dimension(**dimension)
650+
651+
LambdaContext = namedtuple("LambdaContext", "function_name")
652+
lambda_handler({}, LambdaContext("example_fn"))
653+
654+
cold_start_blob, custom_metrics_blob = capture_metrics_output_multiple_emf_objects(capsys)
655+
656+
# THEN ColdStart metric and function_name dimension should be logged
657+
# in a separate EMF blob than the application metrics
658+
assert cold_start_blob["ColdStart"] == 1
659+
assert cold_start_blob["function_name"] == "example_fn"
660+
assert cold_start_blob["service"] == service
661+
662+
# and that application metrics dimensions are not part of ColdStart EMF blob
663+
assert "test_dimension" not in cold_start_blob
664+
665+
# THEN application metrics EMF blob should not have function_name dimension
666+
assert "function_name" not in custom_metrics_blob
667+
assert custom_metrics_blob["service"] == service
668+
assert custom_metrics_blob["single_metric"] == metric["value"]
669+
assert custom_metrics_blob["test_dimension"] == dimension["value"]

0 commit comments

Comments
 (0)