Skip to content
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

feat(profiling): Set active thread id for ASGI frameworks #1778

Closed

Conversation

Zylphrex
Copy link
Member

@Zylphrex Zylphrex commented Dec 7, 2022

When running in ASGI sync views, the transaction gets started in the main thread then the request is dispatched to a handler thread. We want to set the handler thread as the active thread id to ensure that profiles will show it on first render.

@Zylphrex Zylphrex marked this pull request as ready for review December 7, 2022 16:23
@Zylphrex Zylphrex requested review from sl0thentr0py and a team December 7, 2022 16:23
When running in ASGI sync views, the transaction gets started in the main thread
then the request is dispatched to a handler thread. We want to set the handler
thread as the active thread id to ensure that profiles will show it on first
render.
@Zylphrex Zylphrex force-pushed the txiao/feat/set-active-thread-id-for-asgi-frameworks branch from 7d648df to 9724720 Compare December 9, 2022 17:21
@@ -62,6 +65,21 @@ def patch_get_request_handler():

def _sentry_get_request_handler(*args, **kwargs):
# type: (*Any, **Any) -> Any
dependant = kwargs.get("dependant")
if dependant and not asyncio.iscoroutinefunction(dependant.call):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it safe to use asyncio here for this?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think so.
We vendored this from starlette for doing these coroutine checks.

@antonpirker knows this stuff better since he worked on it.

from quart.signals import ( # type: ignore
got_background_exception,
got_request_exception,
got_websocket_exception,
request_started,
websocket_started,
)
from quart.utils import is_coroutine_function # type: ignore
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was introduced in quart==0.11.1, do we need to support older versions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, tox says min 0.16.1, so all good

Copy link
Member

@sl0thentr0py sl0thentr0py left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

left some random comments, but I want to discuss some high-level stuff first.

@@ -62,6 +65,21 @@ def patch_get_request_handler():

def _sentry_get_request_handler(*args, **kwargs):
# type: (*Any, **Any) -> Any
dependant = kwargs.get("dependant")
if dependant and not asyncio.iscoroutinefunction(dependant.call):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think so.
We vendored this from starlette for doing these coroutine checks.

@antonpirker knows this stuff better since he worked on it.

if dependant and not asyncio.iscoroutinefunction(dependant.call):
old_call = dependant.call

def _sentry_call(*args, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is setting the thread in fastapi still necessary if we already do it in request_response in starlette?

from quart.signals import ( # type: ignore
got_background_exception,
got_request_exception,
got_websocket_exception,
request_started,
websocket_started,
)
from quart.utils import is_coroutine_function # type: ignore
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, tox says min 0.16.1, so all good

@Zylphrex
Copy link
Member Author

Zylphrex commented Jan 4, 2023

We have a ThreadingIntegration, should we update the scope there on run?

I thought about this but this would imply that any time a thread is started to do any work, it'll be marked as an active thread. So for use cases like background work, this would cause issues.

Would this be cleaner if we just patch the run_in_threadpool function in starlette or even lower level?

I looked into only patching starlette and leaving fastapi alone but these lower level functions are used for more than just starting sync requests. This would cause the same issue as adding this into the threading integration if someone were to use these lower level apis.

@@ -175,7 +176,7 @@ async def _run_app(self, scope, callback):

with hub.start_transaction(
transaction, custom_sampling_context={"asgi_scope": scope}
):
), start_profiling(transaction, hub):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will enable profiling for all the ASGI frameworks as well. This should be removed in #1797 as that will enable it for all transactions.

@sl0thentr0py sl0thentr0py self-assigned this Jan 5, 2023
@cleptric cleptric self-requested a review January 9, 2023 12:17
@Zylphrex
Copy link
Member Author

Zylphrex commented Jan 9, 2023

replaced by #1824

@Zylphrex Zylphrex closed this Jan 9, 2023
@antonpirker antonpirker deleted the txiao/feat/set-active-thread-id-for-asgi-frameworks branch April 19, 2023 11:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants