diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 4de76a77bb..c85a613422 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -52,6 +52,9 @@ from openedx.core.djangoapps.bookmarks.services import BookmarksService from openedx.core.djangoapps.crawlers.models import CrawlersConfig from openedx.core.djangoapps.credit.services import CreditService from openedx.core.djangoapps.util.user_utils import SystemUser +from openedx.core.djangoapps.monitoring_utils import ( + set_custom_metrics_for_course_key, set_monitoring_transaction_name +) from openedx.core.lib.xblock_utils import ( replace_course_urls, replace_jump_to_id_urls, @@ -81,11 +84,6 @@ from .field_overrides import OverrideFieldData log = logging.getLogger(__name__) -try: - import newrelic.agent -except ImportError: - newrelic = None # pylint: disable=invalid-name - if settings.XQUEUE_INTERFACE.get('basic_auth') is not None: REQUESTS_AUTH = HTTPBasicAuth(*settings.XQUEUE_INTERFACE['basic_auth']) else: @@ -970,10 +968,7 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course except InvalidKeyError: raise Http404 - if newrelic: - # Gather metrics for New Relic so we can slice data in New Relic Insights - newrelic.agent.add_custom_parameter('course_id', unicode(course_key)) - newrelic.agent.add_custom_parameter('org', unicode(course_key.org)) + set_custom_metrics_for_course_key(course_key) with modulestore().bulk_operations(course_key): instance, tracking_context = get_module_by_usage_id(request, course_id, usage_id, course=course) @@ -983,8 +978,7 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course # "handler" in those cases is always just "xmodule_handler". nr_tx_name = "{}.{}".format(instance.__class__.__name__, handler) nr_tx_name += "/{}".format(suffix) if (suffix and handler == "xmodule_handler") else "" - if newrelic: - newrelic.agent.set_transaction_name(nr_tx_name, group="Python/XBlock/Handler") + set_monitoring_transaction_name(nr_tx_name, group="Python/XBlock/Handler") tracking_context_name = 'module_callback_handler' req = django_to_webob_request(request) diff --git a/lms/djangoapps/courseware/views/index.py b/lms/djangoapps/courseware/views/index.py index 33c0a076d3..7fae4a491a 100644 --- a/lms/djangoapps/courseware/views/index.py +++ b/lms/djangoapps/courseware/views/index.py @@ -22,11 +22,6 @@ import logging log = logging.getLogger("edx.courseware.views.index") -try: - import newrelic.agent -except ImportError: - newrelic = None # pylint: disable=invalid-name - import urllib import waffle @@ -36,6 +31,7 @@ from opaque_keys.edx.keys import CourseKey from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY from openedx.core.djangoapps.user_api.preferences.api import get_user_preference from openedx.core.djangoapps.crawlers.models import CrawlersConfig +from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key from request_cache.middleware import RequestCache from shoppingcart.models import CourseRegistrationCode from student.models import CourseEnrollment @@ -107,7 +103,7 @@ class CoursewareIndex(View): self.url = request.path try: - self._init_new_relic() + set_custom_metrics_for_course_key(self.course_key) self._clean_position() with modulestore().bulk_operations(self.course_key): self.course = get_course_with_access(request.user, 'load', self.course_key, depth=CONTENT_DEPTH) @@ -180,15 +176,6 @@ class CoursewareIndex(View): ) ) - def _init_new_relic(self): - """ - Initialize metrics for New Relic so we can slice data in New Relic Insights - """ - if not newrelic: - return - newrelic.agent.add_custom_parameter('course_id', unicode(self.course_key)) - newrelic.agent.add_custom_parameter('org', unicode(self.course_key.org)) - def _clean_position(self): """ Verify that the given position is an integer. If it is not positive, set it to 1. diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py index 947881853b..ff7f2d9ced 100644 --- a/lms/djangoapps/courseware/views/views.py +++ b/lms/djangoapps/courseware/views/views.py @@ -87,8 +87,9 @@ from openedx.core.djangoapps.credit.api import ( ) from openedx.core.djangoapps.programs.utils import ProgramMarketingDataExtender from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers -from shoppingcart.utils import is_shopping_cart_enabled from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration +from openedx.core.djangoapps.monitoring_utils import set_custom_metrics_for_course_key +from shoppingcart.utils import is_shopping_cart_enabled from student.models import UserTestGroup, CourseEnrollment from student.roles import GlobalStaff from util.cache import cache, cache_if_anonymous @@ -502,6 +503,7 @@ class CourseTabView(EdxFragmentView): course = get_course_with_access(request.user, 'load', course_key) tab = CourseTabList.get_tab_by_type(course.tabs, tab_type) page_context = self.create_page_context(request, course=course, tab=tab, **kwargs) + set_custom_metrics_for_course_key(course_key) return super(CourseTabView, self).get(request, course=course, page_context=page_context, **kwargs) def create_page_context(self, request, course=None, tab=None, **kwargs): diff --git a/lms/djangoapps/grades/tasks.py b/lms/djangoapps/grades/tasks.py index e3acd10acb..c7d0704168 100644 --- a/lms/djangoapps/grades/tasks.py +++ b/lms/djangoapps/grades/tasks.py @@ -10,10 +10,6 @@ from django.db.utils import DatabaseError from logging import getLogger log = getLogger(__name__) -try: - import newrelic.agent -except ImportError: - newrelic = None # pylint: disable=invalid-name from celery_utils.logged_task import LoggedTask from celery_utils.persist_on_failure import PersistOnFailureTask @@ -22,6 +18,9 @@ from lms.djangoapps.course_blocks.api import get_course_blocks from lms.djangoapps.courseware import courses from opaque_keys.edx.keys import CourseKey, UsageKey from opaque_keys.edx.locator import CourseLocator +from openedx.core.djangoapps.monitoring_utils import ( + set_custom_metrics_for_course_key, set_custom_metric +) from student.models import CourseEnrollment from submissions import api as sub_api from track.event_transaction_utils import ( @@ -117,9 +116,8 @@ def _recalculate_subsection_grade(self, **kwargs): course_key = CourseLocator.from_string(kwargs['course_id']) scored_block_usage_key = UsageKey.from_string(kwargs['usage_id']).replace(course_key=course_key) - if newrelic: - newrelic.agent.add_custom_parameter('course_id', unicode(course_key)) - newrelic.agent.add_custom_parameter('usage_id', unicode(scored_block_usage_key)) + set_custom_metrics_for_course_key(course_key) + set_custom_metric('usage_id', unicode(scored_block_usage_key)) # The request cache is not maintained on celery workers, # where this code runs. So we take the values from the diff --git a/openedx/core/djangoapps/monitoring_utils/__init__.py b/openedx/core/djangoapps/monitoring_utils/__init__.py index 0234646274..bd581daf52 100644 --- a/openedx/core/djangoapps/monitoring_utils/__init__.py +++ b/openedx/core/djangoapps/monitoring_utils/__init__.py @@ -22,6 +22,11 @@ TODO: supply additional public functions for storing strings and booleans. """ from . import middleware +try: + import newrelic.agent +except ImportError: + newrelic = None # pylint: disable=invalid-name + def accumulate(name, value): """ @@ -53,3 +58,40 @@ def increment(name): middleware should automatically aggregate this metric. """ accumulate(name, 1) + + +def set_custom_metrics_for_course_key(course_key): + """ + Set monitoring custom metrics related to a course key. + + This is not cached, and only support reporting to New Relic Insights. + + """ + if not newrelic: + return + newrelic.agent.add_custom_parameter('course_id', unicode(course_key)) + newrelic.agent.add_custom_parameter('org', unicode(course_key.org)) + + +def set_custom_metric(key, value): + """ + Set monitoring custom metric. + + This is not cached, and only support reporting to New Relic Insights. + + """ + if not newrelic: + return + newrelic.agent.add_custom_parameter(key, value) + + +def set_monitoring_transaction_name(name, group=None, priority=None): + """ + Sets the transaction name for monitoring. + + This is not cached, and only support reporting to New Relic. + + """ + if not newrelic: + return + newrelic.agent.set_transaction_name(name, group, priority)