sentry-python icon indicating copy to clipboard operation
sentry-python copied to clipboard

Statically initialized StrawberryIntegration leads to runtime exception: There is no current event loop in thread

Open Speedy1991 opened this issue 1 year ago • 3 comments

How do you use Sentry?

Self-hosted/on-premise

Version

2.5.1

Steps to Reproduce

I use a mixed app with starlette and django where the starlette router resolves the route into a starlette websocket (async) or a django app (sync). The problem is, that the strawberry extensions guess the async scope here. So I get an async middleware in my sync stack if a query is executed. As far I can see from the codebase I can't opt out this behaviour, because it is added via the default integrations here.

I guess there is a general design problem with the strawberry integration. E.g. the DjangoIntegration does not require to specify the async_execution like the StrawberryIntegration does here. The DjangoIntegration request is evaluated while runtime.

FYI & Ping @patrick91

Expected Result

depending on the request the sync or async resolver is called. Currently, this is statically injected on integration creation (or default integration injection)

Actual Result

An async middleware is added to a wsgi request

image image

Speedy1991 avatar Jun 11 '24 12:06 Speedy1991

Hey @Speedy1991, you can override the behavior by adding the integration explicitly to your sentry_sdk.init with async_execution=False, see here: https://docs.sentry.io/platforms/python/integrations/strawberry/#synchronous-vs-asynchronous-execution Does that solve the issue for you?

sentrivana avatar Jun 11 '24 12:06 sentrivana

Hey @sentrivana, thanks for the quick reply. No this does not solve my problem, because I initialize sentry one time, let me show you an example (psudocode):

from django.core.handlers.asgi import ASGIHandler
from starlette.websockets import WebSocket

sentry_sdk.init(
    dsn="xxx",
    integrations=[DjangoIntegration()],
)

def router(django_app):  
  async def asgi(scope, receive, send):
        if scope["type"] == "websocket" and r_path in ['/graphqlws/']:
            match = resolve(scope["raw_path"].decode("ascii"))
            await match.func(WebSocket(scope, receive, send), *match.args, **match.kwargs)
            return
        await django_app(scope, receive, send)
application = router( ASGIHandler())

now the StrawberryExtension is added async even the django app is mounting a sync strawberry view

Speedy1991 avatar Jun 11 '24 12:06 Speedy1991

Thanks for the follow up. Do I understand correctly that you want to use the StrawberryIntegration both in the Django app (sync) and in the Starlette app (async)? That is not possible with the current setup without initializing Sentry in both apps. You could either force the use of the sync extension everywhere, or disable the StrawberryIntegration altogether (via auto_enabling_integrations=False, see docs) and use the extension directly.

IIRC the reason why the integration needs to know if you want the sync or async version at startup is that it works via injecting an extension which is done at schema creation. So this would need a bigger revamp to support guessing the context during runtime.

sentrivana avatar Jun 13 '24 10:06 sentrivana

This issue has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you remove the label Waiting for: Community, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

getsantry[bot] avatar Oct 29 '24 07:10 getsantry[bot]