From 07801f3b9674ae23a6c3b6e061c5604499d2d36e Mon Sep 17 00:00:00 2001 From: Nimisha Asthagiri <nasthagiri@edx.org> Date: Thu, 6 Oct 2016 23:38:32 -0400 Subject: [PATCH] Move performance from common to openedx/core --- common/djangoapps/performance/__init__.py | 0 common/djangoapps/performance/tests/__init__.py | 0 common/djangoapps/performance/tests/test_logs.py | 132 ------------------------------------------------------------------------------------------------------------------------------------ common/djangoapps/performance/views/__init__.py | 54 ------------------------------------------------------ lms/urls.py | 2 +- openedx/core/djangoapps/performance/__init__.py | 0 openedx/core/djangoapps/performance/tests/__init__.py | 0 openedx/core/djangoapps/performance/tests/test_logs.py | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ openedx/core/djangoapps/performance/views/__init__.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 193 insertions(+), 187 deletions(-) delete mode 100644 common/djangoapps/performance/__init__.py delete mode 100644 common/djangoapps/performance/tests/__init__.py delete mode 100644 common/djangoapps/performance/tests/test_logs.py delete mode 100644 common/djangoapps/performance/views/__init__.py create mode 100644 openedx/core/djangoapps/performance/__init__.py create mode 100644 openedx/core/djangoapps/performance/tests/__init__.py create mode 100644 openedx/core/djangoapps/performance/tests/test_logs.py create mode 100644 openedx/core/djangoapps/performance/views/__init__.py diff --git a/common/djangoapps/performance/__init__.py b/common/djangoapps/performance/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/common/djangoapps/performance/__init__.py +++ /dev/null diff --git a/common/djangoapps/performance/tests/__init__.py b/common/djangoapps/performance/tests/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/common/djangoapps/performance/tests/__init__.py +++ /dev/null diff --git a/common/djangoapps/performance/tests/test_logs.py b/common/djangoapps/performance/tests/test_logs.py deleted file mode 100644 index 0b2b365..0000000 --- a/common/djangoapps/performance/tests/test_logs.py +++ /dev/null @@ -1,132 +0,0 @@ -"""Tests that performance data is successfully logged.""" -import datetime -import dateutil -import json - -import logging -from StringIO import StringIO - -from django.test import TestCase -from django.test.client import RequestFactory -from performance.views import performance_log - - -class PerformanceTrackingTest(TestCase): - """ - Tests that performance logs correctly handle events - """ - - def setUp(self): - super(PerformanceTrackingTest, self).setUp() - self.request_factory = RequestFactory() - self.stream = StringIO() - self.handler = logging.StreamHandler(self.stream) - self.log = logging.getLogger() - self.log.setLevel(logging.INFO) - for handler in self.log.handlers: - self.log.removeHandler(handler) - self.log.addHandler(self.handler) - self.addCleanup(self.log.removeHandler, self.handler) - self.addCleanup(self.handler.close) - - def test_empty_get(self): - request = self.request_factory.get('/performance') - pre_time = datetime.datetime.utcnow() - performance_log(request) - post_time = datetime.datetime.utcnow() - self.handler.flush() - logged_value = json.loads(self.stream.getvalue().strip()) - self.assertEqual(logged_value['accept_language'], '') - self.assertEqual(logged_value['agent'], '') - self.assertEqual(logged_value['event'], '') - self.assertEqual(logged_value['event_source'], 'browser') - self.assertEqual(logged_value['expgroup'], '') - self.assertEqual(logged_value['id'], '') - self.assertEqual(logged_value['page'], '') - self.assertEqual(logged_value['referer'], '') - self.assertEqual(logged_value['value'], '') - logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) - self.assertLessEqual(pre_time, logged_time) - self.assertGreaterEqual(post_time, logged_time) - - def test_empty_post(self): - request = self.request_factory.post('/performance') - pre_time = datetime.datetime.utcnow() - performance_log(request) - post_time = datetime.datetime.utcnow() - self.handler.flush() - logged_value = json.loads(self.stream.getvalue().strip()) - self.assertEqual(logged_value['accept_language'], '') - self.assertEqual(logged_value['agent'], '') - self.assertEqual(logged_value['event'], '') - self.assertEqual(logged_value['event_source'], 'browser') - self.assertEqual(logged_value['expgroup'], '') - self.assertEqual(logged_value['id'], '') - self.assertEqual(logged_value['page'], '') - self.assertEqual(logged_value['referer'], '') - self.assertEqual(logged_value['value'], '') - logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) - self.assertLessEqual(pre_time, logged_time) - self.assertGreaterEqual(post_time, logged_time) - - def test_populated_get(self): - request = self.request_factory.get('/performance', - {'event': "a_great_event", - 'id': "12345012345", - 'expgroup': "17", 'page': "atestpage", - 'value': "100234"}) - request.META['HTTP_ACCEPT_LANGUAGE'] = "en" - request.META['HTTP_REFERER'] = "https://www.edx.org/evilpage" - request.META['HTTP_USER_AGENT'] = "Mozilla/5.0" - request.META['REMOTE_ADDR'] = "18.19.20.21" - request.META['SERVER_NAME'] = "some-aws-server" - pre_time = datetime.datetime.utcnow() - performance_log(request) - post_time = datetime.datetime.utcnow() - self.handler.flush() - logged_value = json.loads(self.stream.getvalue().strip()) - self.assertEqual(logged_value['accept_language'], 'en') - self.assertEqual(logged_value['agent'], 'Mozilla/5.0') - self.assertEqual(logged_value['event'], 'a_great_event') - self.assertEqual(logged_value['event_source'], 'browser') - self.assertEqual(logged_value['expgroup'], '17') - self.assertEqual(logged_value['host'], 'some-aws-server') - self.assertEqual(logged_value['id'], '12345012345') - self.assertEqual(logged_value['ip'], '18.19.20.21') - self.assertEqual(logged_value['page'], 'atestpage') - self.assertEqual(logged_value['referer'], 'https://www.edx.org/evilpage') - self.assertEqual(logged_value['value'], '100234') - logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) - self.assertLessEqual(pre_time, logged_time) - self.assertGreaterEqual(post_time, logged_time) - - def test_populated_post(self): - request = self.request_factory.post('/performance', - {'event': "a_great_event", - 'id': "12345012345", - 'expgroup': "17", 'page': "atestpage", - 'value': "100234"}) - request.META['HTTP_ACCEPT_LANGUAGE'] = "en" - request.META['HTTP_REFERER'] = "https://www.edx.org/evilpage" - request.META['HTTP_USER_AGENT'] = "Mozilla/5.0" - request.META['REMOTE_ADDR'] = "18.19.20.21" - request.META['SERVER_NAME'] = "some-aws-server" - pre_time = datetime.datetime.utcnow() - performance_log(request) - post_time = datetime.datetime.utcnow() - self.handler.flush() - logged_value = json.loads(self.stream.getvalue().strip()) - self.assertEqual(logged_value['accept_language'], 'en') - self.assertEqual(logged_value['agent'], 'Mozilla/5.0') - self.assertEqual(logged_value['event'], 'a_great_event') - self.assertEqual(logged_value['event_source'], 'browser') - self.assertEqual(logged_value['expgroup'], '17') - self.assertEqual(logged_value['host'], 'some-aws-server') - self.assertEqual(logged_value['id'], '12345012345') - self.assertEqual(logged_value['ip'], '18.19.20.21') - self.assertEqual(logged_value['page'], 'atestpage') - self.assertEqual(logged_value['referer'], 'https://www.edx.org/evilpage') - self.assertEqual(logged_value['value'], '100234') - logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) - self.assertLessEqual(pre_time, logged_time) - self.assertGreaterEqual(post_time, logged_time) diff --git a/common/djangoapps/performance/views/__init__.py b/common/djangoapps/performance/views/__init__.py deleted file mode 100644 index 78fe4e3..0000000 --- a/common/djangoapps/performance/views/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -import datetime -import json -import logging - -from django.http import HttpResponse - -from track.utils import DateTimeJSONEncoder - - -perflog = logging.getLogger("perflog") - - -def _get_request_header(request, header_name, default=''): - """Helper method to get header values from a request's META dict, if present.""" - if request is not None and hasattr(request, 'META') and header_name in request.META: - return request.META[header_name] - else: - return default - - -def _get_request_value(request, value_name, default=''): - """Helper method to get header values from a request's GET or POST dicts, if present.""" - if request is not None and hasattr(request, 'GET') and value_name in request.GET: - return request.GET[value_name] - elif request is not None and hasattr(request, 'POST') and value_name in request.POST: - return request.POST[value_name] - else: - return default - - -def performance_log(request): - """ - Log when POST call to "performance" URL is made by a user. - Request should provide "event" and "page" arguments. - """ - - event = { - "ip": _get_request_header(request, 'REMOTE_ADDR'), - "referer": _get_request_header(request, 'HTTP_REFERER'), - "accept_language": _get_request_header(request, 'HTTP_ACCEPT_LANGUAGE'), - "event_source": "browser", - "event": _get_request_value(request, 'event'), - "agent": _get_request_header(request, 'HTTP_USER_AGENT'), - "page": _get_request_value(request, 'page'), - "id": _get_request_value(request, 'id'), - "expgroup": _get_request_value(request, 'expgroup'), - "value": _get_request_value(request, 'value'), - "time": datetime.datetime.utcnow(), - "host": _get_request_header(request, 'SERVER_NAME'), - } - - perflog.info(json.dumps(event, cls=DateTimeJSONEncoder)) - - return HttpResponse(status=204) diff --git a/lms/urls.py b/lms/urls.py index 9691bc7..d3de089 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -33,7 +33,7 @@ urlpatterns = ( url(r'^email_confirm/(?P<key>[^/]*)$', 'student.views.confirm_email_change'), url(r'^event$', 'track.views.user_track'), - url(r'^performance$', 'performance.views.performance_log'), + url(r'^performance$', 'openedx.core.djangoapps.performance.views.performance_log'), url(r'^segmentio/event$', 'track.views.segmentio.segmentio_event'), # TODO: Is this used anymore? What is STATIC_GRAB? diff --git a/openedx/core/djangoapps/performance/__init__.py b/openedx/core/djangoapps/performance/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/openedx/core/djangoapps/performance/__init__.py diff --git a/openedx/core/djangoapps/performance/tests/__init__.py b/openedx/core/djangoapps/performance/tests/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/openedx/core/djangoapps/performance/tests/__init__.py diff --git a/openedx/core/djangoapps/performance/tests/test_logs.py b/openedx/core/djangoapps/performance/tests/test_logs.py new file mode 100644 index 0000000..f53938a --- /dev/null +++ b/openedx/core/djangoapps/performance/tests/test_logs.py @@ -0,0 +1,135 @@ +# pylint: disable=no-member +""" +Tests that performance data is successfully logged. +""" +import datetime +import dateutil +import json + +import logging +from StringIO import StringIO + +from django.test import TestCase +from django.test.client import RequestFactory +from openedx.core.djangoapps.performance.views import performance_log + + +class PerformanceTrackingTest(TestCase): + """ + Tests that performance logs correctly handle events + """ + + def setUp(self): + super(PerformanceTrackingTest, self).setUp() + self.request_factory = RequestFactory() + self.stream = StringIO() + self.handler = logging.StreamHandler(self.stream) + self.log = logging.getLogger() + self.log.setLevel(logging.INFO) + for handler in self.log.handlers: + self.log.removeHandler(handler) + self.log.addHandler(self.handler) + self.addCleanup(self.log.removeHandler, self.handler) + self.addCleanup(self.handler.close) + + def test_empty_get(self): + request = self.request_factory.get('/performance') + pre_time = datetime.datetime.utcnow() + performance_log(request) + post_time = datetime.datetime.utcnow() + self.handler.flush() + logged_value = json.loads(self.stream.getvalue().strip()) + self.assertEqual(logged_value['accept_language'], '') + self.assertEqual(logged_value['agent'], '') + self.assertEqual(logged_value['event'], '') + self.assertEqual(logged_value['event_source'], 'browser') + self.assertEqual(logged_value['expgroup'], '') + self.assertEqual(logged_value['id'], '') + self.assertEqual(logged_value['page'], '') + self.assertEqual(logged_value['referer'], '') + self.assertEqual(logged_value['value'], '') + logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) + self.assertLessEqual(pre_time, logged_time) + self.assertGreaterEqual(post_time, logged_time) + + def test_empty_post(self): + request = self.request_factory.post('/performance') + pre_time = datetime.datetime.utcnow() + performance_log(request) + post_time = datetime.datetime.utcnow() + self.handler.flush() + logged_value = json.loads(self.stream.getvalue().strip()) + self.assertEqual(logged_value['accept_language'], '') + self.assertEqual(logged_value['agent'], '') + self.assertEqual(logged_value['event'], '') + self.assertEqual(logged_value['event_source'], 'browser') + self.assertEqual(logged_value['expgroup'], '') + self.assertEqual(logged_value['id'], '') + self.assertEqual(logged_value['page'], '') + self.assertEqual(logged_value['referer'], '') + self.assertEqual(logged_value['value'], '') + logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) + self.assertLessEqual(pre_time, logged_time) + self.assertGreaterEqual(post_time, logged_time) + + def test_populated_get(self): + request = self.request_factory.get('/performance', + {'event': "a_great_event", + 'id': "12345012345", + 'expgroup': "17", 'page': "atestpage", + 'value': "100234"}) + request.META['HTTP_ACCEPT_LANGUAGE'] = "en" + request.META['HTTP_REFERER'] = "https://www.edx.org/evilpage" + request.META['HTTP_USER_AGENT'] = "Mozilla/5.0" + request.META['REMOTE_ADDR'] = "18.19.20.21" + request.META['SERVER_NAME'] = "some-aws-server" + pre_time = datetime.datetime.utcnow() + performance_log(request) + post_time = datetime.datetime.utcnow() + self.handler.flush() + logged_value = json.loads(self.stream.getvalue().strip()) + self.assertEqual(logged_value['accept_language'], 'en') + self.assertEqual(logged_value['agent'], 'Mozilla/5.0') + self.assertEqual(logged_value['event'], 'a_great_event') + self.assertEqual(logged_value['event_source'], 'browser') + self.assertEqual(logged_value['expgroup'], '17') + self.assertEqual(logged_value['host'], 'some-aws-server') + self.assertEqual(logged_value['id'], '12345012345') + self.assertEqual(logged_value['ip'], '18.19.20.21') + self.assertEqual(logged_value['page'], 'atestpage') + self.assertEqual(logged_value['referer'], 'https://www.edx.org/evilpage') + self.assertEqual(logged_value['value'], '100234') + logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) + self.assertLessEqual(pre_time, logged_time) + self.assertGreaterEqual(post_time, logged_time) + + def test_populated_post(self): + request = self.request_factory.post('/performance', + {'event': "a_great_event", + 'id': "12345012345", + 'expgroup': "17", 'page': "atestpage", + 'value': "100234"}) + request.META['HTTP_ACCEPT_LANGUAGE'] = "en" + request.META['HTTP_REFERER'] = "https://www.edx.org/evilpage" + request.META['HTTP_USER_AGENT'] = "Mozilla/5.0" + request.META['REMOTE_ADDR'] = "18.19.20.21" + request.META['SERVER_NAME'] = "some-aws-server" + pre_time = datetime.datetime.utcnow() + performance_log(request) + post_time = datetime.datetime.utcnow() + self.handler.flush() + logged_value = json.loads(self.stream.getvalue().strip()) + self.assertEqual(logged_value['accept_language'], 'en') + self.assertEqual(logged_value['agent'], 'Mozilla/5.0') + self.assertEqual(logged_value['event'], 'a_great_event') + self.assertEqual(logged_value['event_source'], 'browser') + self.assertEqual(logged_value['expgroup'], '17') + self.assertEqual(logged_value['host'], 'some-aws-server') + self.assertEqual(logged_value['id'], '12345012345') + self.assertEqual(logged_value['ip'], '18.19.20.21') + self.assertEqual(logged_value['page'], 'atestpage') + self.assertEqual(logged_value['referer'], 'https://www.edx.org/evilpage') + self.assertEqual(logged_value['value'], '100234') + logged_time = dateutil.parser.parse(logged_value['time']).replace(tzinfo=None) + self.assertLessEqual(pre_time, logged_time) + self.assertGreaterEqual(post_time, logged_time) diff --git a/openedx/core/djangoapps/performance/views/__init__.py b/openedx/core/djangoapps/performance/views/__init__.py new file mode 100644 index 0000000..f82bd24 --- /dev/null +++ b/openedx/core/djangoapps/performance/views/__init__.py @@ -0,0 +1,57 @@ +""" +Views for logging performance data. +""" +import datetime +import json +import logging + +from django.http import HttpResponse + +from track.utils import DateTimeJSONEncoder + + +log = logging.getLogger("perflog") + + +def _get_request_header(request, header_name, default=''): + """Helper method to get header values from a request's META dict, if present.""" + if request is not None and hasattr(request, 'META') and header_name in request.META: + return request.META[header_name] + else: + return default + + +def _get_request_value(request, value_name, default=''): + """Helper method to get header values from a request's GET or POST dicts, if present.""" + if request is not None and hasattr(request, 'GET') and value_name in request.GET: + return request.GET[value_name] + elif request is not None and hasattr(request, 'POST') and value_name in request.POST: + return request.POST[value_name] + else: + return default + + +def performance_log(request): + """ + Log when POST call to "performance" URL is made by a user. + Request should provide "event" and "page" arguments. + """ + + event = { + "ip": _get_request_header(request, 'REMOTE_ADDR'), + "referer": _get_request_header(request, 'HTTP_REFERER'), + "accept_language": _get_request_header(request, 'HTTP_ACCEPT_LANGUAGE'), + "event_source": "browser", + "event": _get_request_value(request, 'event'), + "agent": _get_request_header(request, 'HTTP_USER_AGENT'), + "page": _get_request_value(request, 'page'), + "id": _get_request_value(request, 'id'), + "expgroup": _get_request_value(request, 'expgroup'), + "value": _get_request_value(request, 'value'), + "time": datetime.datetime.utcnow(), + "host": _get_request_header(request, 'SERVER_NAME'), + } + + log.info(json.dumps(event, cls=DateTimeJSONEncoder)) + + return HttpResponse(status=204) -- libgit2 0.26.0