EastSw
EastSw

Reputation: 1067

Capturing Apscedular job exceptions to Sentry

I'm using apscheduler to process few things in background.

I'd like to capture and report possible exceptions to Sentry. My code looks like this:

sentry = Client(dsn=SENTRY_DSN)

def sample_method():
     # some processing..

     raise ConnectionError

def listen_to_exceptions(event):
    if event.exception:
        # I was hoping raven will capture the exception using  sys.exc_info(), but it's not
        sentry.captureException()


scheduler = BlockingScheduler()

scheduler.add_listener(listen_to_exceptions, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)

scheduler.add_job(sample_method, 'interval', minutes=5, max_instances=1)

# run forever!!!
scheduler.start()

But instead capturing the exception, it generates more exceptions trying to report it to Sentry.

ConnectionError
Error notifying listener
Traceback (most recent call last):
  File "/.../venv/lib/python3.6/site-packages/apscheduler/schedulers/base.py", line 825, in _dispatch_event
    cb(event)
  File "app.py", line 114, in listen_to_exceptions
    sentry.captureException(event.exception)
  File "/.../venv/lib/python3.6/site-packages/raven/base.py", line 814, in captureException
    'raven.events.Exception', exc_info=exc_info, **kwargs)
  File "/.../venv/lib/python3.6/site-packages/raven/base.py", line 623, in capture
    if self.skip_error_for_logging(exc_info):
  File "/.../venv/lib/python3.6/site-packages/raven/base.py", line 358, in skip_error_for_logging
    key = self._get_exception_key(exc_info)
  File "/.../venv/lib/python3.6/site-packages/raven/base.py", line 345, in _get_exception_key
    code_id = id(exc_info[2] and exc_info[2].tb_frame.f_code)
TypeError: 'ConnectionError' object is not subscriptable

I'm trying to use event listener according to the docs. Is there another way to capture exceptions in executed jobs?

Of course I could add try except blocks to each job function. I'm just trying to understand if there's a way to do it with apscedular, because I've 20+ jobs and adding sentry.captureException() every where seems like repetition.

Upvotes: 0

Views: 1794

Answers (2)

Michael
Michael

Reputation: 721

The documentation has been updated. So you have to do it the following way:

from sentry_sdk import capture_exception
....
def sentry_listener(event):
    if event.exception:
        capture_exception(event.exception)

scheduler.add_listener(sentry_listener, EVENT_JOB_ERROR)

Upvotes: 3

Alex Grönholm
Alex Grönholm

Reputation: 5901

You only need to capture EVENT_JOB_ERROR. Also, sentry.captureException() requires an exc_info tuple as its argument, not the exception object. The following will work on Python 3:

def listen_to_exceptions(event):
    exc_info = type(event.exception), event.exception, event.exception.__traceback__
    sentry.captureException(exc_info)

scheduler.add_listener(listen_to_exceptions, EVENT_JOB_ERROR)

Upvotes: 3

Related Questions