diff --git a/contrib/opencensus-ext-django/opencensus/ext/django/middleware.py b/contrib/opencensus-ext-django/opencensus/ext/django/middleware.py index 80436f1e9..03ea9f096 100644 --- a/contrib/opencensus-ext-django/opencensus/ext/django/middleware.py +++ b/contrib/opencensus-ext-django/opencensus/ext/django/middleware.py @@ -54,6 +54,7 @@ EXCLUDELIST_PATHS = 'EXCLUDELIST_PATHS' EXCLUDELIST_HOSTNAMES = 'EXCLUDELIST_HOSTNAMES' +INCLUDE_USER_DATA = 'INCLUDE_USER_DATA' log = logging.getLogger(__name__) @@ -145,6 +146,7 @@ def _trace_db_call(execute, sql, params, many, context): class OpencensusMiddleware(MiddlewareMixin): """Saves the request in thread local""" + _is_coroutine=False def __init__(self, get_response=None): self.get_response = get_response @@ -170,6 +172,8 @@ def __init__(self, get_response=None): self.excludelist_hostnames = settings.get(EXCLUDELIST_HOSTNAMES, None) + self.include_user_data = settings.get(INCLUDE_USER_DATA, True) + if django.VERSION >= (2,): # pragma: NO COVER connection.execute_wrappers.append(_trace_db_call) @@ -267,7 +271,8 @@ def process_response(self, request, response): attribute_key=HTTP_STATUS_CODE, attribute_value=response.status_code) - _set_django_attributes(span, request) + if self.include_user_data: + _set_django_attributes(span, request) tracer = _get_current_tracer() tracer.end_span() @@ -299,6 +304,7 @@ def process_exception(self, request, exception): attribute_key=STACKTRACE, attribute_value='\n'.join(traceback.format_tb(tb))) - _set_django_attributes(span, request) + if self.include_user_data: + _set_django_attributes(span, request) except Exception: # pragma: NO COVER log.error('Failed to trace request', exc_info=True) diff --git a/contrib/opencensus-ext-django/tests/test_django_middleware.py b/contrib/opencensus-ext-django/tests/test_django_middleware.py index 522ea458c..b5127079a 100644 --- a/contrib/opencensus-ext-django/tests/test_django_middleware.py +++ b/contrib/opencensus-ext-django/tests/test_django_middleware.py @@ -236,6 +236,52 @@ def test_process_response(self): self.assertEqual(span.attributes, expected_attributes) + def test_no_user_data(self): + from opencensus.ext.django import middleware + + trace_id = '2dd43a1d6b2549c6bc2a1a54c2fc0b05' + span_id = '6e0c63257de34c92' + django_trace_id = '00-{}-{}-00'.format(trace_id, span_id) + + django_request = RequestFactory().get('/wiki/Rabbit', **{ + 'traceparent': django_trace_id, + }) + + # Force the test request to be sampled + settings = type('Test', (object,), {}) + settings.OPENCENSUS = { + 'TRACE': { + 'SAMPLER': 'opencensus.trace.samplers.AlwaysOnSampler()', # noqa + 'INCLUDE_USER_DATA': False + }, + } + patch_settings = mock.patch( + 'django.conf.settings', + settings) + + with patch_settings: + middleware_obj = middleware.OpencensusMiddleware() + + middleware_obj.process_request(django_request) + tracer = middleware._get_current_tracer() + span = tracer.current_span() + + exporter_mock = mock.Mock() + tracer.exporter = exporter_mock + + django_response = mock.Mock() + django_response.status_code = 200 + + mock_user = mock.Mock() + mock_user.pk = 123 + mock_user.get_username.return_value = 'test_name' + django_request.user = mock_user + + middleware_obj.process_response(django_request, django_response) + actual_attributes = span.attributes + self.assertNotIn('django.user.id', actual_attributes) + self.assertNotIn('django.user.name', actual_attributes) + def test_process_response_unfinished_child_span(self): from opencensus.ext.django import middleware @@ -360,6 +406,62 @@ def test_process_exception(self): self.assertEqual(span.attributes, expected_attributes) + def test_process_exception_without_user_data(self): + from opencensus.ext.django import middleware + + trace_id = '2dd43a1d6b2549c6bc2a1a54c2fc0b05' + span_id = '6e0c63257de34c92' + django_trace_id = '00-{}-{}-00'.format(trace_id, span_id) + + django_request = RequestFactory().get('/wiki/Rabbit', **{ + 'traceparent': django_trace_id, + }) + + # Force the test request to be sampled + settings = type('Test', (object,), {}) + settings.OPENCENSUS = { + 'TRACE': { + 'SAMPLER': 'opencensus.trace.samplers.AlwaysOnSampler()', # noqa + 'INCLUDE_USER_DATA': False + } + } + patch_settings = mock.patch( + 'django.conf.settings', + settings) + + with patch_settings: + middleware_obj = middleware.OpencensusMiddleware() + + tb = None + try: + raise RuntimeError("bork bork bork") + except Exception as exc: + test_exception = exc + if hasattr(exc, "__traceback__"): + tb = exc.__traceback__ + else: + _, _, tb = sys.exc_info() + + middleware_obj.process_request(django_request) + tracer = middleware._get_current_tracer() + span = tracer.current_span() + + exporter_mock = mock.Mock() + tracer.exporter = exporter_mock + + django_response = mock.Mock() + django_response.status_code = 200 + + mock_user = mock.Mock() + mock_user.pk = 123 + mock_user.get_username.return_value = 'test_name' + django_request.user = mock_user + + middleware_obj.process_exception(django_request, test_exception) + + self.assertNotIn('django.user.id', span.attributes) + self.assertNotIn('django.user.name', span.attributes) + class Test__set_django_attributes(unittest.TestCase): class Span(object):