Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tracking logs #206

Merged
merged 13 commits into from
Jun 20, 2024
6 changes: 3 additions & 3 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ Change Log
Unreleased
~~~~~~~~~~

[4.0.4] - 2024-06-13
[4.1.0] - 2024-06-18
~~~~~~~~~~~~~~~~~~~~

* Emit tracking log events for `openedx.completion_aggregator.progress.*` and
`openedx.completion_aggregator.completion.*` for the various block/course types
* Emit `openedx.completion_aggregator.progress.*` tracking log events for the
various block/course types

[4.0.3] - 2023-10-24
~~~~~~~~~~~~~~~~~~~~
Expand Down
9 changes: 9 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ API Details

For details about how the completion aggregator's REST APIs can be used, please refer to `the docstrings in views.py <https://github.com/open-craft/openedx-completion-aggregator/blob/master/completion_aggregator/api/v1/views.py#L24>`_.

Event tracking
--------------

Like other parts of Open edX, the completion aggregator emits "tracking logs" events whenever completion aggregator records are created or updated by this plugin. These events can be used for analytics, for example to track learner progress in a course.

Event tracking is enabled by default for edx-platform, and so event tracking is also enabled by default in the completion aggregator. This can result in a lot of events being generated -- for example when a user completes the final block in a course, aggregator completion events will be generated for the containing unit, subsection, section, and course.
pomegranited marked this conversation as resolved.
Show resolved Hide resolved

You can limit which aggregator events are emitted by modifying the `COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES` setting to limit which block types (`course`, `chapter`, `sequential`, `vertical`) cause tracking events to be emitted. To disable sending any completion aggregator tracking events, set `COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES = None`.
pomegranited marked this conversation as resolved.
Show resolved Hide resolved

Installation and Configuration
------------------------------

Expand Down
2 changes: 1 addition & 1 deletion completion_aggregator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

from __future__ import absolute_import, unicode_literals

__version__ = '4.0.4'
__version__ = '4.1.0'
14 changes: 8 additions & 6 deletions completion_aggregator/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,19 @@ def emit_completion_aggregator_logs(updated_aggregators):

Parameters
----------
updated_aggregators: List of Aggregator intances
updated_aggregators: List of Aggregator instances

