Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion common/djangoapps/student/management/commands/create_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
from student.views import _do_create_account
from django.contrib.auth.models import User

from track.management.tracked_command import TrackedCommand

class Command(BaseCommand):

class Command(TrackedCommand):
help = """
This command creates and registers a user in a given course
as "audit", "verified" or "honor".
Expand Down
Empty file.
29 changes: 29 additions & 0 deletions common/djangoapps/track/management/tests/test_tracked_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import json
from StringIO import StringIO
from django.test import TestCase

from eventtracking import tracker as eventtracker

from track.management.tracked_command import TrackedCommand


class DummyCommand(TrackedCommand):
"""A locally-defined command, for testing, that returns the current context as a JSON string."""
def handle(self, *args, **options):
return json.dumps(eventtracker.get_tracker().resolve_context())


class CommandsTestBase(TestCase):

def _run_dummy_command(self, *args, **kwargs):
"""Runs the test command's execute method directly, and outputs a dict of the current context."""
out = StringIO()
DummyCommand().execute(*args, stdout=out, **kwargs)
out.seek(0)
return json.loads(out.read())

def test_command(self):
args = ['whee']
kwargs = {'key1': 'default', 'key2': True}
json_out = self._run_dummy_command(*args, **kwargs)
self.assertEquals(json_out['command'], 'unknown')
59 changes: 59 additions & 0 deletions common/djangoapps/track/management/tracked_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Provides management command calling info to tracking context."""

from django.core.management.base import BaseCommand

from eventtracking import tracker


class TrackedCommand(BaseCommand):
"""
Provides management command calling info to tracking context.

Information provided to context includes the following value:

'command': the program name and the subcommand used to run a management command.

In future, other values (such as args and options) could be added as needed.

An example tracking log entry resulting from running the 'create_user' management command:

{
"username": "anonymous",
"host": "",
"event_source": "server",
"event_type": "edx.course.enrollment.activated",
"context": {
"course_id": "edX/Open_DemoX/edx_demo_course",
"org_id": "edX",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave these two entries (course_id, org_id) out until they are actually being added by the create_user command

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are added by the enrollment call itself. Only "command" is now being added by the TrackedCommand class.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, I suppose they would be. Awesome.

"command": "./manage.py create_user",
},
"time": "2014-01-06T15:59:49.599522+00:00",
"ip": "",
"event": {
"course_id": "edX/Open_DemoX/edx_demo_course",
"user_id": 29,
"mode": "verified"
},
"agent": "",
"page": null
}

The name of the context used to add (and remove) these values is "edx.mgmt.command".
The context name is used to allow the context additions to be scoped, but doesn't
appear in the context itself.
"""
prog_name = 'unknown'

def create_parser(self, prog_name, subcommand):
"""Wraps create_parser to snag command line info."""
self.prog_name = "{} {}".format(prog_name, subcommand)
return super(TrackedCommand, self).create_parser(prog_name, subcommand)

def execute(self, *args, **options):
"""Wraps base execute() to add command line to tracking context."""
context = {
'command': self.prog_name,
}
COMMAND_CONTEXT_NAME = 'edx.mgmt.command'
with tracker.get_tracker().context(COMMAND_CONTEXT_NAME, context):
super(TrackedCommand, self).execute(*args, **options)