Package: event-tracking
Part ofedX code.Event Tracking libraryTheevent-trackinglibrary tracks context-aware semi-structured system events.
It captures and stores events with nested data structures in order to truly
take advantage of schemaless data storage systems.Key features:Multiple backends - define custom backends that can be used to persist
your event data.Nested contexts - allows data to be injected into events even without
having to pass around all of said data to every location where the events
are emitted.Django integration - provides a Django app that allows context aware events
to easily be captured by multi-threaded web applications.MongoDB integration - support writing events out to a mongo collection.Example:from eventtracking import tracker

tracker = tracker.get_tracker()
tracker.enter_context('outer', {'user_id': 10938})
tracker.emit('navigation.request', {'url': 'http://www.edx.org/some/path/1'})

with tracker.context({'user_id': 11111, 'session_id': '2987lkjdyoioey'}):
    tracker.emit('navigation.request', {'url': 'http://www.edx.org/some/path/2'})

tracker.emit(
    'address.create',
    {
        'name': 'foo',
        'address': {
            'postal_code': '90210',
            'country': 'United States'
        }
    }
)Running the above example produces the following events:{
    "name": "navigation.request",
    "timestamp": ...,
    "context": {
        "user_id": 10938
    },
    "data": {
        "url": "http://www.edx.org/some/path/1"
    }
},
{
    "name": "navigation.request",
    "timestamp": ...,
    "context": {
        "user_id": 11111,
        "session_id": "2987lkjdyoioey"
    },
    "data": {
        "url": "http://www.edx.org/some/path/2"
    }
},
{
    "name": "address.create",
    "timestamp": ...,
    "context": {
        "user_id": 10938
    },
    "data": {
        "name": "foo",
        "address": {
            "postal_code": "90210",
            "country": "United States"
        }
    }
}ConfigurationConfiguration forevent-trackingtakes the form of a tree of backends. When aTrackeris instantiated, it creates a rootRoutingBackendobject using the top-level backends and processors that are passed to it. (Or in the case of theDjangoTracker, the backends and processors are constructed according to the appropriate Django settings.)In thisRoutingBackend, each event is first passed through the chain of processors in series, and then distributed to each backend in turn. Theoretically, these backends might be the Mongo, Segment, or logger backends, but in practice these are wrapped by another layer ofRoutingBackend. This allows each one to have its own set of processors that are not shared with other backends, allowing independent filtering or event emit cancellation.Asynchronous RoutingConsidering the volume of the events being generated, we would want to avoid
processing events in the main thread that could cause delays in response
depending upon the operations and event processors.event-trackingprovides a solution for this i.e.AsyncRoutingBackend.
It extendsRoutingBackendbut performs its operations asynchronously.It can:Process event through the configured processors.If the event is processed successfully, pass it to the configured backends.Handling the operations asynchronously would avoid overburdening the main thread
and pass the intensive processing tasks to celery workers.Limitations: Although backends forRoutingBackendcan be configured
at any level ofEVENT_TRACKING_BACKENDSconfiguration tree,AsyncRoutingBackendonly supports backends defined at the root level ofEVENT_TRACKING_BACKENDSsetting.  It is also only possible to use it
successfully from the default tracker.An example configuration forAsyncRoutingBackendis provided below:EVENT_TRACKING_BACKENDS = {
    'caliper': {
        'ENGINE':  'eventtracking.backends.async_routing.AsyncRoutingBackend',
        'OPTIONS': {
            'backend_name': 'caliper',
            'processors': [
                {
                    'ENGINE': 'eventtracking.processors.regex_filter.RegexFilter',
                    'OPTIONS':{
                        'filter_type': 'allowlist',
                        'regular_expressions': [
                            'edx.course.enrollment.activated',
                            'edx.course.enrollment.deactivated',
                        ]
                    }
                }
            ],
            'backends': {
                'caliper': {
                    'ENGINE': 'dummy.backend.engine',
                    'OPTIONS': {
                        ...
                    }
                }
            },
        },
    },
    'tracking_logs': {
        ...
    }
    ...
}Event Bus Routingevent-trackingprovides a solution for routing events to the Event Bus
using theEventBusBackend. It extendsRoutingBackendbut sends events
to the Event Bus.It can:Process event through the configured processors.If the event is allowed viaEVENT_BUS_TRACKING_LOGS, send it to the Event Bus.Make sure to enable the setting:SEND_TRACKING_EVENT_EMITTED_SIGNALto allow theEventBusBackendto send events to the Event Bus.An example configuration forEventBusBackendis provided below:EVENT_TRACKING_BACKENDS = {
    'xapi': {
        'ENGINE':  'eventtracking.backends.event_bus.EventBusBackend',
        'OPTIONS': {
            'backend_name': 'xapi',
            'processors': [
                {
                    'ENGINE': 'eventtracking.processors.regex_filter.RegexFilter',
                    'OPTIONS':{
                        'filter_type': 'allowlist',
                        'regular_expressions': [
                            'edx.course.enrollment.activated',
                            'edx.course.enrollment.deactivated',
                        ]
                    }
                }
            ],
            'backends': {
                'xapi': {
                    'ENGINE': 'dummy.backend.engine',
                    'OPTIONS': {
                        ...
                    }
                }
            },
        },
    },
    'tracking_logs': {
        ...
    }
    ...
}

EVENT_BUS_TRACKING_LOGS = [
    'edx.course.enrollment.activated',
    'edx.course.enrollment.deactivated',
]RoadmapIn the very near future the following features are planned:Dynamic event documentation and event metadata - allow event emitters to
document the event types, and persist this documentation along with the
events so that it can be referenced during analysis to provide context
about what the event is and when it is emitted.DocumentationLatest documentation(Hosted on Read the Docs)LicenseThe code in this repository is licensed under version 3 of the AGPL unless
otherwise noted.Please seeLICENSE.txtfor details.How to ContributeContributions are very welcome.Please readHow To Contributefor details.Reporting Security IssuesPlease do not report security issues in public. Please emailsecurity@openedx.orgMailing List and IRC ChannelYou can discuss this code on theedx-code Google Groupor in theedx-codeIRC channel on Freenode.