예제 #1
0
def subsection_grade_calculated(subsection_grade):
    """
    Emits an edx.grades.subsection.grade_calculated event
    with data from the passed subsection_grade.
    """
    event_name = SUBSECTION_GRADE_CALCULATED
    context = contexts.course_context_from_course_id(subsection_grade.course_id)
    # TODO (AN-6134): remove this context manager
    with tracker.get_tracker().context(event_name, context):
        tracker.emit(
            event_name,
            {
                'user_id': unicode(subsection_grade.user_id),
                'course_id': unicode(subsection_grade.course_id),
                'block_id': unicode(subsection_grade.usage_key),
                'course_version': unicode(subsection_grade.course_version),
                'weighted_total_earned': subsection_grade.earned_all,
                'weighted_total_possible': subsection_grade.possible_all,
                'weighted_graded_earned': subsection_grade.earned_graded,
                'weighted_graded_possible': subsection_grade.possible_graded,
                'first_attempted': unicode(subsection_grade.first_attempted),
                'subtree_edited_timestamp': unicode(subsection_grade.subtree_edited_timestamp),
                'event_transaction_id': unicode(get_event_transaction_id()),
                'event_transaction_type': unicode(get_event_transaction_type()),
                'visible_blocks_hash': unicode(subsection_grade.visible_blocks_id),
            }
        )
예제 #2
0
파일: models.py 프로젝트: eliesmr4/myedx
 def _emit_grade_calculated_event(grade):
     """
     Emits an edx.grades.subsection.grade_calculated event
     with data from the passed grade.
     """
     # TODO: remove this context manager after completion of AN-6134
     event_name = u'edx.grades.subsection.grade_calculated'
     context = contexts.course_context_from_course_id(grade.course_id)
     with tracker.get_tracker().context(event_name, context):
         tracker.emit(
             event_name,
             {
                 'user_id': unicode(grade.user_id),
                 'course_id': unicode(grade.course_id),
                 'block_id': unicode(grade.usage_key),
                 'course_version': unicode(grade.course_version),
                 'weighted_total_earned': grade.earned_all,
                 'weighted_total_possible': grade.possible_all,
                 'weighted_graded_earned': grade.earned_graded,
                 'weighted_graded_possible': grade.possible_graded,
                 'first_attempted': unicode(grade.first_attempted),
                 'subtree_edited_timestamp': unicode(grade.subtree_edited_timestamp),
                 'event_transaction_id': unicode(get_event_transaction_id()),
                 'event_transaction_type': unicode(get_event_transaction_type()),
                 'visible_blocks_hash': unicode(grade.visible_blocks_id),
             }
         )
예제 #3
0
def subsection_grade_calculated(subsection_grade):
    """
    Emits an edx.grades.subsection.grade_calculated event
    with data from the passed subsection_grade.
    """
    event_name = SUBSECTION_GRADE_CALCULATED
    context = contexts.course_context_from_course_id(subsection_grade.course_id)
    # TODO (AN-6134): remove this context manager
    with tracker.get_tracker().context(event_name, context):
        tracker.emit(
            event_name,
            {
                'user_id': six.text_type(subsection_grade.user_id),
                'course_id': six.text_type(subsection_grade.course_id),
                'block_id': six.text_type(subsection_grade.usage_key),
                'course_version': six.text_type(subsection_grade.course_version),
                'weighted_total_earned': subsection_grade.earned_all,
                'weighted_total_possible': subsection_grade.possible_all,
                'weighted_graded_earned': subsection_grade.earned_graded,
                'weighted_graded_possible': subsection_grade.possible_graded,
                'first_attempted': six.text_type(subsection_grade.first_attempted),
                'subtree_edited_timestamp': six.text_type(subsection_grade.subtree_edited_timestamp),
                'event_transaction_id': six.text_type(get_event_transaction_id()),
                'event_transaction_type': six.text_type(get_event_transaction_type()),
                'visible_blocks_hash': six.text_type(subsection_grade.visible_blocks_id),
            }
        )
