Skip to content

Sentry doesn't capture aiohttp exception? #642

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lopatinay opened this issue Mar 5, 2020 · 6 comments
Closed

Sentry doesn't capture aiohttp exception? #642

lopatinay opened this issue Mar 5, 2020 · 6 comments

Comments

@lopatinay
Copy link

I followed an example https://docs.sentry.io/platforms/python/aiohttp/ and first thing I did

async def hello(request):
    print(1/0)

It's work fine and I got this Sentry Issue. But, when you try

async def hello(request):
    raise web_exceptions.HTTPInternalServerError  # any aiohttp exception

you won't get any Sentry Issue.
Is the only way to catch errors to use middleware?

async def errors_handler(request, handler):
    try:
        response = await handler(request)
    except web.HTTPException as e:
        capture_exception(e)
@xen
Copy link

xen commented Mar 5, 2020

I'm not sure if it helps at all. But maybe it gives some ideas for people who will work on this issue. It is possible to get an error if reraise exception again:

async def errors_handler(request, handler):
    try:
        response = await handler(request)
    except web.HTTPException as e:
        capture_exception(e)
        raise

But this is making impossible to capture error pages and publish custom error page.

@lopatinay
Copy link
Author

But, if you use this tricks you will get in Sentry "[Can't show request body due to implementation details.]". I found this solution

try:
    response = await handler(request)
except web.HTTPException as e:
    with configure_scope() as scope:
        body = await request.json()
        scope.set_extra("body", body)
    capture_exception(e)
    raise e

@untitaker
Copy link
Member

We explicitly ignore all the HTTPExceptions because otherwise you would get an event for random status codes you probably don't care about. Could one of you post an example of an actionable issue with HTTPException? We could add a config option for that

@lopatinay
Copy link
Author

lopatinay commented Mar 6, 2020

As example custom app error inherited from HTTPException. One of example:

from aiohttp.web_exceptions import HTTPServiceUnavailable

class WeatherProviderUnavailableError(HTTPServiceUnavailable):
    pass

@xen
Copy link

xen commented Mar 6, 2020

I assume that my view can end in error state. But I don't want to show user blank error page. So, I made middleware that do exactly this:

async def handle_error(request: Request, code: int = 404) -> Response:
    response = aiohttp_jinja2.render_template(f"misc/{code}.html", request, {})
    response.set_status(code)
    return response


@web.middleware
async def error_middleware(request: Request, handler: Callable) -> Union[FileResponse, Response]:
    error_codes = (403, 404, 405, 500)
    try:
        response = await handler(request)
        if response.status not in error_codes:
            # return response, everythink is ok
            return response
        # return error page because handler explicitly set different status code
        logging.info("Error: %s", response.status)
        return await handle_error(request, response.status)
    except web.HTTPException as ex:
        # this block for errors generated by aiohttp itself. 
        # I want to know that something invoke error
        # probably I will filter some error codes later
        logging.info("Error", exc_info=sys.exc_info())
        capture_exception(ex)
        if ex.status in errors:
            return await handle_error(request, code=ex.status)
        # we don't handle this error
        raise
    except Exception as ex:
        # This is place for all other Exceptions, for example ZeroDivisioinError 
        # This is most important part to capture all traceback
        logging.info("Error", exc_info=sys.exc_info())
        capture_exception(ex)
        return await handle_error(request, code=500)

What is preferred way to achieve correct error handling by Sentry?

@untitaker
Copy link
Member

Closing this issue is a question. Generally there needs to be a strong case made as to why this behavior should change. Any of the above workarounds is fine as long as it works for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants