Remember exceptions that are logged and filter out duplicates.

This fixes #724
This commit is contained in:
Armin Ronacher 2016-01-27 15:03:21 -08:00
parent 385543751f
commit 27cc40e6d5
4 changed files with 38 additions and 0 deletions

View File

@ -1,3 +1,10 @@
Version 5.10.2
--------------
* Remember exceptions in flight until the context is cleared so that two
reports with the same exception data do not result in two errors
being logged.
Version 5.10.1
--------------

View File

@ -282,6 +282,20 @@ class Client(object):
return url
return '%s:%s' % (scheme, url)
def _get_exception_key(self, exc_info):
return (
id(exc_info[1]),
id(exc_info[2]),
)
def skip_error_for_logging(self, exc_info):
key = self._get_exception_key(exc_info)
return key in self.context.exceptions_to_skip
def record_exception_seen(self, exc_info):
key = self._get_exception_key(exc_info)
self.context.exceptions_to_skip.add(key)
def build_msg(self, event_type, data=None, date=None,
time_spent=None, extra=None, stack=None, public_key=None,
tags=None, fingerprint=None, **kwargs):
@ -530,6 +544,12 @@ class Client(object):
if not self.is_enabled():
return
exc_info = kwargs.get('exc_info')
if exc_info is not None:
if self.skip_error_for_logging(exc_info):
return
self.record_exception_seen(exc_info)
data = self.build_msg(
event_type, data, date, time_spent, extra, stack, tags=tags,
**kwargs)
@ -701,6 +721,8 @@ class Client(object):
``kwargs`` are passed through to ``.capture``.
"""
if exc_info is None:
exc_info = sys.exc_info()
return self.capture(
'raven.events.Exception', exc_info=exc_info, **kwargs)

View File

@ -27,6 +27,7 @@ class Context(local, Mapping, Iterable):
"""
def __init__(self):
self.data = {}
self.exceptions_to_skip = set()
def __getitem__(self, key):
return self.data[key]
@ -58,3 +59,4 @@ class Context(local, Mapping, Iterable):
def clear(self):
self.data = {}
self.exceptions_to_skip.clear()

View File

@ -9,6 +9,7 @@ from flask.ext.login import LoginManager, AnonymousUserMixin, login_user
from raven.base import Client
from raven.contrib.flask import Sentry
from raven.utils.testutils import TestCase
from raven.handlers.logging import SentryHandler
class TempStoreClient(Client):
@ -125,6 +126,12 @@ class FlaskTest(BaseTest):
self.assertEquals(event['message'], 'ValueError: hello world')
self.assertEquals(event['culprit'], 'tests.contrib.flask.tests in an_error')
def test_capture_plus_logging(self):
client, raven, app = self.make_client_and_raven(debug=False)
app.logger.addHandler(SentryHandler(raven))
client.get('/an-error/')
assert len(raven.events) == 1
def test_get(self):
response = self.client.get('/an-error/?foo=bar')
self.assertEquals(response.status_code, 500)