예제 #4
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            assert (isinstance(self.course_id, CourseKey))
            data = {
                'user_id': self.user.id,
                'course_id': self.course_id.to_deprecated_string(),
                'mode': self.mode,
            }

            with tracker.get_tracker().context(event_name, context):
                tracker.emit(event_name, data)

                if settings.FEATURES.get(
                        'SEGMENT_IO_LMS') and settings.SEGMENT_IO_LMS_KEY:
                    analytics.track(
                        self.user_id, event_name, {
                            'category': 'conversion',
                            'label': self.course_id.to_deprecated_string(),
                            'org': self.course_id.org,
                            'course': self.course_id.course,
                            'run': self.course_id.run,
                            'mode': self.mode,
                        })
        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception(
                    'Unable to emit event %s for user %s and course %s',
                    event_name, self.user.username, self.course_id)
예제 #5
0
 def _emit_grade_calculated_event(grade):
     """
     Emits an edx.grades.subsection.grade_calculated event
     with data from the passed grade.
     """
     # TODO: remove this context manager after completion of AN-6134
     event_name = u'edx.grades.subsection.grade_calculated'
     context = contexts.course_context_from_course_id(grade.course_id)
     with tracker.get_tracker().context(event_name, context):
         tracker.emit(
             event_name,
             {
                 'user_id': unicode(grade.user_id),
                 'course_id': unicode(grade.course_id),
                 'block_id': unicode(grade.usage_key),
                 'course_version': unicode(grade.course_version),
                 'weighted_total_earned': grade.earned_all,
                 'weighted_total_possible': grade.possible_all,
                 'weighted_graded_earned': grade.earned_graded,
                 'weighted_graded_possible': grade.possible_graded,
                 'first_attempted': unicode(grade.first_attempted),
                 'subtree_edited_timestamp': unicode(grade.subtree_edited_timestamp),
                 'event_transaction_id': unicode(get_event_transaction_id()),
                 'event_transaction_type': unicode(get_event_transaction_type()),
                 'visible_blocks_hash': unicode(grade.visible_blocks_id),
             }
         )
예제 #6
0
 def publish(block, event_type, event):
     """A function that allows XModules to publish events."""
     if event_type == 'grade' and not is_masquerading_as_specific_student(
             user, course_id):
         SCORE_PUBLISHED.send(
             sender=None,
             block=block,
             user=user,
             raw_earned=event['value'],
             raw_possible=event['max_value'],
             only_if_higher=event.get('only_if_higher'),
         )
     else:
         context = contexts.course_context_from_course_id(course_id)
         if block.runtime.user_id:
             context['user_id'] = block.runtime.user_id
         context['asides'] = {}
         for aside in block.runtime.get_asides(block):
             if hasattr(aside, 'get_event_context'):
                 aside_event_info = aside.get_event_context(
                     event_type, event)
                 if aside_event_info is not None:
                     context['asides'][
                         aside.scope_ids.block_type] = aside_event_info
         with tracker.get_tracker().context(event_type, context):
             track_function(event_type, event)
예제 #7
0
 def _emit_grade_calculated_event(grade):
     """
     Emits an edx.grades.course.grade_calculated event
     with data from the passed grade.
     """
     # TODO: remove this context manager after completion of AN-6134
     event_name = u'edx.grades.course.grade_calculated'
     context = contexts.course_context_from_course_id(grade.course_id)
     with tracker.get_tracker().context(event_name, context):
         tracker.emit(
             event_name, {
                 'user_id':
                 unicode(grade.user_id),
                 'course_id':
                 unicode(grade.course_id),
                 'course_version':
                 unicode(grade.course_version),
                 'percent_grade':
                 grade.percent_grade,
                 'letter_grade':
                 unicode(grade.letter_grade),
                 'course_edited_timestamp':
                 unicode(grade.course_edited_timestamp),
                 'event_transaction_id':
                 unicode(get_event_transaction_id()),
                 'event_transaction_type':
                 unicode(get_event_transaction_type()),
                 'grading_policy_hash':
                 unicode(grade.grading_policy_hash),
             })
