Skip to content
This repository has been archived by the owner on Oct 23, 2023. It is now read-only.

[django] fix shared request not being available in thread context #958

Merged
merged 1 commit into from Feb 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions raven/contrib/django/client.py
Expand Up @@ -27,7 +27,7 @@

from raven.base import Client
from raven.contrib.django.utils import get_data_from_template, get_host
from raven.contrib.django.middleware import SentryLogMiddleware
from raven.contrib.django.middleware import SentryMiddleware
from raven.utils.compat import string_types, binary_type, iterlists
from raven.contrib.django.resolver import RouteResolver
from raven.utils.wsgi import get_headers, get_environ
Expand Down Expand Up @@ -263,7 +263,7 @@ def capture(self, event_type, request=None, **kwargs):
data = kwargs['data']

if request is None:
request = getattr(SentryLogMiddleware.thread, 'request', None)
request = getattr(SentryMiddleware.thread, 'request', None)

is_http_request = isinstance(request, HttpRequest)
if is_http_request:
Expand Down
19 changes: 3 additions & 16 deletions raven/contrib/django/middleware/__init__.py
Expand Up @@ -76,25 +76,12 @@ def process_response(self, request, response):
return response


# We need to make a base class for our sentry middleware that is thread
# local but at the same time has the new fnagled middleware mixin applied
# if such a thing exists.
if MiddlewareMixin is object:
_SentryMiddlewareBase = threading.local
else:
_SentryMiddlewareBase = type('_SentryMiddlewareBase', (MiddlewareMixin, threading.local), {})


class SentryMiddleware(_SentryMiddlewareBase):

# backwards compat
@property
def thread(self):
return self
class SentryMiddleware(MiddlewareMixin):
thread = threading.local()

def process_request(self, request):
self._txid = None
self.thread.request = request
SentryMiddleware.thread.request = request

def process_view(self, request, func, args, kwargs):
from raven.contrib.django.models import client
Expand Down
16 changes: 15 additions & 1 deletion tests/contrib/django/tests.py
Expand Up @@ -163,7 +163,8 @@ def test_signal_integration(self):

@pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason='Python 2.6')
def test_view_exception(self):
self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc'))
path = reverse('sentry-raise-exc')
self.assertRaises(Exception, self.client.get, path)

assert len(self.raven.events) == 1
event = self.raven.events.pop(0)
Expand All @@ -173,6 +174,19 @@ def test_view_exception(self):
assert exc['value'] == 'view exception'
assert event['level'] == logging.ERROR
assert event['message'] == 'Exception: view exception'
assert 'request' in event
assert event['request']['url'] == 'http://testserver{}'.format(path)

def test_capture_event_with_request_middleware(self):
path = reverse('sentry-trigger-event')
resp = self.client.get(path)
assert resp.status_code == 200

assert len(self.raven.events) == 1
event = self.raven.events.pop(0)
assert event['message'] == 'test'
assert 'request' in event
assert event['request']['url'] == 'http://testserver{}'.format(path)

def test_user_info(self):
with Settings(MIDDLEWARE_CLASSES=[
Expand Down
1 change: 1 addition & 0 deletions tests/contrib/django/urls.py
Expand Up @@ -30,4 +30,5 @@ def handler500(request):
url(r'^trigger-500-django$', tests.contrib.django.views.django_exc, name='sentry-django-exc'),
url(r'^trigger-500-template$', tests.contrib.django.views.template_exc, name='sentry-template-exc'),
url(r'^trigger-500-log-request$', tests.contrib.django.views.logging_request_exc, name='sentry-log-request-exc'),
url(r'^trigger-event$', tests.contrib.django.views.capture_event, name='sentry-trigger-event'),
)
14 changes: 14 additions & 0 deletions tests/contrib/django/views.py
Expand Up @@ -2,34 +2,48 @@

from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render_to_response
from raven.contrib.django.models import client

import logging


def no_error(request):
return HttpResponse('')


def fake_login(request):
return HttpResponse('')


def django_exc(request):
return get_object_or_404(Exception, pk=1)


def raise_exc(request):
raise Exception(request.GET.get('message', 'view exception'))


def raise_ioerror(request):
raise IOError(request.GET.get('message', 'view exception'))


def decorated_raise_exc(request):
return raise_exc(request)


def template_exc(request):
return render_to_response('error.html')


def logging_request_exc(request):
logger = logging.getLogger(__name__)
try:
raise Exception(request.GET.get('message', 'view exception'))
except Exception as e:
logger.error(e, exc_info=True, extra={'request': request})
return HttpResponse('')


def capture_event(request):
client.captureMessage('test')
return HttpResponse('')