"""
if not settings.COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES:
return

for aggregator in updated_aggregators:
Agrendalath marked this conversation as resolved.
Show resolved Hide resolved
event = "progress" if aggregator.percent < 1 else "completion"
event_type = aggregator.aggregation_name
block_type = aggregator.aggregation_name

if event_type not in settings.ALLOWED_COMPLETION_AGGREGATOR_EVENT_TYPES.get(event, {}):
if block_type not in settings.COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES:
continue

event_name = f"openedx.completion_aggregator.{event}.{event_type}"
event_name = f"openedx.completion_aggregator.progress.{block_type}"

tracker.emit(
event_name,
Expand All @@ -206,7 +208,7 @@ def emit_completion_aggregator_logs(updated_aggregators):
"earned": aggregator.earned,
"possible": aggregator.possible,
"percent": aggregator.percent,
"type": event_type,
"type": block_type,
}
)

Expand Down
5 changes: 5 additions & 0 deletions completion_aggregator/settings/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ def plugin_settings(settings):
"""
Modify the provided settings object with settings specific to this plugin.
"""
settings.COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES = settings.ENV_TOKENS.get(
'COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES',
settings.COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES,
)

settings.COMPLETION_AGGREGATOR_BLOCK_TYPES = set(settings.ENV_TOKENS.get(
'COMPLETION_AGGREGATOR_BLOCK_TYPES',
settings.COMPLETION_AGGREGATOR_BLOCK_TYPES,
Expand Down
24 changes: 7 additions & 17 deletions completion_aggregator/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,19 @@ def plugin_settings(settings):
"""
Modify the provided settings object with settings specific to this plugin.
"""
# Emit feature allows to publish two kind of events progress and completion
# This setting controls which type of event will be published to change the default behavior
# the block type should be removed or added from the progress or completion list.
settings.ALLOWED_COMPLETION_AGGREGATOR_EVENT_TYPES = {
"progress": {
"course",
"chapter",
"sequential",
"vertical",
},
"completion": {
"course",
"chapter",
"sequential",
"vertical",
}
}
settings.COMPLETION_AGGREGATOR_BLOCK_TYPES = {
'course',
'chapter',
'sequential',
'vertical',
}

# Emit feature publishes progress events to track aggregated completion.
# Defaults to the full set of block types subject to completion aggregation.
# Block types may be removed from this list to limit the tracking log events emitted.
settings.COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES = settings.COMPLETION_AGGREGATOR_BLOCK_TYPES
pomegranited marked this conversation as resolved.
Show resolved Hide resolved

# Synchronous completion aggregation is enabled by default
settings.COMPLETION_AGGREGATOR_ASYNC_AGGREGATION = False

# Names of the batch operations locks
Expand Down
2 changes: 1 addition & 1 deletion requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ django-model-utils # Provides TimeStampedModel abstract base class
edx-opaque-keys # Provides CourseKey and UsageKey
edx-completion
edx-toggles
event-tracking
event-tracking # Allows the aggregator to emit tracking events
six
XBlock[django]
18 changes: 3 additions & 15 deletions test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,11 @@ def root(*args):
return join(abspath(dirname(__file__)), *args)


ALLOWED_COMPLETION_AGGREGATOR_EVENT_TYPES = {
"progress": [
"course",
"chapter",
"sequential",
"vertical",
],
"completion": [
"course",
"chapter",
"sequential",
"vertical",
]
}
AUTH_USER_MODEL = 'auth.User'
CELERY_ALWAYS_EAGER = True
COMPLETION_AGGREGATOR_BLOCK_TYPES = {'course', 'chapter', 'sequential'}
COMPLETION_AGGREGATOR_ASYNC_AGGREGATION = False
COMPLETION_AGGREGATOR_BLOCK_TYPES = {'course', 'chapter', 'sequential', 'vertical'}
COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES = COMPLETION_AGGREGATOR_BLOCK_TYPES
COMPLETION_AGGREGATOR_AGGREGATION_LOCK = 'COMPLETION_AGGREGATOR_AGGREGATION_LOCK'
COMPLETION_AGGREGATOR_CLEANUP_LOCK = 'COMPLETION_AGGREGATOR_CLEANUP_LOCK'
COMPLETION_AGGREGATOR_AGGREGATION_LOCK_TIMEOUT_SECONDS = 1800
Expand Down Expand Up @@ -96,6 +83,7 @@ def root(*args):
]
USE_TZ = True

# Enables event tracking in the tests, see https://github.com/openedx/event-tracking
EVENT_TRACKING_ENABLED = True
Agrendalath marked this conversation as resolved.
Show resolved Hide resolved

# pylint: disable=unused-import,wrong-import-position
Expand Down
23 changes: 17 additions & 6 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.test import TestCase, override_settings
from django.utils.timezone import now

from completion_aggregator.models import Aggregator
Expand Down Expand Up @@ -228,15 +228,26 @@ def test_get_values(self, block_key_obj, aggregate_name, earned, possible, expec
self.assertEqual(values['user'], self.user.id)
self.assertEqual(values['percent'], expected_percent)

@override_settings(COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES=None)
def test_submit_completion_with_tracking_disabled(self):
_obj, is_new = Aggregator.objects.submit_completion(
user=self.user,
course_key=self.BLOCK_KEY_OBJ.course_key,
block_key=self.BLOCK_KEY_OBJ,
aggregation_name='course',
earned=0.5,
possible=1,
last_modified=now(),
)
self.assertTrue(is_new)
self.assertEqual(len(Aggregator.objects.all()), 1)
self.tracker_mock.emit.assert_not_called()

def assert_emit_method_called(self, obj):
"""Verify that the tracker.emit method was called once with the right values."""
if obj.aggregation_name not in settings.ALLOWED_COMPLETION_AGGREGATOR_EVENT_TYPES:
return

event = "progress" if obj.percent < 1 else "completion"

self.tracker_mock.emit.assert_called_once_with(
f"openedx.completion_aggregator.{event}.{obj.aggregation_name}",
f"openedx.completion_aggregator.progress.{obj.aggregation_name}",
{
"user_id": obj.user_id,
"course_id": str(obj.course_key),
Expand Down
17 changes: 17 additions & 0 deletions tests/test_plugin_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""
Test the aggregator plugin settings.
"""
from django.conf import settings
from django.test import override_settings

from completion_aggregator.settings import aws as aws_settings


@override_settings(ENV_TOKENS={})
def test_production_settings():
"""
Test that the completion aggregator production settings behave as expected
"""
aws_settings.plugin_settings(settings)

assert settings.COMPLETION_AGGREGATOR_TRACKING_EVENT_TYPES == settings.COMPLETION_AGGREGATOR_BLOCK_TYPES
Loading