예제 #8
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            assert isinstance(self.course_id, CourseKey)
            data = {"user_id": self.user.id, "course_id": self.course_id.to_deprecated_string(), "mode": self.mode}

            with tracker.get_tracker().context(event_name, context):
                tracker.emit(event_name, data)

                if settings.FEATURES.get("SEGMENT_IO_LMS") and settings.SEGMENT_IO_LMS_KEY:
                    tracking_context = tracker.get_tracker().resolve_context()
                    analytics.track(
                        self.user_id,
                        event_name,
                        {
                            "category": "conversion",
                            "label": self.course_id.to_deprecated_string(),
                            "org": self.course_id.org,
                            "course": self.course_id.course,
                            "run": self.course_id.run,
                            "mode": self.mode,
                        },
                        context={"Google Analytics": {"clientId": tracking_context.get("client_id")}},
                    )

        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception(
                    "Unable to emit event %s for user %s and course %s", event_name, self.user.username, self.course_id
                )
예제 #9
0
def course_grade_calculated(course_grade):
    """
    Emits an edx.grades.course.grade_calculated event
    with data from the passed course_grade.
    """
    event_name = COURSE_GRADE_CALCULATED
    context = contexts.course_context_from_course_id(course_grade.course_id)
    # TODO (AN-6134): remove this context manager
    with tracker.get_tracker().context(event_name, context):
        tracker.emit(
            event_name, {
                'user_id':
                unicode(course_grade.user_id),
                'course_id':
                unicode(course_grade.course_id),
                'course_version':
                unicode(course_grade.course_version),
                'percent_grade':
                course_grade.percent_grade,
                'letter_grade':
                unicode(course_grade.letter_grade),
                'course_edited_timestamp':
                unicode(course_grade.course_edited_timestamp),
                'event_transaction_id':
                unicode(get_event_transaction_id()),
                'event_transaction_type':
                unicode(get_event_transaction_type()),
                'grading_policy_hash':
                unicode(course_grade.grading_policy_hash),
            })
예제 #10
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            assert(isinstance(self.course_id, CourseKey))
            data = {
                'user_id': self.user.id,
                'course_id': self.course_id.to_deprecated_string(),
                'mode': self.mode,
            }

            with tracker.get_tracker().context(event_name, context):
                tracker.emit(event_name, data)

                if settings.FEATURES.get('SEGMENT_IO_LMS') and settings.SEGMENT_IO_LMS_KEY:
                    tracking_context = tracker.get_tracker().resolve_context()
                    analytics.track(self.user_id, event_name, {
                        'category': 'conversion',
                        'label': self.course_id.to_deprecated_string(),
                        'org': self.course_id.org,
                        'course': self.course_id.course,
                        'run': self.course_id.run,
                        'mode': self.mode,
                    }, context={
                        'Google Analytics': {
                            'clientId': tracking_context.get('client_id')
                        }
                    })

        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception('Unable to emit event %s for user %s and course %s', event_name, self.user.username, self.course_id)
예제 #11
0
def emit_team_event(event_name, course_key, event_data):
    """
    Emit team events with the correct course id context.
    """
    context = contexts.course_context_from_course_id(course_key)

    with tracker.get_tracker().context(event_name, context):
        tracker.emit(event_name, event_data)
def emit_team_event(event_name, course_key, event_data):
    """
    Emit team events with the correct course id context.
    """
    context = contexts.course_context_from_course_id(course_key)

    with tracker.get_tracker().context(event_name, context):
        tracker.emit(event_name, event_data)
예제 #13
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            data = {"user_id": self.user.id, "course_id": self.course_id, "mode": self.mode}

            with tracker.get_tracker().context(event_name, context):
                server_track(crum.get_current_request(), event_name, data)
        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception(
                    "Unable to emit event %s for user %s and course %s", event_name, self.user.username, self.course_id
                )
