diff --git a/samcli/lib/telemetry/metric.py b/samcli/lib/telemetry/metric.py index 8fc803fba1..006bb75323 100644 --- a/samcli/lib/telemetry/metric.py +++ b/samcli/lib/telemetry/metric.py @@ -17,6 +17,7 @@ from samcli.lib.warnings.sam_cli_warning import TemplateWarningsChecker from samcli.commands.exceptions import UserException from samcli.lib.telemetry.cicd import CICDDetector, CICDPlatform +from samcli.lib.telemetry.event import EventTracker from samcli.lib.telemetry.project_metadata import get_git_remote_origin_url, get_project_name, get_initial_commit_hash from samcli.commands._utils.experimental import get_all_experimental_statues from .telemetry import Telemetry @@ -158,6 +159,9 @@ def wrapped(*args, **kwargs): metric_specific_attributes["gitOrigin"] = get_git_remote_origin_url() metric_specific_attributes["projectName"] = get_project_name() metric_specific_attributes["initialCommit"] = get_initial_commit_hash() + # Event metrics + metric_specific_attributes["events"] = [e.to_json() for e in EventTracker.get_tracked_events()] + EventTracker.clear_trackers() metric.add_data("metricSpecificAttributes", metric_specific_attributes) # Metric about command's execution characteristics metric.add_data("duration", duration_fn()) diff --git a/tests/integration/telemetry/test_experimental_metric.py b/tests/integration/telemetry/test_experimental_metric.py index 2bcd93e340..98bd45649a 100644 --- a/tests/integration/telemetry/test_experimental_metric.py +++ b/tests/integration/telemetry/test_experimental_metric.py @@ -59,6 +59,7 @@ def test_must_send_experimental_metrics_if_experimental_command(self): "gitOrigin": ANY, "projectName": ANY, "initialCommit": ANY, + "events": ANY, }, "duration": ANY, "exitReason": ANY, @@ -113,6 +114,7 @@ def test_must_send_experimental_metrics_if_experimental_option(self): "gitOrigin": ANY, "projectName": ANY, "initialCommit": ANY, + "events": ANY, }, "duration": ANY, "exitReason": ANY, @@ -175,6 +177,7 @@ def test_must_send_cdk_project_type_metrics(self): "gitOrigin": ANY, "projectName": ANY, "initialCommit": ANY, + "events": ANY, }, "duration": ANY, "exitReason": ANY, diff --git a/tests/unit/lib/telemetry/test_metric.py b/tests/unit/lib/telemetry/test_metric.py index e4b59fd6ec..7d14233059 100644 --- a/tests/unit/lib/telemetry/test_metric.py +++ b/tests/unit/lib/telemetry/test_metric.py @@ -9,6 +9,7 @@ from unittest import TestCase from unittest.mock import patch, Mock, ANY, call +from samcli.lib.telemetry.event import Event, EventTracker import samcli.lib.telemetry.metric from samcli.lib.telemetry.cicd import CICDPlatform @@ -339,6 +340,49 @@ def real_fn(a, b=None): "The command metrics be emitted when used as a decorator", ) + @parameterized.expand( + [ + ([],), + ([Mock(event_name=Mock(value="TestEvent"), event_value="TestValue")],), + ( + [ + Mock(event_name=Mock(value="Test1"), event_value="TestValue1"), + Mock(event_name=Mock(value="Test2"), event_value="TestValue2"), + ], + ), + ( + [ + Mock(event_name=Mock(value="T1"), event_value="1"), + Mock(event_name=Mock(value="T2"), event_value="2"), + Mock(event_name=Mock(value="T3"), event_value="3"), + ], + ), + ] + ) + @patch("samcli.lib.telemetry.metric.Context") + @patch("samcli.lib.telemetry.event.EventTracker.clear_trackers", side_effect=EventTracker.clear_trackers) + def test_must_return_list_of_events(self, events, clr_mock, ContextMock): + ContextMock.get_current_context.return_value = self.context_mock + clr_mock.clear_trackers.return_value = EventTracker.clear_trackers() + for e in events: + e.to_json.return_value = Event.to_json(e) + + def func_with_event(): + for e in events: + EventTracker._events.append(e) + + expected = [e.to_json() for e in events] + + track_command(func_with_event)() + + args, _ = self.telemetry_instance.emit.call_args_list[0] + metric = args[0] + assert metric.get_metric_name() == "commandRun" + metric_events = metric.get_data()["metricSpecificAttributes"]["events"] + clr_mock.assert_called() + self.assertEqual(len(events), len(metric_events)) + self.assertEqual(metric_events, expected) + class TestParameterCapture(TestCase): def setUp(self):