From fc080dbb9b9214b5c5584554bd6dd9ac0dfca3c4 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 22 Jan 2026 17:30:33 +0100 Subject: [PATCH 1/2] feat(asyncio): Allow to turn task spans off --- sentry_sdk/integrations/asyncio.py | 23 ++++++-- tests/integrations/asyncio/test_asyncio.py | 69 ++++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/sentry_sdk/integrations/asyncio.py b/sentry_sdk/integrations/asyncio.py index afaca73d33..abf59198ac 100644 --- a/sentry_sdk/integrations/asyncio.py +++ b/sentry_sdk/integrations/asyncio.py @@ -4,6 +4,7 @@ import sentry_sdk from sentry_sdk.consts import OP from sentry_sdk.integrations import Integration, DidNotEnable +from sentry_sdk.integrations._wsgi_common import nullcontext from sentry_sdk.utils import event_from_exception, logger, reraise try: @@ -60,11 +61,22 @@ def _sentry_task_factory( async def _task_with_sentry_span_creation() -> "Any": result = None + integration = sentry_sdk.get_client().get_integration( + AsyncioIntegration + ) + task_spans = ( + integration.task_spans if integration is not None else True + ) + with sentry_sdk.isolation_scope(): - with sentry_sdk.start_span( - op=OP.FUNCTION, - name=get_name(coro), - origin=AsyncioIntegration.origin, + with ( + sentry_sdk.start_span( + op=OP.FUNCTION, + name=get_name(coro), + origin=AsyncioIntegration.origin, + ) + if task_spans + else nullcontext() ): try: result = await coro @@ -140,6 +152,9 @@ class AsyncioIntegration(Integration): identifier = "asyncio" origin = f"auto.function.{identifier}" + def __init__(self, task_spans: bool = True) -> None: + self.task_spans = task_spans + @staticmethod def setup_once() -> None: patch_asyncio() diff --git a/tests/integrations/asyncio/test_asyncio.py b/tests/integrations/asyncio/test_asyncio.py index 58072b0071..5cc0159606 100644 --- a/tests/integrations/asyncio/test_asyncio.py +++ b/tests/integrations/asyncio/test_asyncio.py @@ -395,6 +395,75 @@ async def test_span_origin( assert event["spans"][0]["origin"] == "auto.function.asyncio" +@minimum_python_38 +@pytest.mark.asyncio +async def test_task_spans_false( + sentry_init, + capture_events, + uninstall_integration, +): + """ + Test that task_spans=False disables span creation but retains scope isolation. + """ + uninstall_integration("asyncio") + + sentry_init( + traces_sample_rate=1.0, + integrations=[ + AsyncioIntegration(task_spans=False), + ], + ) + + events = capture_events() + + with sentry_sdk.start_transaction(name="test_no_spans"): + with sentry_sdk.start_span(op="root", name="root span"): + tasks = [asyncio.create_task(foo()), asyncio.create_task(bar())] + await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION) + + sentry_sdk.flush() + + (transaction_event,) = events + + # Only the root span should be present, no asyncio spans + assert len(transaction_event["spans"]) == 1 + assert transaction_event["spans"][0]["op"] == "root" + assert transaction_event["spans"][0]["description"] == "root span" + + +@minimum_python_38 +@pytest.mark.asyncio +async def test_enable_asyncio_integration_with_task_spans_false( + sentry_init, + capture_events, + uninstall_integration, +): + """ + Test that enable_asyncio_integration() helper works with task_spans=False. + """ + uninstall_integration("asyncio") + + sentry_init(traces_sample_rate=1.0) + + assert "asyncio" not in sentry_sdk.get_client().integrations + + enable_asyncio_integration(task_spans=False) + + assert "asyncio" in sentry_sdk.get_client().integrations + assert sentry_sdk.get_client().integrations["asyncio"].task_spans is False + + events = capture_events() + + with sentry_sdk.start_transaction(name="test"): + await asyncio.create_task(foo()) + + sentry_sdk.flush() + + (transaction,) = events + # No asyncio spans should be created + assert not transaction["spans"] + + @minimum_python_38 @pytest.mark.asyncio async def test_delayed_enable_integration(sentry_init, capture_events): From 4db63eb95dc22f4b4eb34f0645230b84e91f4068 Mon Sep 17 00:00:00 2001 From: Ivana Kellyer Date: Thu, 22 Jan 2026 17:35:33 +0100 Subject: [PATCH 2/2] . --- sentry_sdk/integrations/asyncio.py | 4 +--- tests/integrations/asyncio/test_asyncio.py | 14 +++----------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/sentry_sdk/integrations/asyncio.py b/sentry_sdk/integrations/asyncio.py index abf59198ac..b7aa0a7202 100644 --- a/sentry_sdk/integrations/asyncio.py +++ b/sentry_sdk/integrations/asyncio.py @@ -64,9 +64,7 @@ async def _task_with_sentry_span_creation() -> "Any": integration = sentry_sdk.get_client().get_integration( AsyncioIntegration ) - task_spans = ( - integration.task_spans if integration is not None else True - ) + task_spans = integration.task_spans if integration else False with sentry_sdk.isolation_scope(): with ( diff --git a/tests/integrations/asyncio/test_asyncio.py b/tests/integrations/asyncio/test_asyncio.py index 5cc0159606..b41aa244cb 100644 --- a/tests/integrations/asyncio/test_asyncio.py +++ b/tests/integrations/asyncio/test_asyncio.py @@ -402,9 +402,6 @@ async def test_task_spans_false( capture_events, uninstall_integration, ): - """ - Test that task_spans=False disables span creation but retains scope isolation. - """ uninstall_integration("asyncio") sentry_init( @@ -417,18 +414,14 @@ async def test_task_spans_false( events = capture_events() with sentry_sdk.start_transaction(name="test_no_spans"): - with sentry_sdk.start_span(op="root", name="root span"): - tasks = [asyncio.create_task(foo()), asyncio.create_task(bar())] - await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION) + tasks = [asyncio.create_task(foo()), asyncio.create_task(bar())] + await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION) sentry_sdk.flush() (transaction_event,) = events - # Only the root span should be present, no asyncio spans - assert len(transaction_event["spans"]) == 1 - assert transaction_event["spans"][0]["op"] == "root" - assert transaction_event["spans"][0]["description"] == "root span" + assert not transaction_event["spans"] @minimum_python_38 @@ -460,7 +453,6 @@ async def test_enable_asyncio_integration_with_task_spans_false( sentry_sdk.flush() (transaction,) = events - # No asyncio spans should be created assert not transaction["spans"]