From 21d8b40576293ad88447307489943dbacdcb2be4 Mon Sep 17 00:00:00 2001
From: Usman Khalid <2200617@gmail.com>
Date: Thu, 6 Feb 2014 23:05:02 +0500
Subject: [PATCH] Added feature setting 'DISPLAY_HISTOGRAMS_TO_STAFF' to
 configure display of histograms in Staff Debug Info panel.

Generating histograms requires scanning the courseware_studentmodule table on
each view. This can make staff access to courseware very slow on large courses.

Default is False.

LMS-1199
---
 common/djangoapps/xmodule_modifiers.py        | 10 +++-
 .../courseware/tests/test_module_render.py    | 59 +++++++++++++++++++
 lms/envs/common.py                            |  1 +
 3 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py
index 654482fab6d..537a7592c2f 100644
--- a/common/djangoapps/xmodule_modifiers.py
+++ b/common/djangoapps/xmodule_modifiers.py
@@ -126,8 +126,12 @@ def replace_static_urls(data_dir, block, view, frag, context, course_id=None, st
 
 
 def grade_histogram(module_id):
-    ''' Print out a histogram of grades on a given problem.
-        Part of staff member debug info.
+    '''
+    Print out a histogram of grades on a given problem in staff member debug info.
+
+    Warning: If a student has just looked at an xmodule and not attempted
+    it, their grade is None. Since there will always be at least one such student
+    this function almost always returns [].
     '''
     from django.db import connection
     cursor = connection.cursor()
@@ -161,7 +165,7 @@ def add_staff_debug_info(user, block, view, frag, context):  # pylint: disable=u
         return frag
 
     block_id = block.id
-    if block.has_score:
+    if block.has_score and settings.FEATURES.get('DISPLAY_HISTOGRAMS_TO_STAFF'):
         histogram = grade_histogram(block_id)
         render_histogram = len(histogram) > 0
     else:
diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py
index 0f942b4d3fa..0dd527ed2b6 100644
--- a/lms/djangoapps/courseware/tests/test_module_render.py
+++ b/lms/djangoapps/courseware/tests/test_module_render.py
@@ -564,6 +564,65 @@ class TestStaffDebugInfo(ModuleStoreTestCase):
         result_fragment = module.render('student_view')
         self.assertIn('Staff Debug', result_fragment.content)
 
+    @patch.dict('django.conf.settings.FEATURES', {'DISPLAY_HISTOGRAMS_TO_STAFF': False})
+    def test_histogram_disabled(self):
+        module = render.get_module(
+            self.user,
+            self.request,
+            self.location,
+            self.field_data_cache,
+            self.course.id,
+        )
+        result_fragment = module.render('student_view')
+        self.assertNotIn('histrogram', result_fragment.content)
+
+    def test_histogram_enabled_for_unscored_xmodules(self):
+        """Histograms should not display for xmodules which are not scored."""
+
+        html_descriptor = ItemFactory.create(
+            category='html',
+            data='Here are some course details.'
+        )
+        field_data_cache = FieldDataCache.cache_for_descriptor_descendents(
+            self.course.id,
+            self.user,
+            self.descriptor
+        )
+        with patch('xmodule_modifiers.grade_histogram') as mock_grade_histogram:
+            mock_grade_histogram.return_value = []
+            module = render.get_module(
+                self.user,
+                self.request,
+                html_descriptor.location,
+                field_data_cache,
+                self.course.id,
+            )
+            module.render('student_view')
+            self.assertFalse(mock_grade_histogram.called)
+
+    def test_histogram_enabled_for_scored_xmodules(self):
+        """Histograms should display for xmodules which are scored."""
+
+        StudentModuleFactory.create(
+            course_id=self.course.id,
+            module_state_key=self.location,
+            student=UserFactory(),
+            grade=1,
+            max_grade=1,
+            state="{}",
+        )
+        with patch('xmodule_modifiers.grade_histogram') as mock_grade_histogram:
+            mock_grade_histogram.return_value = []
+            module = render.get_module(
+                self.user,
+                self.request,
+                self.location,
+                self.field_data_cache,
+                self.course.id,
+            )
+            module.render('student_view')
+            self.assertTrue(mock_grade_histogram.called)
+
 
 PER_COURSE_ANONYMIZED_DESCRIPTORS = (LTIDescriptor, )
 
diff --git a/lms/envs/common.py b/lms/envs/common.py
index d3724c68b2b..e528c884e86 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -57,6 +57,7 @@ FEATURES = {
     'USE_DJANGO_PIPELINE': True,
 
     'DISPLAY_DEBUG_INFO_TO_STAFF': True,
+    'DISPLAY_HISTOGRAMS_TO_STAFF': False,  # For large courses this slows down courseware access for staff.
 
     'REROUTE_ACTIVATION_EMAIL': False,  # nonempty string = address for all activation emails
     'DEBUG_LEVEL': 0,  # 0 = lowest level, least verbose, 255 = max level, most verbose
-- 
GitLab