Commit 6a55ef79 by Joel Barciauskas Committed by GitHub

Merge pull request #14633 from edx/jbarciauskas/remove-newrelic-dep

Wrap all newrelic dependencies in a check to see if the module is loaded
parents b71f7d98 630985b3
...@@ -6,7 +6,14 @@ This middleware will only call on the newrelic agent if there are any metrics ...@@ -6,7 +6,14 @@ This middleware will only call on the newrelic agent if there are any metrics
to report for this request, so it will not incur any processing overhead for to report for this request, so it will not incur any processing overhead for
request handlers which do not record custom metrics. request handlers which do not record custom metrics.
""" """
import newrelic.agent import logging
log = logging.getLogger(__name__)
try:
import newrelic.agent
except ImportError:
log.warning("Unable to load NewRelic agent module")
newrelic = None # pylint: disable=invalid-name
import request_cache import request_cache
REQUEST_CACHE_KEY = 'newrelic_custom_metrics' REQUEST_CACHE_KEY = 'newrelic_custom_metrics'
...@@ -40,6 +47,8 @@ class NewRelicCustomMetrics(object): ...@@ -40,6 +47,8 @@ class NewRelicCustomMetrics(object):
""" """
Report the collected custom metrics to New Relic. Report the collected custom metrics to New Relic.
""" """
if not newrelic:
return
metrics_cache = cls._get_metrics_cache() metrics_cache = cls._get_metrics_cache()
for metric_name, metric_value in metrics_cache.iteritems(): for metric_name, metric_value in metrics_cache.iteritems():
newrelic.agent.add_custom_parameter(metric_name, metric_value) newrelic.agent.add_custom_parameter(metric_name, metric_value)
......
...@@ -14,7 +14,6 @@ from lxml import etree ...@@ -14,7 +14,6 @@ from lxml import etree
from xblock.core import XBlock from xblock.core import XBlock
from xblock.fields import Integer, Scope, Boolean, String from xblock.fields import Integer, Scope, Boolean, String
from xblock.fragment import Fragment from xblock.fragment import Fragment
import newrelic.agent
from .exceptions import NotFoundError from .exceptions import NotFoundError
from .fields import Date from .fields import Date
...@@ -25,6 +24,11 @@ from .xml_module import XmlDescriptor ...@@ -25,6 +24,11 @@ from .xml_module import XmlDescriptor
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
try:
import newrelic.agent
except ImportError:
newrelic = None # pylint: disable=invalid-name
# HACK: This shouldn't be hard-coded to two types # HACK: This shouldn't be hard-coded to two types
# OBSOLETE: This obsoletes 'type' # OBSOLETE: This obsoletes 'type'
class_priority = ['video', 'problem'] class_priority = ['video', 'problem']
...@@ -385,6 +389,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -385,6 +389,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
""" """
Capture basic information about this sequence in New Relic. Capture basic information about this sequence in New Relic.
""" """
if not newrelic:
return
newrelic.agent.add_custom_parameter('seq.block_id', unicode(self.location)) newrelic.agent.add_custom_parameter('seq.block_id', unicode(self.location))
newrelic.agent.add_custom_parameter('seq.display_name', self.display_name or '') newrelic.agent.add_custom_parameter('seq.display_name', self.display_name or '')
newrelic.agent.add_custom_parameter('seq.position', self.position) newrelic.agent.add_custom_parameter('seq.position', self.position)
...@@ -396,6 +402,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -396,6 +402,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
the sequence as a whole. We send this information to New Relic so that the sequence as a whole. We send this information to New Relic so that
we can do better performance analysis of courseware. we can do better performance analysis of courseware.
""" """
if not newrelic:
return
# Basic count of the number of Units (a.k.a. VerticalBlocks) we have in # Basic count of the number of Units (a.k.a. VerticalBlocks) we have in
# this learning sequence # this learning sequence
newrelic.agent.add_custom_parameter('seq.num_units', len(display_items)) newrelic.agent.add_custom_parameter('seq.num_units', len(display_items))
...@@ -414,6 +422,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -414,6 +422,8 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
""" """
Capture information about the current selected Unit within the Sequence. Capture information about the current selected Unit within the Sequence.
""" """
if not newrelic:
return
# Positions are stored with indexing starting at 1. If we get into a # Positions are stored with indexing starting at 1. If we get into a
# weird state where the saved position is out of bounds (e.g. the # weird state where the saved position is out of bounds (e.g. the
# content was changed), avoid going into any details about this unit. # content was changed), avoid going into any details about this unit.
......
...@@ -8,7 +8,6 @@ import logging ...@@ -8,7 +8,6 @@ import logging
from collections import OrderedDict from collections import OrderedDict
from functools import partial from functools import partial
import newrelic.agent
from capa.xqueue_interface import XQueueInterface from capa.xqueue_interface import XQueueInterface
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
...@@ -82,6 +81,10 @@ from .field_overrides import OverrideFieldData ...@@ -82,6 +81,10 @@ from .field_overrides import OverrideFieldData
log = logging.getLogger(__name__) 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: if settings.XQUEUE_INTERFACE.get('basic_auth') is not None:
REQUESTS_AUTH = HTTPBasicAuth(*settings.XQUEUE_INTERFACE['basic_auth']) REQUESTS_AUTH = HTTPBasicAuth(*settings.XQUEUE_INTERFACE['basic_auth'])
...@@ -967,9 +970,10 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course ...@@ -967,9 +970,10 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course
except InvalidKeyError: except InvalidKeyError:
raise Http404 raise Http404
# Gather metrics for New Relic so we can slice data in New Relic Insights if newrelic:
newrelic.agent.add_custom_parameter('course_id', unicode(course_key)) # Gather metrics for New Relic so we can slice data in New Relic Insights
newrelic.agent.add_custom_parameter('org', unicode(course_key.org)) newrelic.agent.add_custom_parameter('course_id', unicode(course_key))
newrelic.agent.add_custom_parameter('org', unicode(course_key.org))
with modulestore().bulk_operations(course_key): with modulestore().bulk_operations(course_key):
instance, tracking_context = get_module_by_usage_id(request, course_id, usage_id, course=course) instance, tracking_context = get_module_by_usage_id(request, course_id, usage_id, course=course)
...@@ -979,7 +983,8 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course ...@@ -979,7 +983,8 @@ def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course
# "handler" in those cases is always just "xmodule_handler". # "handler" in those cases is always just "xmodule_handler".
nr_tx_name = "{}.{}".format(instance.__class__.__name__, handler) nr_tx_name = "{}.{}".format(instance.__class__.__name__, handler)
nr_tx_name += "/{}".format(suffix) if (suffix and handler == "xmodule_handler") else "" nr_tx_name += "/{}".format(suffix) if (suffix and handler == "xmodule_handler") else ""
newrelic.agent.set_transaction_name(nr_tx_name, group="Python/XBlock/Handler") if newrelic:
newrelic.agent.set_transaction_name(nr_tx_name, group="Python/XBlock/Handler")
tracking_context_name = 'module_callback_handler' tracking_context_name = 'module_callback_handler'
req = django_to_webob_request(request) req = django_to_webob_request(request)
......
...@@ -19,7 +19,14 @@ from django.shortcuts import redirect ...@@ -19,7 +19,14 @@ from django.shortcuts import redirect
from courseware.url_helpers import get_redirect_url_for_global_staff from courseware.url_helpers import get_redirect_url_for_global_staff
from edxmako.shortcuts import render_to_response, render_to_string from edxmako.shortcuts import render_to_response, render_to_string
import logging import logging
import newrelic.agent
log = logging.getLogger("edx.courseware.views.index")
try:
import newrelic.agent
except ImportError:
newrelic = None # pylint: disable=invalid-name
import urllib import urllib
from lms.djangoapps.gating.api import get_entrance_exam_score_ratio, get_entrance_exam_usage_key from lms.djangoapps.gating.api import get_entrance_exam_score_ratio, get_entrance_exam_usage_key
...@@ -55,7 +62,6 @@ from ..module_render import toc_for_course, get_module_for_descriptor ...@@ -55,7 +62,6 @@ from ..module_render import toc_for_course, get_module_for_descriptor
from .views import get_current_child, registered_for_course from .views import get_current_child, registered_for_course
log = logging.getLogger("edx.courseware.views.index")
TEMPLATE_IMPORTS = {'urllib': urllib} TEMPLATE_IMPORTS = {'urllib': urllib}
CONTENT_DEPTH = 2 CONTENT_DEPTH = 2
...@@ -175,6 +181,8 @@ class CoursewareIndex(View): ...@@ -175,6 +181,8 @@ class CoursewareIndex(View):
""" """
Initialize metrics for New Relic so we can slice data in New Relic Insights 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('course_id', unicode(self.course_key))
newrelic.agent.add_custom_parameter('org', unicode(self.course_key.org)) newrelic.agent.add_custom_parameter('org', unicode(self.course_key.org))
......
...@@ -17,7 +17,13 @@ from django.shortcuts import render_to_response ...@@ -17,7 +17,13 @@ from django.shortcuts import render_to_response
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import get_language_bidi from django.utils.translation import get_language_bidi
from django.views.decorators.http import require_GET from django.views.decorators.http import require_GET
import newrelic.agent
log = logging.getLogger("edx.discussions")
try:
import newrelic.agent
except ImportError:
newrelic = None # pylint: disable=invalid-name
from rest_framework import status from rest_framework import status
from web_fragments.fragment import Fragment from web_fragments.fragment import Fragment
...@@ -51,13 +57,27 @@ from util.enterprise_helpers import data_sharing_consent_required ...@@ -51,13 +57,27 @@ from util.enterprise_helpers import data_sharing_consent_required
from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.keys import CourseKey
from contextlib import contextmanager
THREADS_PER_PAGE = 20 THREADS_PER_PAGE = 20
INLINE_THREADS_PER_PAGE = 20 INLINE_THREADS_PER_PAGE = 20
PAGES_NEARBY_DELTA = 2 PAGES_NEARBY_DELTA = 2
log = logging.getLogger("edx.discussions")
@newrelic.agent.function_trace() @contextmanager
def newrelic_function_trace(function_name):
"""
A wrapper context manager newrelic.agent.FunctionTrace to no-op if the
newrelic package is not installed
"""
if newrelic:
nr_transaction = newrelic.agent.current_transaction()
with newrelic.agent.FunctionTrace(nr_transaction, function_name):
yield
else:
yield
def make_course_settings(course, user): def make_course_settings(course, user):
""" """
Generate a JSON-serializable model for course settings, which will be used to initialize a Generate a JSON-serializable model for course settings, which will be used to initialize a
...@@ -72,7 +92,6 @@ def make_course_settings(course, user): ...@@ -72,7 +92,6 @@ def make_course_settings(course, user):
} }
@newrelic.agent.function_trace()
def get_threads(request, course, user_info, discussion_id=None, per_page=THREADS_PER_PAGE): def get_threads(request, course, user_info, discussion_id=None, per_page=THREADS_PER_PAGE):
""" """
This may raise an appropriate subclass of cc.utils.CommentClientError This may raise an appropriate subclass of cc.utils.CommentClientError
...@@ -186,7 +205,6 @@ def inline_discussion(request, course_key, discussion_id): ...@@ -186,7 +205,6 @@ def inline_discussion(request, course_key, discussion_id):
""" """
Renders JSON for DiscussionModules Renders JSON for DiscussionModules
""" """
nr_transaction = newrelic.agent.current_transaction()
course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True)
cc_user = cc.User.from_django_user(request.user) cc_user = cc.User.from_django_user(request.user)
...@@ -197,12 +215,14 @@ def inline_discussion(request, course_key, discussion_id): ...@@ -197,12 +215,14 @@ def inline_discussion(request, course_key, discussion_id):
except ValueError: except ValueError:
return HttpResponseServerError("Invalid group_id") return HttpResponseServerError("Invalid group_id")
with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): with newrelic_function_trace("get_metadata_for_threads"):
annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info) annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info)
is_staff = has_permission(request.user, 'openclose_thread', course.id) is_staff = has_permission(request.user, 'openclose_thread', course.id)
threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads] threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads]
with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): with newrelic_function_trace("add_courseware_context"):
add_courseware_context(threads, course, request.user) add_courseware_context(threads, course, request.user)
return utils.JsonResponse({ return utils.JsonResponse({
'is_commentable_cohorted': is_commentable_cohorted(course_key, discussion_id), 'is_commentable_cohorted': is_commentable_cohorted(course_key, discussion_id),
'discussion_data': threads, 'discussion_data': threads,
...@@ -222,8 +242,6 @@ def forum_form_discussion(request, course_key): ...@@ -222,8 +242,6 @@ def forum_form_discussion(request, course_key):
""" """
Renders the main Discussion page, potentially filtered by a search query Renders the main Discussion page, potentially filtered by a search query
""" """
nr_transaction = newrelic.agent.current_transaction()
course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True)
if request.is_ajax(): if request.is_ajax():
user = cc.User.from_django_user(request.user) user = cc.User.from_django_user(request.user)
...@@ -238,10 +256,10 @@ def forum_form_discussion(request, course_key): ...@@ -238,10 +256,10 @@ def forum_form_discussion(request, course_key):
except ValueError: except ValueError:
return HttpResponseServerError("Invalid group_id") return HttpResponseServerError("Invalid group_id")
with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): with newrelic_function_trace("get_metadata_for_threads"):
annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info) annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info)
with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): with newrelic_function_trace("add_courseware_context"):
add_courseware_context(threads, course, request.user) add_courseware_context(threads, course, request.user)
return utils.JsonResponse({ return utils.JsonResponse({
...@@ -269,8 +287,6 @@ def single_thread(request, course_key, discussion_id, thread_id): ...@@ -269,8 +287,6 @@ def single_thread(request, course_key, discussion_id, thread_id):
Depending on the HTTP headers, we'll adjust our response accordingly. Depending on the HTTP headers, we'll adjust our response accordingly.
""" """
nr_transaction = newrelic.agent.current_transaction()
course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True)
if request.is_ajax(): if request.is_ajax():
...@@ -282,7 +298,7 @@ def single_thread(request, course_key, discussion_id, thread_id): ...@@ -282,7 +298,7 @@ def single_thread(request, course_key, discussion_id, thread_id):
if not thread: if not thread:
raise Http404 raise Http404
with newrelic.agent.FunctionTrace(nr_transaction, "get_annotated_content_infos"): with newrelic_function_trace("get_annotated_content_infos"):
annotated_content_info = utils.get_annotated_content_infos( annotated_content_info = utils.get_annotated_content_infos(
course_key, course_key,
thread, thread,
...@@ -291,7 +307,7 @@ def single_thread(request, course_key, discussion_id, thread_id): ...@@ -291,7 +307,7 @@ def single_thread(request, course_key, discussion_id, thread_id):
) )
content = utils.prepare_content(thread.to_dict(), course_key, is_staff) content = utils.prepare_content(thread.to_dict(), course_key, is_staff)
with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): with newrelic_function_trace("add_courseware_context"):
add_courseware_context([content], course, request.user) add_courseware_context([content], course, request.user)
return utils.JsonResponse({ return utils.JsonResponse({
...@@ -376,7 +392,6 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th ...@@ -376,7 +392,6 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th
""" """
Returns the template context for rendering the discussion board. Returns the template context for rendering the discussion board.
""" """
nr_transaction = newrelic.agent.current_transaction()
context = _create_base_discussion_view_context(request, course_key) context = _create_base_discussion_view_context(request, course_key)
course = context['course'] course = context['course']
course_settings = context['course_settings'] course_settings = context['course_settings']
...@@ -405,13 +420,13 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th ...@@ -405,13 +420,13 @@ def _create_discussion_board_context(request, course_key, discussion_id=None, th
is_staff = has_permission(user, 'openclose_thread', course.id) is_staff = has_permission(user, 'openclose_thread', course.id)
threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads] threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads]
with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): with newrelic_function_trace("get_metadata_for_threads"):
annotated_content_info = utils.get_metadata_for_threads(course_key, threads, user, user_info) annotated_content_info = utils.get_metadata_for_threads(course_key, threads, user, user_info)
with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): with newrelic_function_trace("add_courseware_context"):
add_courseware_context(threads, course, user) add_courseware_context(threads, course, user)
with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): with newrelic_function_trace("get_cohort_info"):
user_cohort_id = get_cohort_id(user, course_key) user_cohort_id = get_cohort_id(user, course_key)
context.update({ context.update({
...@@ -439,9 +454,6 @@ def user_profile(request, course_key, user_id): ...@@ -439,9 +454,6 @@ def user_profile(request, course_key, user_id):
Renders a response to display the user profile page (shown after clicking Renders a response to display the user profile page (shown after clicking
on a post author's username). on a post author's username).
""" """
nr_transaction = newrelic.agent.current_transaction()
user = cc.User.from_django_user(request.user) user = cc.User.from_django_user(request.user)
course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True)
...@@ -470,13 +482,13 @@ def user_profile(request, course_key, user_id): ...@@ -470,13 +482,13 @@ def user_profile(request, course_key, user_id):
query_params['page'] = page query_params['page'] = page
query_params['num_pages'] = num_pages query_params['num_pages'] = num_pages
with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): with newrelic_function_trace("get_metadata_for_threads"):
user_info = cc.User.from_django_user(request.user).to_dict() user_info = cc.User.from_django_user(request.user).to_dict()
annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info) annotated_content_info = utils.get_metadata_for_threads(course_key, threads, request.user, user_info)
is_staff = has_permission(request.user, 'openclose_thread', course.id) is_staff = has_permission(request.user, 'openclose_thread', course.id)
threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads] threads = [utils.prepare_content(thread, course_key, is_staff) for thread in threads]
with newrelic.agent.FunctionTrace(nr_transaction, "add_courseware_context"): with newrelic_function_trace("add_courseware_context"):
add_courseware_context(threads, course, request.user) add_courseware_context(threads, course, request.user)
if request.is_ajax(): if request.is_ajax():
return utils.JsonResponse({ return utils.JsonResponse({
...@@ -490,7 +502,7 @@ def user_profile(request, course_key, user_id): ...@@ -490,7 +502,7 @@ def user_profile(request, course_key, user_id):
course_id=course.id course_id=course.id
).order_by("name").values_list("name", flat=True).distinct() ).order_by("name").values_list("name", flat=True).distinct()
with newrelic.agent.FunctionTrace(nr_transaction, "get_cohort_info"): with newrelic_function_trace("get_cohort_info"):
user_cohort_id = get_cohort_id(request.user, course_key) user_cohort_id = get_cohort_id(request.user, course_key)
context = _create_base_discussion_view_context(request, course_key) context = _create_base_discussion_view_context(request, course_key)
...@@ -518,9 +530,6 @@ def followed_threads(request, course_key, user_id): ...@@ -518,9 +530,6 @@ def followed_threads(request, course_key, user_id):
""" """
Ajax-only endpoint retrieving the threads followed by a specific user. Ajax-only endpoint retrieving the threads followed by a specific user.
""" """
nr_transaction = newrelic.agent.current_transaction()
course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True)
try: try:
profiled_user = cc.User(id=user_id, course_id=course_key) profiled_user = cc.User(id=user_id, course_id=course_key)
...@@ -561,7 +570,7 @@ def followed_threads(request, course_key, user_id): ...@@ -561,7 +570,7 @@ def followed_threads(request, course_key, user_id):
query_params['num_pages'] = paginated_results.num_pages query_params['num_pages'] = paginated_results.num_pages
user_info = cc.User.from_django_user(request.user).to_dict() user_info = cc.User.from_django_user(request.user).to_dict()
with newrelic.agent.FunctionTrace(nr_transaction, "get_metadata_for_threads"): with newrelic_function_trace("get_metadata_for_threads"):
annotated_content_info = utils.get_metadata_for_threads( annotated_content_info = utils.get_metadata_for_threads(
course_key, course_key,
paginated_results.collection, paginated_results.collection,
......
...@@ -8,7 +8,12 @@ from django.contrib.auth.models import User ...@@ -8,7 +8,12 @@ from django.contrib.auth.models import User
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db.utils import DatabaseError from django.db.utils import DatabaseError
from logging import getLogger from logging import getLogger
import newrelic.agent
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.logged_task import LoggedTask
from celery_utils.persist_on_failure import PersistOnFailureTask from celery_utils.persist_on_failure import PersistOnFailureTask
...@@ -29,8 +34,6 @@ from .new.subsection_grade import SubsectionGradeFactory ...@@ -29,8 +34,6 @@ from .new.subsection_grade import SubsectionGradeFactory
from .signals.signals import SUBSECTION_SCORE_CHANGED from .signals.signals import SUBSECTION_SCORE_CHANGED
from .transformer import GradesTransformer from .transformer import GradesTransformer
log = getLogger(__name__)
class DatabaseNotReadyError(IOError): class DatabaseNotReadyError(IOError):
""" """
...@@ -99,8 +102,9 @@ def _recalculate_subsection_grade(self, **kwargs): ...@@ -99,8 +102,9 @@ def _recalculate_subsection_grade(self, **kwargs):
course_key = CourseLocator.from_string(kwargs['course_id']) course_key = CourseLocator.from_string(kwargs['course_id'])
scored_block_usage_key = UsageKey.from_string(kwargs['usage_id']).replace(course_key=course_key) scored_block_usage_key = UsageKey.from_string(kwargs['usage_id']).replace(course_key=course_key)
newrelic.agent.add_custom_parameter('course_id', unicode(course_key)) if newrelic:
newrelic.agent.add_custom_parameter('usage_id', unicode(scored_block_usage_key)) newrelic.agent.add_custom_parameter('course_id', unicode(course_key))
newrelic.agent.add_custom_parameter('usage_id', unicode(scored_block_usage_key))
# The request cache is not maintained on celery workers, # The request cache is not maintained on celery workers,
# where this code runs. So we take the values from the # where this code runs. So we take the values from the
......
...@@ -4,7 +4,11 @@ Middleware to serve assets. ...@@ -4,7 +4,11 @@ Middleware to serve assets.
import logging import logging
import datetime import datetime
import newrelic.agent log = logging.getLogger(__name__)
try:
import newrelic.agent
except ImportError:
newrelic = None # pylint: disable=invalid-name
from django.http import ( from django.http import (
HttpResponse, HttpResponseNotModified, HttpResponseForbidden, HttpResponse, HttpResponseNotModified, HttpResponseForbidden,
HttpResponseBadRequest, HttpResponseNotFound, HttpResponsePermanentRedirect) HttpResponseBadRequest, HttpResponseNotFound, HttpResponsePermanentRedirect)
...@@ -25,7 +29,6 @@ from .models import CourseAssetCacheTtlConfig, CdnUserAgentsConfig ...@@ -25,7 +29,6 @@ from .models import CourseAssetCacheTtlConfig, CdnUserAgentsConfig
# TODO: Soon as we have a reasonable way to serialize/deserialize AssetKeys, we need # TODO: Soon as we have a reasonable way to serialize/deserialize AssetKeys, we need
# to change this file so instead of using course_id_partial, we're just using asset keys # to change this file so instead of using course_id_partial, we're just using asset keys
log = logging.getLogger(__name__)
HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT" HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
...@@ -86,17 +89,18 @@ class StaticContentServer(object): ...@@ -86,17 +89,18 @@ class StaticContentServer(object):
if safe_course_key.run is None: if safe_course_key.run is None:
safe_course_key = safe_course_key.replace(run='only') safe_course_key = safe_course_key.replace(run='only')
newrelic.agent.add_custom_parameter('course_id', safe_course_key) if newrelic:
newrelic.agent.add_custom_parameter('org', loc.org) newrelic.agent.add_custom_parameter('course_id', safe_course_key)
newrelic.agent.add_custom_parameter('contentserver.path', loc.path) newrelic.agent.add_custom_parameter('org', loc.org)
newrelic.agent.add_custom_parameter('contentserver.path', loc.path)
# Figure out if this is a CDN using us as the origin. # Figure out if this is a CDN using us as the origin.
is_from_cdn = StaticContentServer.is_cdn_request(request) is_from_cdn = StaticContentServer.is_cdn_request(request)
newrelic.agent.add_custom_parameter('contentserver.from_cdn', is_from_cdn) newrelic.agent.add_custom_parameter('contentserver.from_cdn', is_from_cdn)
# Check if this content is locked or not. # Check if this content is locked or not.
locked = self.is_content_locked(content) locked = self.is_content_locked(content)
newrelic.agent.add_custom_parameter('contentserver.locked', locked) newrelic.agent.add_custom_parameter('contentserver.locked', locked)
# Check that user has access to the content. # Check that user has access to the content.
if not self.is_user_authorized(request, content, loc): if not self.is_user_authorized(request, content, loc):
...@@ -153,7 +157,8 @@ class StaticContentServer(object): ...@@ -153,7 +157,8 @@ class StaticContentServer(object):
response['Content-Length'] = str(last - first + 1) response['Content-Length'] = str(last - first + 1)
response.status_code = 206 # Partial Content response.status_code = 206 # Partial Content
newrelic.agent.add_custom_parameter('contentserver.ranged', True) if newrelic:
newrelic.agent.add_custom_parameter('contentserver.ranged', True)
else: else:
log.warning( log.warning(
u"Cannot satisfy ranges in Range header: %s for content: %s", header_value, unicode(loc) u"Cannot satisfy ranges in Range header: %s for content: %s", header_value, unicode(loc)
...@@ -165,8 +170,9 @@ class StaticContentServer(object): ...@@ -165,8 +170,9 @@ class StaticContentServer(object):
response = HttpResponse(content.stream_data()) response = HttpResponse(content.stream_data())
response['Content-Length'] = content.length response['Content-Length'] = content.length
newrelic.agent.add_custom_parameter('contentserver.content_len', content.length) if newrelic:
newrelic.agent.add_custom_parameter('contentserver.content_type', content.content_type) newrelic.agent.add_custom_parameter('contentserver.content_len', content.length)
newrelic.agent.add_custom_parameter('contentserver.content_type', content.content_type)
# "Accept-Ranges: bytes" tells the user that only "bytes" ranges are allowed # "Accept-Ranges: bytes" tells the user that only "bytes" ranges are allowed
response['Accept-Ranges'] = 'bytes' response['Accept-Ranges'] = 'bytes'
...@@ -194,12 +200,14 @@ class StaticContentServer(object): ...@@ -194,12 +200,14 @@ class StaticContentServer(object):
# indicate there should be no caching whatsoever. # indicate there should be no caching whatsoever.
cache_ttl = CourseAssetCacheTtlConfig.get_cache_ttl() cache_ttl = CourseAssetCacheTtlConfig.get_cache_ttl()
if cache_ttl > 0 and not is_locked: if cache_ttl > 0 and not is_locked:
newrelic.agent.add_custom_parameter('contentserver.cacheable', True) if newrelic:
newrelic.agent.add_custom_parameter('contentserver.cacheable', True)
response['Expires'] = StaticContentServer.get_expiration_value(datetime.datetime.utcnow(), cache_ttl) response['Expires'] = StaticContentServer.get_expiration_value(datetime.datetime.utcnow(), cache_ttl)
response['Cache-Control'] = "public, max-age={ttl}, s-maxage={ttl}".format(ttl=cache_ttl) response['Cache-Control'] = "public, max-age={ttl}, s-maxage={ttl}".format(ttl=cache_ttl)
elif is_locked: elif is_locked:
newrelic.agent.add_custom_parameter('contentserver.cacheable', False) if newrelic:
newrelic.agent.add_custom_parameter('contentserver.cacheable', False)
response['Cache-Control'] = "private, no-cache, no-store" response['Cache-Control'] = "private, no-cache, no-store"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment