diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index b2fcc73ca3..2b940fe982 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -39,6 +39,8 @@ from collections import namedtuple from courseware.courses import get_courses_by_university from courseware.access import has_access +from statsd import statsd + log = logging.getLogger("mitx.student") Article = namedtuple('Article', 'title url author image deck publication publish_date') @@ -204,7 +206,13 @@ def change_enrollment(request): return {'success': False, 'error': 'enrollment in {} not allowed at this time' .format(course.display_name)} - + + org, course_num, run=course_id.split("/") + statsd.increment("common.student.enrollment", + tags=["org:{0}".format(org), + "course:{0}".format(course_num), + "run:{0}".format(run)]) + enrollment, created = CourseEnrollment.objects.get_or_create(user=user, course_id=course.id) return {'success': True} @@ -212,6 +220,13 @@ def change_enrollment(request): try: enrollment = CourseEnrollment.objects.get(user=user, course_id=course_id) enrollment.delete() + + org, course_num, run=course_id.split("/") + statsd.increment("common.student.unenrollment", + tags=["org:{0}".format(org), + "course:{0}".format(course_num), + "run:{0}".format(run)]) + return {'success': True} except CourseEnrollment.DoesNotExist: return {'success': False, 'error': 'You are not enrolled for this course.'} @@ -260,7 +275,9 @@ def login_user(request, error=""): log.info("Login success - {0} ({1})".format(username, email)) try_change_enrollment(request) - + + statsd.increment("common.student.successful_login") + return HttpResponse(json.dumps({'success': True})) log.warning("Login failed - Account not active for user {0}, resending activation".format(username)) @@ -466,7 +483,9 @@ def create_account(request, post_override=None): log.debug('bypassing activation email') login_user.is_active = True login_user.save() - + + statsd.increment("common.student.account_created") + js = {'success': True} return HttpResponse(json.dumps(js), mimetype="application/json") diff --git a/common/lib/capa/capa/correctmap.py b/common/lib/capa/capa/correctmap.py index 227f85bc8e..3c4f43a1d6 100644 --- a/common/lib/capa/capa/correctmap.py +++ b/common/lib/capa/capa/correctmap.py @@ -3,7 +3,6 @@ # # Used by responsetypes and capa_problem - class CorrectMap(object): """ Stores map between answer_id and response evaluation result for each question diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 1e45822ebf..e0b0c3aaec 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -28,6 +28,8 @@ from xmodule.x_module import ModuleSystem from xmodule.error_module import ErrorDescriptor, NonStaffErrorDescriptor from xmodule_modifiers import replace_course_urls, replace_static_urls, add_histogram, wrap_xmodule +from statsd import statsd + log = logging.getLogger("mitx.courseware") @@ -382,6 +384,15 @@ def xqueue_callback(request, course_id, userid, id, dispatch): if instance_module.grade != oldgrade or instance_module.state != old_instance_state: instance_module.save() + #Bin score into range and increment stats + score_bucket=get_score_bucket(instance_module.grade, instance_module.max_grade) + org, course_num, run=course_id.split("/") + statsd.increment("lms.courseware.question_answered", + tags=["org:{0}".format(org), + "course:{0}".format(course_num), + "run:{0}".format(run), + "score_bucket:{0}".format(score_bucket), + "type:xqueue"]) return HttpResponse("") @@ -466,6 +477,17 @@ def modx_dispatch(request, dispatch, location, course_id): instance_module.max_grade != old_instance_max_grade): instance_module.save() + #Bin score into range and increment stats + score_bucket=get_score_bucket(instance_module.grade, instance_module.max_grade) + org, course_num, run=course_id.split("/") + statsd.increment("lms.courseware.question_answered", + tags=["org:{0}".format(org), + "course:{0}".format(course_num), + "run:{0}".format(run), + "score_bucket:{0}".format(score_bucket), + "type:ajax"]) + + if shared_module is not None: shared_module.state = instance.get_shared_state() if shared_module.state != old_shared_state: @@ -511,4 +533,17 @@ def preview_chemcalc(request): return HttpResponse(json.dumps(result)) +def get_score_bucket(grade,max_grade): + """ + Function to split arbitrary score ranges into 3 buckets. + Used with statsd tracking. + """ + score_bucket="incorrect" + if(grade>0 and grade