예제 #14
0
 def publish_event(event_name, result, **kwargs):
     """
     Helper function to publish an event for analytics purposes
     """
     event_data = {
         "location": unicode(location),
         "previous_count": previous_count,
         "result": result,
         "max_count": max_count,
     }
     event_data.update(kwargs)
     context = contexts.course_context_from_course_id(location.course_key)
     if user_id:
         context['user_id'] = user_id
     full_event_name = "edx.librarycontentblock.content.{}".format(event_name)
     with tracker.get_tracker().context(full_event_name, context):
         tracker.emit(full_event_name, event_data)
예제 #15
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            assert isinstance(self.course_id, SlashSeparatedCourseKey)
            data = {"user_id": self.user.id, "course_id": self.course_id.to_deprecated_string(), "mode": self.mode}

            with tracker.get_tracker().context(event_name, context):
                tracker.emit(event_name, data)
        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception(
                    "Unable to emit event %s for user %s and course %s", event_name, self.user.username, self.course_id
                )
예제 #16
0
 def publish_event(event_name, result, **kwargs):
     """
     Helper function to publish an event for analytics purposes
     """
     event_data = {
         "location": unicode(location),
         "previous_count": previous_count,
         "result": result,
         "max_count": max_count,
     }
     event_data.update(kwargs)
     context = contexts.course_context_from_course_id(location.course_key)
     if user_id:
         context['user_id'] = user_id
     full_event_name = "edx.librarycontentblock.content.{}".format(event_name)
     with tracker.get_tracker().context(full_event_name, context):
         tracker.emit(full_event_name, event_data)
예제 #17
0
    def emit_event(self, event_name):
        """
        Emits an event to explicitly track course enrollment and unenrollment.
        """

        try:
            context = contexts.course_context_from_course_id(self.course_id)
            data = {
                'user_id': self.user.id,
                'course_id': self.course_id,
                'mode': self.mode,
            }

            with tracker.get_tracker().context(event_name, context):
                tracker.emit(event_name, data)
        except:  # pylint: disable=bare-except
            if event_name and self.course_id:
                log.exception('Unable to emit event %s for user %s and course %s', event_name, self.user.username, self.course_id)
예제 #18
0
 def publish(block, event_type, event):
     """
     A function that allows XModules to publish events.
     """
     handle_event = get_event_handler(event_type)
     if handle_event and not is_masquerading_as_specific_student(user, course_id):
         handle_event(block, event)
     else:
         context = contexts.course_context_from_course_id(course_id)
         if block.runtime.user_id:
             context['user_id'] = block.runtime.user_id
         context['asides'] = {}
         for aside in block.runtime.get_asides(block):
             if hasattr(aside, 'get_event_context'):
                 aside_event_info = aside.get_event_context(event_type, event)
                 if aside_event_info is not None:
                     context['asides'][aside.scope_ids.block_type] = aside_event_info
         with tracker.get_tracker().context(event_type, context):
             track_function(event_type, event)
예제 #19
0
 def publish(block, event_type, event):
     """
     A function that allows XModules to publish events.
     """
     handle_event = get_event_handler(event_type)
     if handle_event and not is_masquerading_as_specific_student(user, course_id):
         handle_event(block, event)
     else:
         context = contexts.course_context_from_course_id(course_id)
         if block.runtime.user_id:
             context['user_id'] = block.runtime.user_id
         context['asides'] = {}
         for aside in block.runtime.get_asides(block):
             if hasattr(aside, 'get_event_context'):
                 aside_event_info = aside.get_event_context(event_type, event)
                 if aside_event_info is not None:
                     context['asides'][aside.scope_ids.block_type] = aside_event_info
         with tracker.get_tracker().context(event_type, context):
             track_function(event_type, event)
