diff --git a/CHANGELOG.md b/CHANGELOG.md index a658e399..f38a01d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +# Version 9 / 2019-11-04 + +- Tag layer-generated `aws.lambda.enhanced.invocations` and `aws.lambda.enhanced.errors` enhanced metrics with `runtime` and `memorysize` + # Version 8 / 2019-10-24 - Remove vendored botocore requests patching since the package has been removed from the latest botocore diff --git a/datadog_lambda/__init__.py b/datadog_lambda/__init__.py index 0edd20bc..16d81390 100644 --- a/datadog_lambda/__init__.py +++ b/datadog_lambda/__init__.py @@ -1,6 +1,6 @@ # The minor version corresponds to the Lambda layer version. # E.g.,, version 0.5.0 gets packaged into layer version 5. -__version__ = '0.8.0' +__version__ = '0.9.0' import os diff --git a/datadog_lambda/metric.py b/datadog_lambda/metric.py index 784b4286..3a1997e8 100644 --- a/datadog_lambda/metric.py +++ b/datadog_lambda/metric.py @@ -14,8 +14,7 @@ from datadog import api from datadog.threadstats import ThreadStats from datadog_lambda import __version__ -from datadog_lambda.cold_start import get_cold_start_tag -from datadog_lambda.tags import parse_lambda_tags_from_arn +from datadog_lambda.tags import get_enhanced_metrics_tags ENHANCED_METRICS_NAMESPACE_PREFIX = "aws.lambda.enhanced" @@ -82,7 +81,7 @@ def are_enhanced_metrics_enabled(): return os.environ.get("DD_ENHANCED_METRICS", "false").lower() == "true" -def submit_invocations_metric(lambda_arn): +def submit_invocations_metric(lambda_context): """Increment aws.lambda.enhanced.invocations by 1 """ if not are_enhanced_metrics_enabled(): @@ -91,11 +90,11 @@ def submit_invocations_metric(lambda_arn): lambda_metric( "{}.invocations".format(ENHANCED_METRICS_NAMESPACE_PREFIX), 1, - tags=parse_lambda_tags_from_arn(lambda_arn) + [get_cold_start_tag()], + tags=get_enhanced_metrics_tags(lambda_context), ) -def submit_errors_metric(lambda_arn): +def submit_errors_metric(lambda_context): """Increment aws.lambda.enhanced.errors by 1 """ if not are_enhanced_metrics_enabled(): @@ -104,7 +103,7 @@ def submit_errors_metric(lambda_arn): lambda_metric( "{}.errors".format(ENHANCED_METRICS_NAMESPACE_PREFIX), 1, - tags=parse_lambda_tags_from_arn(lambda_arn) + [get_cold_start_tag()], + tags=get_enhanced_metrics_tags(lambda_context), ) diff --git a/datadog_lambda/tags.py b/datadog_lambda/tags.py index 4d962257..fa9f8ec2 100644 --- a/datadog_lambda/tags.py +++ b/datadog_lambda/tags.py @@ -1,3 +1,8 @@ +from platform import python_version_tuple + +from datadog_lambda.cold_start import get_cold_start_tag + + def parse_lambda_tags_from_arn(arn): """Generate the list of lambda tags based on the data in the arn Args: @@ -18,3 +23,23 @@ def parse_lambda_tags_from_arn(arn): "account_id:{}".format(account_id), "functionname:{}".format(function_name), ] + + +def get_runtime_tag(): + """Get the runtime tag from the current Python version + """ + major_version, minor_version, _ = python_version_tuple() + + return "runtime:python{major}.{minor}".format( + major=major_version, minor=minor_version + ) + + +def get_enhanced_metrics_tags(lambda_context): + """Get the list of tags to apply to enhanced metrics + """ + return parse_lambda_tags_from_arn(lambda_context.invoked_function_arn) + [ + get_cold_start_tag(), + "memorysize:{}".format(lambda_context.memory_limit_in_mb), + get_runtime_tag(), + ] diff --git a/datadog_lambda/wrapper.py b/datadog_lambda/wrapper.py index a2c1fad4..99678ffa 100644 --- a/datadog_lambda/wrapper.py +++ b/datadog_lambda/wrapper.py @@ -61,7 +61,7 @@ def _before(self, event, context): set_cold_start() try: - submit_invocations_metric(context.invoked_function_arn) + submit_invocations_metric(context) # Extract Datadog trace context from incoming requests extract_dd_trace_context(event) @@ -82,7 +82,7 @@ def __call__(self, event, context): try: return self.func(event, context) except Exception: - submit_errors_metric(context.invoked_function_arn) + submit_errors_metric(context) raise finally: self._after(event, context) diff --git a/tests/test_tags.py b/tests/test_tags.py index f3dfc4cf..af4c8882 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -1,9 +1,19 @@ import unittest -from datadog_lambda.tags import parse_lambda_tags_from_arn +try: + from unittest.mock import patch +except ImportError: + from mock import patch + +from datadog_lambda.tags import parse_lambda_tags_from_arn, get_runtime_tag class TestMetricTags(unittest.TestCase): + def setUp(self): + patcher = patch("datadog_lambda.tags.python_version_tuple") + self.mock_python_version_tuple = patcher.start() + self.addCleanup(patcher.stop) + def test_parse_lambda_tags_from_arn(self): self.assertListEqual( parse_lambda_tags_from_arn( @@ -27,3 +37,10 @@ def test_parse_lambda_tags_from_arn(self): ], ) + def test_get_runtime_tag(self): + self.mock_python_version_tuple.return_value = ("2", "7", "10") + self.assertEqual(get_runtime_tag(), "runtime:python2.7") + + self.mock_python_version_tuple.return_value = ("3", "7", "2") + self.assertEqual(get_runtime_tag(), "runtime:python3.7") + diff --git a/tests/test_wrapper.py b/tests/test_wrapper.py index 4be85b5c..bcb69a86 100644 --- a/tests/test_wrapper.py +++ b/tests/test_wrapper.py @@ -33,7 +33,7 @@ def setUp(self): self.addCleanup(patcher.stop) patcher = patch("datadog_lambda.metric.lambda_metric") - self.mock_wrapper_lambda_metric = patcher.start() + self.mock_lambda_metric = patcher.start() self.addCleanup(patcher.stop) patcher = patch("datadog_lambda.wrapper.extract_dd_trace_context") @@ -57,6 +57,11 @@ def setUp(self): self.mock_is_cold_start.return_value = True self.addCleanup(patcher.stop) + patcher = patch("datadog_lambda.tags.python_version_tuple") + self.mock_python_version_tuple = patcher.start() + self.mock_python_version_tuple.return_value = ("2", "7", "10") + self.addCleanup(patcher.stop) + def test_datadog_lambda_wrapper(self): @datadog_lambda_wrapper def lambda_handler(event, context): @@ -116,7 +121,7 @@ def lambda_handler(event, context): lambda_handler(lambda_event, get_mock_context()) - self.mock_wrapper_lambda_metric.assert_has_calls( + self.mock_lambda_metric.assert_has_calls( [ call( "aws.lambda.enhanced.invocations", @@ -126,6 +131,8 @@ def lambda_handler(event, context): "account_id:123457598159", "functionname:python-layer-test", "cold_start:true", + "memorysize:256", + "runtime:python2.7", ], ) ] @@ -145,7 +152,7 @@ def lambda_handler(event, context): with self.assertRaises(RuntimeError): lambda_handler(lambda_event, get_mock_context()) - self.mock_wrapper_lambda_metric.assert_has_calls( + self.mock_lambda_metric.assert_has_calls( [ call( "aws.lambda.enhanced.invocations", @@ -155,6 +162,8 @@ def lambda_handler(event, context): "account_id:123457598159", "functionname:python-layer-test", "cold_start:true", + "memorysize:256", + "runtime:python2.7", ], ), call( @@ -165,6 +174,8 @@ def lambda_handler(event, context): "account_id:123457598159", "functionname:python-layer-test", "cold_start:true", + "memorysize:256", + "runtime:python2.7", ], ), ] @@ -189,7 +200,7 @@ def lambda_handler(event, context): lambda_event, get_mock_context(aws_request_id="second-request-id") ) - self.mock_wrapper_lambda_metric.assert_has_calls( + self.mock_lambda_metric.assert_has_calls( [ call( "aws.lambda.enhanced.invocations", @@ -199,6 +210,8 @@ def lambda_handler(event, context): "account_id:123457598159", "functionname:python-layer-test", "cold_start:true", + "memorysize:256", + "runtime:python2.7", ], ), call( @@ -209,6 +222,8 @@ def lambda_handler(event, context): "account_id:123457598159", "functionname:python-layer-test", "cold_start:false", + "memorysize:256", + "runtime:python2.7", ], ), ] @@ -226,5 +241,5 @@ def lambda_handler(event, context): with self.assertRaises(RuntimeError): lambda_handler(lambda_event, get_mock_context()) - self.mock_wrapper_lambda_metric.assert_not_called() + self.mock_lambda_metric.assert_not_called()