diff --git a/cms/envs/aws.py b/cms/envs/aws.py index 58fa03fea2..1ad5374744 100644 --- a/cms/envs/aws.py +++ b/cms/envs/aws.py @@ -127,6 +127,10 @@ LOGGING = get_logger_config(LOG_DIR, #theming start: PLATFORM_NAME = ENV_TOKENS.get('PLATFORM_NAME', 'edX') +# Event Tracking +if "TRACKING_IGNORE_URL_PATTERNS" in ENV_TOKENS: + TRACKING_IGNORE_URL_PATTERNS = ENV_TOKENS.get("TRACKING_IGNORE_URL_PATTERNS") + ################ SECURE AUTH ITEMS ############################### # Secret things: passwords, access keys, etc. diff --git a/cms/envs/common.py b/cms/envs/common.py index 2bab98519f..ef3c8654d4 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -404,3 +404,7 @@ TRACKING_BACKENDS = { } } } + +# We're already logging events, and we don't want to capture user +# names/passwords. Heartbeat events are likely not interesting. +TRACKING_IGNORE_URL_PATTERNS = [r'^/event', r'^/login', r'^/heartbeat'] diff --git a/common/djangoapps/track/middleware.py b/common/djangoapps/track/middleware.py index 7fc02d9969..1da051582d 100644 --- a/common/djangoapps/track/middleware.py +++ b/common/djangoapps/track/middleware.py @@ -1,14 +1,15 @@ import json +import re + +from django.conf import settings import views -class TrackMiddleware: +class TrackMiddleware(object): def process_request(self, request): try: - # We're already logging events, and we don't want to capture user - # names/passwords. - if request.META['PATH_INFO'] in ['/event', '/login']: + if not self._should_process_request(request): return # Removes passwords from the tracking logs @@ -45,3 +46,14 @@ class TrackMiddleware: views.server_track(request, request.META['PATH_INFO'], event) except: pass + + def _should_process_request(self, request): + path = request.META['PATH_INFO'] + + ignored_url_patterns = getattr(settings, 'TRACKING_IGNORE_URL_PATTERNS', []) + for pattern in ignored_url_patterns: + # Note we are explicitly relying on python's internal caching of + # compiled regular expressions here. + if re.match(pattern, path): + return False + return True diff --git a/common/djangoapps/track/tests/test_middleware.py b/common/djangoapps/track/tests/test_middleware.py new file mode 100644 index 0000000000..4bfb843634 --- /dev/null +++ b/common/djangoapps/track/tests/test_middleware.py @@ -0,0 +1,46 @@ +import re + +from mock import patch + +from django.test import TestCase +from django.test.client import RequestFactory +from django.test.utils import override_settings + +from track.middleware import TrackMiddleware + + +@patch('track.views.server_track') +class TrackMiddlewareTestCase(TestCase): + + def setUp(self): + self.track_middleware = TrackMiddleware() + self.request_factory = RequestFactory() + + def test_normal_request(self, mock_server_track): + request = self.request_factory.get('/somewhere') + self.track_middleware.process_request(request) + self.assertTrue(mock_server_track.called) + + def test_default_filters_do_not_render_view(self, mock_server_track): + for url in ['/event', '/event/1', '/login', '/heartbeat']: + request = self.request_factory.get(url) + self.track_middleware.process_request(request) + self.assertFalse(mock_server_track.called) + mock_server_track.reset_mock() + + @override_settings(TRACKING_IGNORE_URL_PATTERNS=[]) + def test_reading_filtered_urls_from_settings(self, mock_server_track): + request = self.request_factory.get('/event') + self.track_middleware.process_request(request) + self.assertTrue(mock_server_track.called) + + @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*']) + def test_anchoring_of_patterns_at_beginning(self, mock_server_track): + request = self.request_factory.get('/excluded') + self.track_middleware.process_request(request) + self.assertTrue(mock_server_track.called) + mock_server_track.reset_mock() + + request = self.request_factory.get('/some/excluded/url') + self.track_middleware.process_request(request) + self.assertFalse(mock_server_track.called) diff --git a/lms/envs/aws.py b/lms/envs/aws.py index 51af65758c..1d012e4ca0 100644 --- a/lms/envs/aws.py +++ b/lms/envs/aws.py @@ -187,6 +187,10 @@ for name, value in ENV_TOKENS.get("CODE_JAIL", {}).items(): COURSES_WITH_UNSAFE_CODE = ENV_TOKENS.get("COURSES_WITH_UNSAFE_CODE", []) +# Event Tracking +if "TRACKING_IGNORE_URL_PATTERNS" in ENV_TOKENS: + TRACKING_IGNORE_URL_PATTERNS = ENV_TOKENS.get("TRACKING_IGNORE_URL_PATTERNS") + ############################## SECURE AUTH ITEMS ############### # Secret things: passwords, access keys, etc. diff --git a/lms/envs/common.py b/lms/envs/common.py index f0997d5579..3fa1918769 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -334,6 +334,10 @@ if MITX_FEATURES.get('ENABLE_SQL_TRACKING_LOGS'): } }) +# We're already logging events, and we don't want to capture user +# names/passwords. Heartbeat events are likely not interesting. +TRACKING_IGNORE_URL_PATTERNS = [r'^/event', r'^/login', r'^/heartbeat'] + ######################## subdomain specific settings ########################### COURSE_LISTINGS = {} SUBDOMAIN_BRANDING = {}