예제 #20
0
 def publish(block, event_type, event):
     """A function that allows XModules to publish events."""
     if event_type == 'grade':
         handle_grade_event(block, event_type, event)
     elif event_type == 'progress':
         # expose another special case event type which gets sent
         # into the CourseCompletions models
         handle_progress_event(block, event_type, event)
     else:
         context = contexts.course_context_from_course_id(course_id)
         if block.runtime.user_id:
             context['user_id'] = block.runtime.user_id
         context['asides'] = {}
         for aside in block.runtime.get_asides(block):
             if hasattr(aside, 'get_event_context'):
                 aside_event_info = aside.get_event_context(event_type, event)
                 if aside_event_info is not None:
                     context['asides'][aside.scope_ids.block_type] = aside_event_info
         with tracker.get_tracker().context(event_type, context):
             track_function(event_type, event)
예제 #21
0
 def _emit_grade_calculated_event(grade):
     """
     Emits an edx.grades.course.grade_calculated event
     with data from the passed grade.
     """
     # TODO: remove this context manager after completion of AN-6134
     event_name = u'edx.grades.course.grade_calculated'
     context = contexts.course_context_from_course_id(grade.course_id)
     with tracker.get_tracker().context(event_name, context):
         tracker.emit(
             event_name,
             {
                 'user_id': unicode(grade.user_id),
                 'course_id': unicode(grade.course_id),
                 'course_version': unicode(grade.course_version),
                 'percent_grade': grade.percent_grade,
                 'letter_grade': unicode(grade.letter_grade),
                 'course_edited_timestamp': unicode(grade.course_edited_timestamp),
                 'event_transaction_id': unicode(get_event_transaction_id()),
                 'event_transaction_type': unicode(get_event_transaction_type()),
                 'grading_policy_hash': unicode(grade.grading_policy_hash),
             }
         )
예제 #22
0
 def publish(block, event_type, event):
     """A function that allows XModules to publish events."""
     if event_type == 'grade' and not is_masquerading_as_specific_student(user, course_id):
         SCORE_PUBLISHED.send(
             sender=None,
             block=block,
             user=user,
             raw_earned=event['value'],
             raw_possible=event['max_value'],
             only_if_higher=event.get('only_if_higher'),
         )
     else:
         context = contexts.course_context_from_course_id(course_id)
         if block.runtime.user_id:
             context['user_id'] = block.runtime.user_id
         context['asides'] = {}
         for aside in block.runtime.get_asides(block):
             if hasattr(aside, 'get_event_context'):
                 aside_event_info = aside.get_event_context(event_type, event)
                 if aside_event_info is not None:
                     context['asides'][aside.scope_ids.block_type] = aside_event_info
         with tracker.get_tracker().context(event_type, context):
             track_function(event_type, event)
예제 #23
0
def course_grade_calculated(course_grade):
    """
    Emits an edx.grades.course.grade_calculated event
    with data from the passed course_grade.
    """
    event_name = COURSE_GRADE_CALCULATED
    context = contexts.course_context_from_course_id(course_grade.course_id)
    # TODO (AN-6134): remove this context manager
    with tracker.get_tracker().context(event_name, context):
        tracker.emit(
            event_name,
            {
                'user_id': unicode(course_grade.user_id),
                'course_id': unicode(course_grade.course_id),
                'course_version': unicode(course_grade.course_version),
                'percent_grade': course_grade.percent_grade,
                'letter_grade': unicode(course_grade.letter_grade),
                'course_edited_timestamp': unicode(course_grade.course_edited_timestamp),
                'event_transaction_id': unicode(get_event_transaction_id()),
                'event_transaction_type': unicode(get_event_transaction_type()),
                'grading_policy_hash': unicode(course_grade.grading_policy_hash),
            }
        )
