Skip to content

Commit

Permalink
Merge pull request getsentry#958 from getsentry/fix/django-request
Browse files Browse the repository at this point in the history
[django] fix shared request not being available in thread context
  • Loading branch information
dcramer authored Feb 15, 2017
2 parents 17b823d + 3991bec commit a8dc4a2
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 19 deletions.
4 changes: 2 additions & 2 deletions raven/contrib/django/client.py
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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('')

0 comments on commit a8dc4a2

Please sign in to comment.