Modifying flask-rest-jsonapi Exception Handling in Open Event Server to Enable Support for Sentry

In Open Event Server Project, Sentry support was enabled for the project. So first of all,

What is Sentry ?

Sentry provides open source error tracking that shows you every crash in your stack as it happens, with the details needed to prioritize, identify, reproduce, and fix each issue.

The basic error tracking can be enabled with the following two simple lines,

from raven.contrib.flask import Sentry
sentry = Sentry(app, dsn='https://<key>:<secret>@sentry.io/<project>')

 

But after sometime, it was noticed that app-related errors were not being caught in Sentry, while migration related errors were being caught. This meant that sentry was functioning properly in the app, but it was having some trouble in identifying uncaught exceptions.

After a lot of digging, it came to knowledge that the api framework, flask-rest-jsonapi caught all unknown exceptions while dispatching the request. After catching the exceptions, it gave a jsonapi error with status 500 in return. Following is the code responsible for that:

except Exception as e:
           if current_app.config['DEBUG'] is True:
               raise e
           exc = JsonApiException('', 'Unknown error')
           return make_response(json.dumps(jsonapi_errors([exc.to_dict()])),
                                exc.status,
                                headers)

 

We now had to let these exceptions go uncaught and that required us to modify the api framework. Modifications were done in the api-framework’s exception handling as shown below

if 'API_PROPOGATE_UNCAUGHT_EXCEPTIONS' in current_app.config:
               if current_app.config['API_PROPOGATE_UNCAUGHT_EXCEPTIONS'] is True:
                   raise
           if current_app.config['DEBUG'] is True:
               raise e
           exc = JsonApiException({'pointer': ''}, 'Unknown error')
           return make_response(json.dumps(jsonapi_errors([exc.to_dict()])),
                                exc.status,
                                headers)

A config parameter named API_PROPOGATE_UNCAUGHT_EXCEPTIONS was added to the config to turn this feature on or off.

But with all this done, Sentry was able to catch and report uncaught exceptions, but the json-api spec compliant error messages on an unknown error were not being returned due to this new change. So it was decided to handle these uncaught exceptions in the app itself. Flask’s default error handlers were used to tackle this situation:

@app.errorhandler(500)
def internal_server_error(error):
   exc = JsonApiException({'pointer': ''}, 'Unknown error')
   return make_response(json.dumps(jsonapi_errors([exc.to_dict()])), exc.status,
                        {'Content-Type': 'application/vnd.api+json'})

Thus, all uncaught exceptions were now returning a proper json-api spec compliant error response.

Related links:

Published by

shubham-padia

Full Stack Developer at Fossasia | Interested in software design and architecture | An Avid Potterhead <3