예제 #24
0
def rescore_problem_module_state(xmodule_instance_args, module_descriptor,
                                 student_module, task_input):
    '''
    Takes an XModule descriptor and a corresponding StudentModule object, and
    performs rescoring on the student's problem submission.

    Throws exceptions if the rescoring is fatal and should be aborted if in a loop.
    In particular, raises UpdateProblemModuleStateError if module fails to instantiate,
    or if the module doesn't support rescoring.

    Returns True if problem was successfully rescored for the given student, and False
    if problem encountered some kind of error in rescoring.
    '''
    # unpack the StudentModule:
    course_id = student_module.course_id
    student = student_module.student
    usage_key = student_module.module_state_key

    with modulestore().bulk_operations(course_id):
        course = get_course_by_id(course_id)
        # TODO: Here is a call site where we could pass in a loaded course.  I
        # think we certainly need it since grading is happening here, and field
        # overrides would be important in handling that correctly
        instance = _get_module_instance_for_task(course_id,
                                                 student,
                                                 module_descriptor,
                                                 xmodule_instance_args,
                                                 grade_bucket_type='rescore',
                                                 course=course)

        if instance is None:
            # Either permissions just changed, or someone is trying to be clever
            # and load something they shouldn't have access to.
            msg = "No module {loc} for student {student}--access denied?".format(
                loc=usage_key, student=student)
            TASK_LOG.warning(msg)
            return UPDATE_STATUS_FAILED

        # TODO: (TNL-6594)  Remove this switch once rescore_problem support
        # once CAPA uses ScorableXBlockMixin.
        for method in ['rescore', 'rescore_problem']:
            rescore_method = getattr(instance, method, None)
            if rescore_method is not None:
                break
        else:  # for-else: Neither method exists on the block.
            # This should not happen, since it should be already checked in the
            # caller, but check here to be sure.
            msg = "Specified problem does not support rescoring."
            raise UpdateProblemModuleStateError(msg)

        # TODO: Remove the first part of this if-else with TNL-6594
        # We check here to see if the problem has any submissions. If it does not, we don't want to rescore it
        if hasattr(instance, "done"):
            if not instance.done:
                return UPDATE_STATUS_SKIPPED
        elif not instance.has_submitted_answer():
            return UPDATE_STATUS_SKIPPED

        # Set the tracking info before this call, because it makes downstream
        # calls that create events.  We retrieve and store the id here because
        # the request cache will be erased during downstream calls.
        event_transaction_id = create_new_event_transaction_id()
        set_event_transaction_type(GRADES_RESCORE_EVENT_TYPE)

        result = rescore_method(only_if_higher=task_input['only_if_higher'])
        instance.save()

        if result is None or result.get(u'success') in {
                u'correct', u'incorrect'
        }:
            TASK_LOG.debug(
                u"successfully processed rescore call for course %(course)s, problem %(loc)s "
                u"and student %(student)s",
                dict(course=course_id, loc=usage_key, student=student))

            if result is not None:  # Only for CAPA. This will get moved to the grade handler.
                new_weighted_earned, new_weighted_possible = weighted_score(
                    result['new_raw_earned'] if result else None,
                    result['new_raw_possible'] if result else None,
                    module_descriptor.weight,
                )

                # TODO: remove this context manager after completion of AN-6134
                context = course_context_from_course_id(course_id)
                with tracker.get_tracker().context(GRADES_RESCORE_EVENT_TYPE,
                                                   context):
                    tracker.emit(
                        unicode(GRADES_RESCORE_EVENT_TYPE), {
                            'course_id':
                            unicode(course_id),
                            'user_id':
                            unicode(student.id),
                            'problem_id':
                            unicode(usage_key),
                            'new_weighted_earned':
                            new_weighted_earned,
                            'new_weighted_possible':
                            new_weighted_possible,
                            'only_if_higher':
                            task_input['only_if_higher'],
                            'instructor_id':
                            unicode(xmodule_instance_args['request_info']
                                    ['user_id']),
                            'event_transaction_id':
                            unicode(event_transaction_id),
                            'event_transaction_type':
                            unicode(GRADES_RESCORE_EVENT_TYPE),
                        })
            return UPDATE_STATUS_SUCCEEDED
        else:
            TASK_LOG.warning(
                u"error processing rescore call for course %(course)s, problem %(loc)s "
                u"and student %(student)s: %(msg)s",
                dict(msg=result.get('success', result),
                     course=course_id,
                     loc=usage_key,
                     student=student))
            return UPDATE_STATUS_FAILED