Skip to content

Commit 3dacbf2

Browse files
authored
ref(asyncio): Migrate integration to span-first (#6198)
Migrates the asyncio integration to support the span-first (streaming) trace lifecycle alongside the existing static transaction-based approach. The integration now uses `StreamedSpan` when `trace_lifecycle: "stream"` is enabled, and falls back to the existing `Span`-based behavior otherwise. Tests are parametrized to cover both modes. Fixes PY-2304 Fixes #6002
1 parent ecc23fa commit 3dacbf2

2 files changed

Lines changed: 374 additions & 131 deletions

File tree

sentry_sdk/integrations/asyncio.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
1-
import sys
21
import functools
2+
import sys
33

44
import sentry_sdk
55
from sentry_sdk.consts import OP
6-
from sentry_sdk.integrations import Integration, DidNotEnable
6+
from sentry_sdk.integrations import DidNotEnable, Integration
77
from sentry_sdk.integrations._wsgi_common import nullcontext
8+
from sentry_sdk.traces import StreamedSpan
9+
from sentry_sdk.tracing import Span
10+
from sentry_sdk.tracing_utils import has_span_streaming_enabled
11+
from sentry_sdk.transport import AsyncHttpTransport
812
from sentry_sdk.utils import (
913
event_from_exception,
14+
is_internal_task,
1015
logger,
1116
reraise,
12-
is_internal_task,
1317
)
14-
from sentry_sdk.transport import AsyncHttpTransport
1518

1619
try:
1720
import asyncio
1821
from asyncio.tasks import Task
1922
except ImportError:
2023
raise DidNotEnable("asyncio not available")
2124

22-
from typing import TYPE_CHECKING
25+
from typing import TYPE_CHECKING, Optional, Union
2326

2427
if TYPE_CHECKING:
25-
from typing import Any, Callable, TypeVar
2628
from collections.abc import Coroutine
29+
from typing import Any, Callable, TypeVar
2730

2831
from sentry_sdk._types import ExcInfo
2932

@@ -142,22 +145,31 @@ def _sentry_task_factory(
142145
@_wrap_coroutine(coro)
143146
async def _task_with_sentry_span_creation() -> "Any":
144147
result = None
145-
146-
integration = sentry_sdk.get_client().get_integration(
147-
AsyncioIntegration
148-
)
148+
client = sentry_sdk.get_client()
149+
integration = client.get_integration(AsyncioIntegration)
149150
task_spans = integration.task_spans if integration else False
150151

152+
span_ctx: "Optional[Union[StreamedSpan, Span]]" = None
153+
is_span_streaming_enabled = has_span_streaming_enabled(client.options)
154+
151155
with sentry_sdk.isolation_scope():
152-
with (
153-
sentry_sdk.start_span(
154-
op=OP.FUNCTION,
155-
name=get_name(coro),
156-
origin=AsyncioIntegration.origin,
157-
)
158-
if task_spans
159-
else nullcontext()
160-
):
156+
if task_spans:
157+
if is_span_streaming_enabled:
158+
span_ctx = sentry_sdk.traces.start_span(
159+
name=get_name(coro),
160+
attributes={
161+
"sentry.op": OP.FUNCTION,
162+
"sentry.origin": AsyncioIntegration.origin,
163+
},
164+
)
165+
else:
166+
span_ctx = sentry_sdk.start_span(
167+
op=OP.FUNCTION,
168+
name=get_name(coro),
169+
origin=AsyncioIntegration.origin,
170+
)
171+
172+
with span_ctx if span_ctx else nullcontext():
161173
try:
162174
result = await coro
163175
except StopAsyncIteration as e:

0 commit comments

Comments
 (0)