Skip to content

Commit 31ae84b

Browse files
committed
ref(asyncio integration): Refactor asyncio context filtering
GH-4699
1 parent 7c0d466 commit 31ae84b

File tree

3 files changed

+47
-51
lines changed

3 files changed

+47
-51
lines changed

sentry_sdk/integrations/asyncio.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
event_from_exception,
99
logger,
1010
reraise,
11-
is_sentry_internal_task,
11+
is_internal_task,
1212
)
1313
from sentry_sdk.transport import AsyncHttpTransport
1414

@@ -89,16 +89,18 @@ def _sentry_task_factory(
8989
) -> asyncio.Future[Any]:
9090

9191
# Check if this is an internal Sentry task
92-
is_internal = is_sentry_internal_task.get()
92+
is_internal = is_internal_task()
9393

9494
if is_internal:
95+
task = None
9596
if orig_task_factory:
96-
return orig_task_factory(loop, coro, **kwargs)
97-
else:
97+
task = orig_task_factory(loop, coro, **kwargs)
98+
if task is None:
9899
task = Task(coro, loop=loop, **kwargs)
99100
if task._source_traceback: # type: ignore
100101
del task._source_traceback[-1] # type: ignore
101-
return task
102+
103+
return task
102104

103105
async def _task_with_sentry_span_creation() -> Any:
104106
result = None

sentry_sdk/utils.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,23 @@
7474

7575
_installed_modules = None
7676

77-
is_sentry_internal_task = contextvars.ContextVar(
77+
_is_sentry_internal_task = contextvars.ContextVar(
7878
"is_sentry_internal_task", default=False
7979
)
8080

8181

82+
def is_internal_task():
83+
return _is_sentry_internal_task.get()
84+
85+
8286
@contextmanager
8387
def mark_sentry_task_internal():
8488
"""Context manager to mark a task as Sentry internal."""
85-
token = is_sentry_internal_task.set(True)
89+
token = _is_sentry_internal_task.set(True)
8690
try:
8791
yield
8892
finally:
89-
is_sentry_internal_task.reset(token)
93+
_is_sentry_internal_task.reset(token)
9094

9195

9296
BASE64_ALPHABET = re.compile(r"^[a-zA-Z0-9/+=]*$")

tests/integrations/asyncio/test_asyncio.py

Lines changed: 33 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -433,57 +433,47 @@ def test_loop_close_flushes_async_transport(sentry_init):
433433
@minimum_python_38
434434
@pytest.mark.asyncio
435435
async def test_internal_tasks_not_wrapped(sentry_init, capture_events):
436-
"""Test that internal Sentry tasks marked with context manager are not wrapped."""
437436

438-
# Get the event loop and save original task factory
439-
loop = asyncio.get_running_loop()
440-
original_task_factory = loop.get_task_factory()
441-
442-
try:
443-
sentry_init(integrations=[AsyncioIntegration()], traces_sample_rate=1.0)
444-
events = capture_events()
445-
446-
# Create a user task that should be wrapped
447-
async def user_task():
448-
await asyncio.sleep(0.01)
449-
return "user_result"
437+
sentry_init(integrations=[AsyncioIntegration()], traces_sample_rate=1.0)
438+
events = capture_events()
450439

451-
# Create an internal task that should NOT be wrapped
452-
async def internal_task():
453-
await asyncio.sleep(0.01)
454-
return "internal_result"
440+
# Create a user task that should be wrapped
441+
async def user_task():
442+
await asyncio.sleep(0.01)
443+
return "user_result"
455444

456-
with sentry_sdk.start_transaction(name="test_transaction"):
457-
user_task_obj = asyncio.create_task(user_task())
445+
# Create an internal task that should NOT be wrapped
446+
async def internal_task():
447+
await asyncio.sleep(0.01)
448+
return "internal_result"
458449

459-
with mark_sentry_task_internal():
460-
internal_task_obj = asyncio.create_task(internal_task())
450+
with sentry_sdk.start_transaction(name="test_transaction"):
451+
user_task_obj = asyncio.create_task(user_task())
461452

462-
user_result = await user_task_obj
463-
internal_result = await internal_task_obj
453+
with mark_sentry_task_internal():
454+
internal_task_obj = asyncio.create_task(internal_task())
464455

465-
assert user_result == "user_result"
466-
assert internal_result == "internal_result"
456+
user_result = await user_task_obj
457+
internal_result = await internal_task_obj
467458

468-
assert len(events) == 1
469-
transaction = events[0]
459+
assert user_result == "user_result"
460+
assert internal_result == "internal_result"
470461

471-
user_spans = []
472-
internal_spans = []
462+
assert len(events) == 1
463+
transaction = events[0]
473464

474-
for span in transaction.get("spans", []):
475-
if "user_task" in span.get("description", ""):
476-
user_spans.append(span)
477-
elif "internal_task" in span.get("description", ""):
478-
internal_spans.append(span)
465+
user_spans = []
466+
internal_spans = []
479467

480-
assert (
481-
len(user_spans) > 0
482-
), f"User task should have been traced. All spans: {[s.get('description') for s in transaction.get('spans', [])]}"
483-
assert (
484-
len(internal_spans) == 0
485-
), f"Internal task should NOT have been traced. All spans: {[s.get('description') for s in transaction.get('spans', [])]}"
468+
for span in transaction.get("spans", []):
469+
if "user_task" in span.get("description", ""):
470+
user_spans.append(span)
471+
elif "internal_task" in span.get("description", ""):
472+
internal_spans.append(span)
486473

487-
finally:
488-
# Restore original task factory to avoid interfering with other tests
489-
loop.set_task_factory(original_task_factory)
474+
assert (
475+
len(user_spans) > 0
476+
), f"User task should have been traced. All spans: {[s.get('description') for s in transaction.get('spans', [])]}"
477+
assert (
478+
len(internal_spans) == 0
479+
), f"Internal task should NOT have been traced. All spans: {[s.get('description') for s in transaction.get('spans', [])]}"

0 commit comments

Comments
 (0)