diff --git a/raven/contrib/django/middleware/__init__.py b/raven/contrib/django/middleware/__init__.py index 5d3f024fb..63f7a6051 100644 --- a/raven/contrib/django/middleware/__init__.py +++ b/raven/contrib/django/middleware/__init__.py @@ -33,6 +33,18 @@ def is_ignorable_404(uri): ) +def get_grouping_fingerprint(uri): + """ + Returns the corresponding fingerprint if the given URL matches a pattern + of URLs that who should be grouped + + """ + for pattern, fingerprint in getattr(settings, 'GROUPING_404_URLS', ()): + if pattern.search(uri): + return fingerprint + return None + + class Sentry404CatchMiddleware(MiddlewareMixin): def process_response(self, request, response): if response.status_code != 404: @@ -46,14 +58,26 @@ def process_response(self, request, response): if not client.is_enabled(): return response + kwargs = {} + data = client.get_data_from_request(request) data.update({ 'level': logging.INFO, 'logger': 'http404', }) - result = client.captureMessage(message='Page Not Found: %s' % request.build_absolute_uri(), data=data) - if not result: - return + kwargs.update({ + 'data': data + }) + + fingerprint = get_grouping_fingerprint(request.get_full_path()) + if fingerprint: + kwargs.update({ + 'fingerprint': fingerprint + }) + + message = 'Page Not Found: %s' % request.build_absolute_uri() + + result = client.captureMessage(message=message, **kwargs) request.sentry = { 'project_id': data.get('project', client.remote.project), diff --git a/tests/contrib/django/tests.py b/tests/contrib/django/tests.py index 0adf7c6d1..a9ffa81fb 100644 --- a/tests/contrib/django/tests.py +++ b/tests/contrib/django/tests.py @@ -392,6 +392,36 @@ def test_404_middleware(self): assert http['query_string'] == '' assert http['data'] is None + def test_404_middleware_with_url_matching_grouping_urls(self): + extra_settings = { + 'MIDDLEWARE_CLASSES': ['raven.contrib.django.middleware.Sentry404CatchMiddleware'], + 'GROUPING_404_URLS': ((re.compile(r'^/old/(?:\d+)$'), ['FP']),) + } + + with Settings(**extra_settings): + resp = self.client.get('/old/42') + assert resp.status_code == 404 + + assert len(self.raven.events) == 1 + event = self.raven.events.pop(0) + + assert event['fingerprint'] == ['FP'] + + def test_404_middleware_with_url_not_matching_grouping_urls(self): + extra_settings = { + 'MIDDLEWARE_CLASSES': ['raven.contrib.django.middleware.Sentry404CatchMiddleware'], + 'GROUPING_404_URLS': ((re.compile(r'^/old/(?:\d+)$'), ['FP']),) + } + + with Settings(**extra_settings): + resp = self.client.get('/new/42') + assert resp.status_code == 404 + + assert len(self.raven.events) == 1 + event = self.raven.events.pop(0) + + assert 'fingerprint' not in event + def test_404_middleware_when_disabled(self): extra_settings = { 'MIDDLEWARE_CLASSES': ['raven.contrib.django.middleware.Sentry404CatchMiddleware'],