From 12f0c81c7216455eed8d1413e9e2e9698d4f2a9f Mon Sep 17 00:00:00 2001 From: Cristhian Garcia Date: Thu, 26 Oct 2023 15:32:01 -0500 Subject: [PATCH] fix: only generate metadata fix: assert for subset ignoring runtime generated only metadata chore: quality fixes chore: improve docstring fix: convert timestamp str to datetime object test: add test for str datetime fix: rename tracking log event emitted fix: rename tracking log event emitted config fix: rename tracking event chore: handle comments --- eventtracking/backends/event_bus.py | 40 +++++------- eventtracking/backends/routing.py | 4 +- .../backends/tests/test_event_bus.py | 65 ++++++++++++------- eventtracking/config.py | 11 +++- 4 files changed, 68 insertions(+), 52 deletions(-) diff --git a/eventtracking/backends/event_bus.py b/eventtracking/backends/event_bus.py index baba6e29..d20a158e 100644 --- a/eventtracking/backends/event_bus.py +++ b/eventtracking/backends/event_bus.py @@ -1,29 +1,27 @@ """Event tracker backend that emits events to the event-bus.""" import json +import logging +from datetime import datetime from openedx_events.analytics.data import TrackingLogData from openedx_events.analytics.signals import TRACKING_EVENT_EMITTED +from openedx_events.event_bus import get_producer from eventtracking.backends.routing import RoutingBackend from eventtracking.config import SEND_TRACKING_EVENT_EMITTED_SIGNAL -from openedx_events.data import EventsMetadata -from openedx_events.event_bus import get_producer -from attrs import asdict -import logging logger = logging.getLogger(__name__) -EVENT_BUS_SOURCE = "openedx/eventtracking" class EventBusRoutingBackend(RoutingBackend): """ - Event tracker backend that emits an Open edX public signal. + Event tracker backend for the event bus. """ def send(self, event): """ - Emit the TRACKING_EVENT_EMITTED Open edX public signal to allow - other apps to listen for tracking events. + Send the tracking log event to the event bus by emitting the + TRACKING_EVENT_EMITTED signal using custom metadata. """ if not SEND_TRACKING_EVENT_EMITTED_SIGNAL.is_enabled(): return @@ -31,29 +29,25 @@ def send(self, event): data = json.dumps(event.get("data")) context = json.dumps(event.get("context")) - tracking_log=TrackingLogData( + timestamp = event.get("timestamp") + + if isinstance(timestamp, str): + timestamp = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f%z") + + tracking_log = TrackingLogData( name=event.get("name"), - timestamp=event.get("timestamp"), + timestamp=timestamp, data=data, context=context, ) - logger.info(f"Sending tracking event emitted signal for event for {tracking_log.name}") + metadata = TRACKING_EVENT_EMITTED.generate_signal_metadata() + + logger.info(f"Emitting tracking log {tracking_log.name} to the event bus.") get_producer().send( signal=TRACKING_EVENT_EMITTED, topic="analytics", event_key_field="tracking_log.name", event_data={"tracking_log": tracking_log}, - event_metadata=generate_signal_metadata() + event_metadata=metadata, ) - - -def generate_signal_metadata(): - """ - Generate the metadata for the signal with a custom source. - """ - metadata = TRACKING_EVENT_EMITTED.generate_signal_metadata() - medata_dict = asdict(metadata) - medata_dict["source"] = EVENT_BUS_SOURCE - metadata = EventsMetadata(**medata_dict) - return metadata diff --git a/eventtracking/backends/routing.py b/eventtracking/backends/routing.py index c8238a91..d59d941e 100644 --- a/eventtracking/backends/routing.py +++ b/eventtracking/backends/routing.py @@ -118,7 +118,7 @@ def process_event(self, event): processed_event = modified_event except EventEmissionExit: raise - except Exception: # pylint: disable=broad-except + except Exception: LOG.exception( 'Failed to execute processor: %s', str(processor) ) @@ -142,7 +142,7 @@ def send_to_backends(self, event): LOG.info('[send_to_backends] Failed to send edx event "%s" to "%s" backend. "%s" backend has' ' not been enabled, [%s]', event["name"], name, name, repr(exc) ) - except Exception: # pylint: disable=broad-except + except Exception: LOG.exception( 'Unable to send edx event "%s" to backend: %s', event["name"], name ) diff --git a/eventtracking/backends/tests/test_event_bus.py b/eventtracking/backends/tests/test_event_bus.py index 2b33b0bf..c16a7abe 100644 --- a/eventtracking/backends/tests/test_event_bus.py +++ b/eventtracking/backends/tests/test_event_bus.py @@ -2,11 +2,16 @@ Test the async routing backend. """ import json - +from datetime import datetime from unittest import TestCase -from unittest.mock import sentinel, patch, Mock -from eventtracking.backends.event_bus import EventBusRoutingBackend +from unittest.mock import Mock, patch, sentinel + +from django.test import override_settings from openedx_events.analytics.data import TrackingLogData +from openedx_events.analytics.signals import TRACKING_EVENT_EMITTED + +from eventtracking.backends.event_bus import EventBusRoutingBackend + class TestAsyncRoutingBackend(TestCase): """ @@ -16,40 +21,52 @@ class TestAsyncRoutingBackend(TestCase): def setUp(self): super().setUp() self.sample_event = { - 'name': str(sentinel.name), - 'data': {'foo': 'bar'}, - 'timestamp': '2020-01-01T12:12:12.000000+00:00', - 'context': {'baz': 'qux'}, + "name": str(sentinel.name), + "data": {"foo": "bar"}, + "timestamp": "2020-01-01T12:12:12.000000+00:00", + "context": {"baz": "qux"}, } - @patch('eventtracking.backends.event_bus.EventBusRoutingBackend.send') + @patch("eventtracking.backends.event_bus.EventBusRoutingBackend.send") def test_successful_send(self, mocked_send_event): backend = EventBusRoutingBackend() backend.send(self.sample_event) mocked_send_event.assert_called_once_with(self.sample_event) - @patch('eventtracking.backends.event_bus.get_producer') + @override_settings(SEND_TRACKING_EVENT_EMITTED_SIGNAL=True) + @patch("eventtracking.backends.event_bus.get_producer") def test_successful_send_event(self, mock_get_producer): - backend = EventBusRoutingBackend() - backend.send(self.sample_event) mock_send = Mock() - mock_get_producer.return_value = Mock(send=mock_send) - mock_get_producer.assert_called() + backend = EventBusRoutingBackend() + backend.send(self.sample_event) + mock_get_producer.assert_called() mock_send.assert_called() - mock_send.assert_called_once_with( - tracking_log=TrackingLogData( - name=self.sample_event['name'], - timestamp=self.sample_event['timestamp'], - data=json.dumps(self.sample_event['data']), - context=json.dumps(self.sample_event['context']), - ) - - - @patch('eventtracking.backends.event_bus.SEND_TRACKING_EVENT_EMITTED_SIGNAL.is_enabled') - @patch('eventtracking.backends.event_bus.get_producer') + self.assertDictContainsSubset( + { + "signal": TRACKING_EVENT_EMITTED, + "topic": "analytics", + "event_key_field": "tracking_log.name", + "event_data": { + "tracking_log": TrackingLogData( + name=self.sample_event["name"], + timestamp=datetime.strptime( + self.sample_event["timestamp"], "%Y-%m-%dT%H:%M:%S.%f%z" + ), + data=json.dumps(self.sample_event["data"]), + context=json.dumps(self.sample_event["context"]), + ) + }, + }, + mock_send.call_args.kwargs, + ) + + @patch( + "eventtracking.backends.event_bus.SEND_TRACKING_EVENT_EMITTED_SIGNAL.is_enabled" + ) + @patch("eventtracking.backends.event_bus.get_producer") def test_event_is_disabled(self, mock_get_producer, mock_is_enabled): mock_is_enabled.return_value = False backend = EventBusRoutingBackend() diff --git a/eventtracking/config.py b/eventtracking/config.py index f316a2f6..48f3743d 100644 --- a/eventtracking/config.py +++ b/eventtracking/config.py @@ -1,6 +1,6 @@ """ This module contains various configuration settings via -waffle switches for the Certificates app. +waffle switches for the event-tracking app. """ from edx_toggles.toggles import SettingToggle @@ -10,5 +10,10 @@ # .. toggle_default: False # .. toggle_description: When True, the system will publish `TRACKING_EVENT_EMITTED` signals to the event bus. The # `TRACKING_EVENT_EMITTED` signal is emit when a tracking log is emitted. -# .. toggle_use_cases: publish -SEND_TRACKING_EVENT_EMITTED_SIGNAL = SettingToggle('SEND_TRACKING_EVENT_EMITTED_SIGNAL', default=True, module_name=__name__) +# .. toggle_use_cases: circuit_breaker +# .. toggle_creation_date: 2023-10-26 +SEND_TRACKING_EVENT_EMITTED_SIGNAL = SettingToggle( + 'SEND_TRACKING_EVENT_EMITTED_SIGNAL', + default=False, + module_name=__name__ +)