diff --git a/openedx/core/lib/request_utils.py b/openedx/core/lib/request_utils.py index 33901f5d68f9..8de5af8526fc 100644 --- a/openedx/core/lib/request_utils.py +++ b/openedx/core/lib/request_utils.py @@ -23,9 +23,9 @@ # .. toggle_name: request_utils.capture_cookie_sizes # .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: Enables capturing of cookie sizes for monitoring purposes. This can be useful for tracking -# down large cookies and avoiding hitting limits on the total size of cookies. See the CookieMonitoringMiddleware -# docstring for details on the monitoring custom attributes that will be set. +# .. toggle_description: Enables more detailed capturing of cookie sizes for monitoring purposes. This can be useful for tracking +# down large cookies if requests are nearing limits on the total size of cookies. See the +# CookieMonitoringMiddleware docstring for details on the monitoring custom attributes that will be set. # .. toggle_warnings: Enabling this flag will add a number of custom attributes, and could adversely affect other # monitoring. Only enable temporarily, or lower TOP_N_COOKIES_CAPTURED and TOP_N_COOKIE_GROUPS_CAPTURED django # settings to capture less data. @@ -123,6 +123,10 @@ def process_request(self, request): Attributes that are added by this middleware: + cookies.header.size: The total size in bytes of the cookie header + + If CAPTURE_COOKIE_SIZES is enabled, additional attributes will be added: + cookies..name: The name of the Nth largest cookie cookies..size: The size of the Nth largest cookie cookies..group..name: The name of the Nth largest cookie. @@ -141,6 +145,10 @@ def process_request(self, request): - TOP_N_COOKIE_GROUPS_CAPTURED """ + + raw_header_cookie = request.META.get('HTTP_COOKIE', '') + set_custom_attribute('cookies.header.size', len(raw_header_cookie.encode('utf-8'))) + if not CAPTURE_COOKIE_SIZES.is_enabled(): return diff --git a/openedx/core/lib/tests/test_request_utils.py b/openedx/core/lib/tests/test_request_utils.py index 5bc10c29e86d..e9d2e2bec253 100644 --- a/openedx/core/lib/tests/test_request_utils.py +++ b/openedx/core/lib/tests/test_request_utils.py @@ -97,6 +97,24 @@ def assertCourseIdFieldsMatch(self, course_id, org, course, run): assert course_id.course == course assert course_id.run == run + @patch("openedx.core.lib.request_utils.CAPTURE_COOKIE_SIZES") + @patch("openedx.core.lib.request_utils.set_custom_attribute") + def test_basic_cookie_monitoring(self, mock_set_custom_attribute, mock_capture_cookie_sizes): + mock_capture_cookie_sizes.is_enabled.return_value = False + middleware = CookieMonitoringMiddleware() + + cookies_dict = {'a': 'b'} + + factory = RequestFactory() + for name, value in cookies_dict.items(): + factory.cookies[name] = value + + mock_request = factory.request() + + middleware.process_request(mock_request) + + mock_set_custom_attribute.assert_called_once_with('cookies.header.size', 3) + @patch("openedx.core.lib.request_utils.CAPTURE_COOKIE_SIZES") @patch("openedx.core.lib.request_utils.set_custom_attribute") def test_cookie_monitoring(self, mock_set_custom_attribute, mock_capture_cookie_sizes): @@ -104,8 +122,7 @@ def test_cookie_monitoring(self, mock_set_custom_attribute, mock_capture_cookie_ mock_capture_cookie_sizes.is_enabled.return_value = True middleware = CookieMonitoringMiddleware() - mock_request = Mock() - mock_request.COOKIES = { + cookies_dict = { "a": "." * 100, "_b": "." * 13, "_c_": "." * 13, @@ -117,6 +134,12 @@ def test_cookie_monitoring(self, mock_set_custom_attribute, mock_capture_cookie_ "d": "." * 3, } + factory = RequestFactory() + for name, value in cookies_dict.items(): + factory.cookies[name] = value + + mock_request = factory.request() + middleware.process_request(mock_request) mock_set_custom_attribute.assert_has_calls([ @@ -147,6 +170,7 @@ def test_cookie_monitoring(self, mock_set_custom_attribute, mock_capture_cookie_ call('cookies_total_size', 192), call('cookies_unaccounted_size', 3), call('cookies_total_num', 9), + call('cookies.header.size', 238) ], any_order=True) @patch("openedx.core.lib.request_utils.CAPTURE_COOKIE_SIZES") @@ -156,13 +180,18 @@ def test_cookie_monitoring_max_group(self, mock_set_custom_attribute, mock_captu mock_capture_cookie_sizes.is_enabled.return_value = True middleware = CookieMonitoringMiddleware() - mock_request = Mock() - mock_request.COOKIES = { + cookies_dict = { "a": "." * 10, "b_a": "." * 15, "b_c": "." * 20, } + factory = RequestFactory() + for name, value in cookies_dict.items(): + factory.cookies[name] = value + + mock_request = factory.request() + middleware.process_request(mock_request) mock_set_custom_attribute.assert_has_calls([ @@ -188,12 +217,20 @@ def test_cookie_monitoring_no_cookies(self, mock_set_custom_attribute, mock_capt mock_capture_cookie_sizes.is_enabled.return_value = True middleware = CookieMonitoringMiddleware() - mock_request = Mock() - mock_request.COOKIES = {} + cookies_dict = {} + + factory = RequestFactory() + for name, value in cookies_dict.items(): + factory.cookies[name] = value + + mock_request = factory.request() middleware.process_request(mock_request) - mock_set_custom_attribute.assert_has_calls([call('cookies_total_size', 0)], any_order=True) + mock_set_custom_attribute.assert_has_calls([ + call('cookies_total_size', 0), + call('cookies.header.size', 0) + ], any_order=True) @patch("openedx.core.lib.request_utils.CAPTURE_COOKIE_SIZES") @patch("openedx.core.lib.request_utils.set_custom_attribute") @@ -202,12 +239,17 @@ def test_cookie_monitoring_no_groups(self, mock_set_custom_attribute, mock_captu mock_capture_cookie_sizes.is_enabled.return_value = True middleware = CookieMonitoringMiddleware() - mock_request = Mock() - mock_request.COOKIES = { + cookies_dict = { "a": "." * 10, "b": "." * 15, } + factory = RequestFactory() + for name, value in cookies_dict.items(): + factory.cookies[name] = value + + mock_request = factory.request() + middleware.process_request(mock_request) mock_set_custom_attribute.assert_has_calls([