Skip to content

Commit

Permalink
Merge pull request #4 from mattbennett/dont-report-expected-excs
Browse files Browse the repository at this point in the history
Don't report expected exceptions
  • Loading branch information
mattbennett authored Nov 11, 2016
2 parents 4d91a46 + 8695fca commit 6d72c6d
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 146 deletions.
98 changes: 46 additions & 52 deletions nameko_sentry.py
Original file line number Diff line number Diff line change
@@ -1,84 +1,78 @@
import logging

from eventlet.queue import Queue
from nameko.extensions import DependencyProvider
from raven import Client


class SentryReporter(DependencyProvider):
""" Send exceptions generated by entrypoints to a sentry server.
"""
_gt = None
queue = None
client = None

def _run(self):

while True:
item = self.queue.get()
if item is None:
break

exc_info, message, extra, data = item
self.client.captureException(
exc_info, message=message, extra=extra, data=data)

# these will remain in scope until the next iteration and
# can potentially be large, so delete to reclaim the memory now
del exc_info, message, extra, data, item

def start(self):
self._gt = self.container.spawn_managed_thread(
self._run, protected=True)

def stop(self):
self.queue.put(None)

if self._gt is not None:
self._gt.wait()

def setup(self):
sentry_config = self.container.config.get('SENTRY')

dsn = sentry_config['DSN']
kwargs = sentry_config.get('CLIENT_CONFIG', {})
report_expected_exceptions = sentry_config.get(
'REPORT_EXPECTED_EXCEPTIONS', True
)

self.queue = Queue()
self.client = Client(dsn, **kwargs)
self.report_expected_exceptions = report_expected_exceptions

def format_message(self, worker_ctx, exc_info):
exc_type, exc, _ = exc_info
return (
'Unhandled exception in call {}: '
'{} {!r}'.format(worker_ctx.call_id, exc_type.__name__, str(exc))
)

def is_expected_exception(self, worker_ctx, exc_info):
_, exc, _ = exc_info
expected_exceptions = getattr(
worker_ctx.entrypoint, 'expected_exceptions', tuple())
return isinstance(exc, expected_exceptions)

def build_tags(self, worker_ctx, exc_info):
return {
'call_id': worker_ctx.call_id,
'parent_call_id': worker_ctx.immediate_parent_call_id,
}

def build_extra(self, worker_ctx, exc_info):
_, exc, _ = exc_info
return {
'exc': exc
}

def worker_result(self, worker_ctx, result, exc_info):
if exc_info is None:
return
self.capture_exception(worker_ctx, exc_info)

exc = exc_info[1]
call_id = worker_ctx.call_id
parent_call_id = worker_ctx.immediate_parent_call_id
def capture_exception(self, worker_ctx, exc_info):

expected_exceptions = getattr(
worker_ctx.entrypoint, 'expected_exceptions', tuple())
logger = '{}.{}'.format(
worker_ctx.service_name, worker_ctx.entrypoint.method_name
)

level = logging.ERROR
if expected_exceptions and isinstance(exc, expected_exceptions):
if self.is_expected_exception(worker_ctx, exc_info):
if not self.report_expected_exceptions:
return # nothing to do
level = logging.WARNING
else:
level = logging.ERROR

message = (
'Unhandled exception in call {}: '
'{} {!r}'.format(call_id, exc_info[0].__name__, str(exc))
)

logger = '{}.{}'.format(
worker_ctx.service_name, worker_ctx.entrypoint.method_name)
message = self.format_message(worker_ctx, exc_info)
extra = self.build_extra(worker_ctx, exc_info)
tags = self.build_tags(worker_ctx, exc_info)

data = {
'logger': logger,
'level': level,
'message': message,
'tags': {
'call_id': call_id,
'parent_call_id': parent_call_id,
},
'tags': tags
}

extra = {'exc': exc}

self.queue.put((exc_info, message, extra, data))
self.client.captureException(
exc_info, message=message, extra=extra, data=data
)
Loading

0 comments on commit 6d72c6d

Please sign in to comment.