Description
How do you use Sentry?
Sentry Saas (sentry.io)
Version
2.25.1
Steps to Reproduce
I am starting (calling) a bunch of futures, before I actually await them concurrently using asyncio.gather
.
The code looks like this:
import asyncio
import sentry_sdk
@sentry_sdk.trace
async def foo(a):
await asyncio.sleep(1)
return a
@sentry_sdk.trace
async def real_main():
futures = [foo(a) for a in range(5)]
results = await asyncio.gather(*futures)
print(results)
async def main():
sentry_sdk.init(
dsn="…",
debug=True,
traces_sample_rate=1.0,
)
with sentry_sdk.start_transaction(op="task", name="main"):
await real_main()
if __name__ == "__main__":
asyncio.run(main())
I might be able to work around this in this toy example by using explicit isolation_scope
myself somehow.
However, my real usecase happens deep within the graphql
library, somewhere here:
https://github.com/graphql-python/graphql-core/blob/416247c1d511350445c23096f9491fbef424b69b/src/graphql/execution/execute.py#L431-L470
Expected Result
I expect the futures to create sibling spans, as they are being "started" in the same caller function.
Actual Result
Instead of the calls ending up with sibling spans, they end up as parent->child spans instead.
As the first async fn has not "finished" yet when I "start" the next one, it is on the top of the span hierarchy.
Example trace: https://sentry-sdks.sentry.io/discover/trace/9f5c02338db64a91901d28c3d90541b7