Skip to content

fix(asyncio integration): Filter SDK internal tasks from span creation #4700

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
166 commits
Select commit Hold shift + click to select a range
63b1f24
ref(transport): Added shared sync/async transport superclass and crea…
srothh Jul 11, 2025
666ff3a
ref(transport) Removed Todo and reverted class name change
srothh Jul 11, 2025
748764e
test(transport): Add test for HTTP error status handling
srothh Jul 11, 2025
ee6dbee
test(transport): Restore accidentally removed comments
srothh Jul 11, 2025
19405fd
ref(transport) Refactor class names to reflect previous functionality
srothh Jul 14, 2025
3736c03
ref(transport): Add flush_async in the Transport abc
srothh Jul 17, 2025
3607d44
ref(transport): Move flush_async from ABC
srothh Jul 17, 2025
0ba5a83
ref(transport): add async type annotations to HTTPTransportCore
srothh Jul 23, 2025
9bb628e
ref(transport): Add abstract base class for worker implementation
srothh Jul 14, 2025
a81487e
ref(transport): Add _create_worker factory method to Transport
srothh Jul 14, 2025
8960e6f
ref(worker): Add flush_async method to Worker ABC
srothh Jul 17, 2025
0f7937b
ref(worker): Move worker flush_async from Worker ABC
srothh Jul 17, 2025
268ea1a
ref(worker): Amend function signature for coroutines
srothh Jul 17, 2025
b3c05cc
feat(transport): Add an async task-based worker for transport
srothh Jul 17, 2025
fb0ad18
ref(worker): Make worker work with new ABC interface
srothh Jul 17, 2025
7edbbaf
fix(worker): Check if callbacks from worker queue are coroutines or f…
srothh Jul 17, 2025
0f63d24
ref(worker): Amend return type of submit and flush to accomodate for …
srothh Jul 17, 2025
2430e2e
ref(worker): Add type parameters for AsyncWorker variables
srothh Jul 17, 2025
96fcd85
ref(worker): Remove loop upon killing worker
srothh Jul 17, 2025
331e40b
feat(worker): Enable concurrent callbacks on async task worker
srothh Jul 18, 2025
5f67485
fix(worker): Modify kill behaviour to mirror threaded worker
srothh Jul 18, 2025
97c5e3d
ref(worker): add proper type annotation to worker task list
srothh Jul 21, 2025
8809b08
feat(transport): Add async transport class
srothh Jul 21, 2025
7c5dec0
ref(transport): Fix event loop handling in async transport
srothh Jul 22, 2025
b0390e6
feat(transport): Add kill method for async transport
srothh Jul 22, 2025
f01b00d
ref(transport): Fix type errors in async transport
srothh Jul 23, 2025
23b8ea2
Add silent failing to kill on event loop errors
srothh Jul 24, 2025
176a1d1
ref(transport): Fix event loop check in make_transport
srothh Jul 24, 2025
4fe61bf
ref(transport): Add missing transport instantiation in non-async context
srothh Jul 24, 2025
52c9e36
ref(transport): Fix httpcore async specific request handling
srothh Jul 25, 2025
6d69406
ref(transport): Add gc safety to async kill
srothh Jul 25, 2025
3629609
ref(transport): Add missing httpcore extensions
srothh Jul 25, 2025
21cde52
fix(transport): Fix fallback sync transport creating async worker
srothh Jul 28, 2025
9f24136
ref(transport): Add abstract base class for worker implementation
srothh Jul 14, 2025
001f36c
ref(transport): Add _create_worker factory method to Transport
srothh Jul 14, 2025
401b1bc
ref(worker): Add flush_async method to Worker ABC
srothh Jul 17, 2025
3f43d8f
ref(worker): Move worker flush_async from Worker ABC
srothh Jul 17, 2025
15fa295
ref(worker): Amend function signature for coroutines
srothh Jul 17, 2025
ef780f3
ref(worker): Add missing docstrings to worker ABC
srothh Jul 24, 2025
c541bd7
ref(transport): Make kill optionally return a task for async
srothh Jul 29, 2025
2808062
Integrate AsyncHttpTransport as a new experimental option
srothh Jul 22, 2025
ea5f557
ref(transport): Fix type issues in AsyncTransport
srothh Jul 22, 2025
c61eb02
ref(transport): Add missing async transport loop type annotation
srothh Jul 23, 2025
38baead
fix(client): Fix mypy type errors
srothh Jul 23, 2025
e4ed773
ref(client): Fix mypy inheritance type error
srothh Jul 23, 2025
236ae2c
ref(client): Move mypy annotations to correct place
srothh Jul 23, 2025
9dd546c
ref(client): Add event loop handling to client flush/close
srothh Jul 24, 2025
f4ac157
ref(client): Moved close done callback into async task
srothh Jul 24, 2025
ed392e9
ref(client): Move timeout check in client to properly cover async
srothh Jul 25, 2025
50553d4
feat(asyncio): Add patching for loop.close in asyncio
srothh Jul 25, 2025
4a7b8ce
ref(asyncio): Fix mypy type annotation errors
srothh Jul 25, 2025
cd8a35f
ref(client): Fix redundant async flush helper flushes
srothh Jul 25, 2025
b9f2ec7
ref(client): remove wrongful indent
srothh Jul 25, 2025
98d74ed
test(transport): Add inital transport tests
srothh Jul 28, 2025
9df5ec5
fix(requirements): Fix requirements for async transport testing on py…
srothh Jul 28, 2025
23d8740
fix(dependencies): Remove version constraint from httpcore
srothh Jul 28, 2025
a496787
fix(dependencies): Version guards for correct httpcore version
srothh Jul 28, 2025
32a9abd
ref(tox): remove anyio version pin
srothh Jul 28, 2025
a69f7bb
Revert "ref(tox): remove anyio version pin"
srothh Jul 28, 2025
c80b095
ref(dependencies): Revert dependency changes
srothh Jul 28, 2025
5904968
ref(test): Remove flush from async transport test
srothh Jul 28, 2025
09034b7
ref(client): Remove wrongful indents in client sync flush
srothh Jul 28, 2025
21b1cda
fix(testing): Changed httpx anyio version pin to >=3, <5
srothh Jul 29, 2025
9d0cde4
fix(test): Properly modify httpx anyio pin
srothh Jul 29, 2025
f21e2ea
fix(test): Add fastapi anyio pin for <0.8
srothh Jul 29, 2025
76aae83
feat(test): Add tests for specific async transport functionality
srothh Jul 29, 2025
4c1e99b
feat(test): Add flush to async transport test
srothh Jul 29, 2025
6df7037
ref(client): Adapt client for blocking kill in async transport
srothh Jul 29, 2025
25c04fc
ref(client): Fix transport shutdown if loop is not running
srothh Jul 29, 2025
e8d889c
ref(test): Add config tests for SSL/proxy for async
srothh Jul 29, 2025
f63e46f
feat(transport): Add an async task-based worker for transport
srothh Jul 17, 2025
1804271
ref(worker): Make worker work with new ABC interface
srothh Jul 17, 2025
11da869
fix(worker): Check if callbacks from worker queue are coroutines or f…
srothh Jul 17, 2025
779a0d6
ref(worker): Amend return type of submit and flush to accomodate for …
srothh Jul 17, 2025
0895d23
ref(worker): Add type parameters for AsyncWorker variables
srothh Jul 17, 2025
bbf426b
ref(worker): Remove loop upon killing worker
srothh Jul 17, 2025
744dc8a
feat(worker): Enable concurrent callbacks on async task worker
srothh Jul 18, 2025
fcc8040
fix(worker): Modify kill behaviour to mirror threaded worker
srothh Jul 18, 2025
9a43d9b
ref(worker): add proper type annotation to worker task list
srothh Jul 21, 2025
b5eda0e
ref(worker): Refactor implementation to incorporate feedback
srothh Jul 30, 2025
9e380b8
ref(worker): fix queue initialization
srothh Jul 30, 2025
ee44621
ref(worker): Add queue as optional to allow for initialisation in start
srothh Jul 30, 2025
d9f7383
ref(worker): Change to sync flush method that launches task
srothh Jul 30, 2025
a644465
feat(transport): Add async transport class
srothh Jul 21, 2025
c935e9e
ref(transport): Fix event loop handling in async transport
srothh Jul 22, 2025
b90daf4
feat(transport): Add kill method for async transport
srothh Jul 22, 2025
e1d7cdb
ref(transport): Fix type errors in async transport
srothh Jul 23, 2025
90346a5
Add silent failing to kill on event loop errors
srothh Jul 24, 2025
47416f4
ref(transport): Fix event loop check in make_transport
srothh Jul 24, 2025
73cdc6d
ref(transport): Add missing transport instantiation in non-async context
srothh Jul 24, 2025
1ae8708
ref(transport): Fix httpcore async specific request handling
srothh Jul 25, 2025
6f18657
ref(transport): Add gc safety to async kill
srothh Jul 25, 2025
87a9b2f
ref(transport): Add missing httpcore extensions
srothh Jul 25, 2025
4fd7fa0
fix(transport): Fix fallback sync transport creating async worker
srothh Jul 28, 2025
69734cd
ref(transport): Make kill optionally return a task for async
srothh Jul 29, 2025
f5ef707
ref(transport): Adapt transport for synchronous flush interface
srothh Jul 30, 2025
fca8740
ref(transport): Fix mypy error
srothh Jul 30, 2025
4b0d09b
Merge branch 'srothh/async-transport' into srothh/async-transport-int…
srothh Jul 30, 2025
e23efd7
ref(transport): Make client work with sync flush changes
srothh Jul 30, 2025
d2e647b
ref(worker): Readd coroutine check for worker callbacks
srothh Jul 30, 2025
55b606a
ref(client): Properly add client changes for sync flush
srothh Jul 30, 2025
d89abed
feat(transport): Add async transport class
srothh Jul 21, 2025
5e1e0c6
ref(transport): Fix event loop handling in async transport
srothh Jul 22, 2025
8fdf43d
feat(transport): Add kill method for async transport
srothh Jul 22, 2025
6619670
ref(transport): Fix type errors in async transport
srothh Jul 23, 2025
2eee1b1
Add silent failing to kill on event loop errors
srothh Jul 24, 2025
6c787a4
ref(transport): Fix event loop check in make_transport
srothh Jul 24, 2025
b79d346
ref(transport): Add missing transport instantiation in non-async context
srothh Jul 24, 2025
1717888
ref(transport): Fix httpcore async specific request handling
srothh Jul 25, 2025
e1fd57a
ref(transport): Add gc safety to async kill
srothh Jul 25, 2025
b87c68e
ref(transport): Add missing httpcore extensions
srothh Jul 25, 2025
a827d0d
fix(transport): Fix fallback sync transport creating async worker
srothh Jul 28, 2025
ee0b440
ref(transport): Make kill optionally return a task for async
srothh Jul 29, 2025
70f228e
ref(transport): Adapt transport for synchronous flush interface
srothh Jul 30, 2025
328d8ad
ref(transport): Fix mypy error
srothh Jul 30, 2025
ef61134
ref(transport): Make transport loop public
srothh Jul 30, 2025
ad93516
Merge branch 'srothh/async-transport' into srothh/async-transport-int…
srothh Jul 30, 2025
42d3a34
ref(transport): Add import checking for async transport
srothh Jul 30, 2025
10d85f6
ref(transport): Fix typing errors
srothh Jul 30, 2025
aaae195
ref(transport): Fix import checking
srothh Jul 30, 2025
de47da2
Merge branch 'srothh/async-transport' into srothh/async-transport-int…
srothh Jul 30, 2025
6e2c4f6
ref(client): Fix type checking with fallback asynctransport
srothh Jul 30, 2025
9da7be8
ref(asyncio): Refactor loop close patch in asyncio integration
srothh Jul 31, 2025
8a5ab06
ref(client): Split client flush into seperate function for readability
srothh Jul 31, 2025
295a0e9
ref(transport): Refactor async transport to be more aligned with sync
srothh Jul 31, 2025
e754a85
Merge branch 'srothh/async-transport' into srothh/async-transport-int…
srothh Jul 31, 2025
859a0e2
ref(worker): Remove sync callbacks from worker processing for now
srothh Jul 31, 2025
4a58ce7
feat(transport): Add async transport class
srothh Jul 21, 2025
cbecde7
ref(transport): Fix event loop handling in async transport
srothh Jul 22, 2025
c8bb55a
feat(transport): Add kill method for async transport
srothh Jul 22, 2025
05a7de7
ref(transport): Fix type errors in async transport
srothh Jul 23, 2025
38246d0
Add silent failing to kill on event loop errors
srothh Jul 24, 2025
8b226cb
ref(transport): Fix event loop check in make_transport
srothh Jul 24, 2025
823215e
ref(transport): Add missing transport instantiation in non-async context
srothh Jul 24, 2025
4eed4fd
ref(transport): Fix httpcore async specific request handling
srothh Jul 25, 2025
afd494d
ref(transport): Add gc safety to async kill
srothh Jul 25, 2025
fcc7ac3
ref(transport): Add missing httpcore extensions
srothh Jul 25, 2025
f659514
fix(transport): Fix fallback sync transport creating async worker
srothh Jul 28, 2025
8c542ce
ref(transport): Make kill optionally return a task for async
srothh Jul 29, 2025
30dde67
ref(transport): Adapt transport for synchronous flush interface
srothh Jul 30, 2025
3392e0e
ref(transport): Fix mypy error
srothh Jul 30, 2025
6c85500
ref(transport): Make transport loop public
srothh Jul 30, 2025
ae5a864
ref(transport): Add import checking for async transport
srothh Jul 30, 2025
9c537e6
ref(transport): Fix typing errors
srothh Jul 30, 2025
f7554b2
ref(transport): Fix import checking
srothh Jul 30, 2025
6cb72ad
ref(transport): Refactor async transport to be more aligned with sync
srothh Jul 31, 2025
9f226cf
Merge branch 'srothh/async-transport' into srothh/async-transport-int…
srothh Jul 31, 2025
9171c5d
Merge remote-tracking branch 'origin/srothh/transport-class-hierarchy…
sl0thentr0py Aug 12, 2025
111861b
ref(transport): Improve transport code quality
srothh Aug 13, 2025
1334a29
Merge branch 'srothh/async-transport' into srothh/async-transport-int…
srothh Aug 13, 2025
41983fc
fix(asyncio integration): Filter SDK internal tasks from asyncio spans
srothh Aug 13, 2025
cfbea39
ref(asyncio integration): Change Context manager name
srothh Aug 13, 2025
7c0d466
ref(asyncio integration): Update context var names
srothh Aug 13, 2025
a2aafb4
Merge remote-tracking branch 'origin/srothh/transport-class-hierarchy…
sl0thentr0py Aug 13, 2025
31ae84b
ref(asyncio integration): Refactor asyncio context filtering
srothh Aug 14, 2025
e170cf7
ref(asyncio integration): Refactor code to avoid duplication
srothh Aug 14, 2025
6dd8138
test(transport): Remove background tasks from transport tests
srothh Aug 14, 2025
7ae7f12
Merge branch 'srothh/async-transport-integration' into srothh/async-t…
srothh Aug 14, 2025
5f7af94
fix(transport): Add asyncio integration check to async transport
srothh Aug 14, 2025
f44f690
fix(transport): Fix asyncio integration check for transport
srothh Aug 14, 2025
b1eff8b
Merge branch 'srothh/async-transport-integration' into srothh/async-t…
srothh Aug 14, 2025
f4bc00a
fix(asyncio integration): Change loop scope for asyncio test
srothh Aug 14, 2025
df1ceaf
ref(asyncio integrations): Fix asyncio tests
srothh Aug 14, 2025
315f8dc
Merge branch 'srothh/transport-class-hierarchy' into srothh/async-tas…
srothh Aug 14, 2025
e3bcf06
fix(asyncio integration): Fix wrong merge decision for test
srothh Aug 14, 2025
cb67c24
ref(client): Remove wrong type annotation
srothh Aug 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 44 additions & 20 deletions sentry_sdk/integrations/asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
import sentry_sdk
from sentry_sdk.consts import OP
from sentry_sdk.integrations import Integration, DidNotEnable
from sentry_sdk.utils import event_from_exception, logger, reraise
from sentry_sdk.utils import (
event_from_exception,
logger,
reraise,
is_internal_task,
)
from sentry_sdk.transport import AsyncHttpTransport

try:
Expand Down Expand Up @@ -69,6 +74,33 @@ def _patched_close() -> None:
loop._sentry_flush_patched = True # type: ignore


def _create_task_with_factory(
orig_task_factory: Any,
loop: asyncio.AbstractEventLoop,
coro: Coroutine[Any, Any, Any],
**kwargs: Any,
) -> asyncio.Task[Any]:
task = None

# Trying to use user set task factory (if there is one)
if orig_task_factory:
task = orig_task_factory(loop, coro, **kwargs)

if task is None:
# The default task factory in `asyncio` does not have its own function
# but is just a couple of lines in `asyncio.base_events.create_task()`
# Those lines are copied here.

# WARNING:
# If the default behavior of the task creation in asyncio changes,
# this will break!
task = Task(coro, loop=loop, **kwargs)
if task._source_traceback: # type: ignore
del task._source_traceback[-1] # type: ignore

return task


def patch_asyncio() -> None:
orig_task_factory = None
try:
Expand All @@ -81,6 +113,14 @@ def _sentry_task_factory(
**kwargs: Any,
) -> asyncio.Future[Any]:

# Check if this is an internal Sentry task
is_internal = is_internal_task()

if is_internal:
return _create_task_with_factory(
orig_task_factory, loop, coro, **kwargs
)

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

Expand All @@ -98,25 +138,9 @@ async def _task_with_sentry_span_creation() -> Any:

return result

task = None

# Trying to use user set task factory (if there is one)
if orig_task_factory:
task = orig_task_factory(
loop, _task_with_sentry_span_creation(), **kwargs
)

if task is None:
# The default task factory in `asyncio` does not have its own function
# but is just a couple of lines in `asyncio.base_events.create_task()`
# Those lines are copied here.

# WARNING:
# If the default behavior of the task creation in asyncio changes,
# this will break!
task = Task(_task_with_sentry_span_creation(), loop=loop, **kwargs)
if task._source_traceback: # type: ignore
del task._source_traceback[-1] # type: ignore
task = _create_task_with_factory(
orig_task_factory, loop, _task_with_sentry_span_creation(), **kwargs
)

# Set the task name to include the original coroutine's name
try:
Expand Down
10 changes: 8 additions & 2 deletions sentry_sdk/transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,12 @@
import certifi

from sentry_sdk.consts import EndpointType
from sentry_sdk.utils import Dsn, logger, capture_internal_exceptions
from sentry_sdk.utils import (
Dsn,
logger,
capture_internal_exceptions,
mark_sentry_task_internal,
)
from sentry_sdk.worker import BackgroundWorker, Worker, AsyncWorker
from sentry_sdk.envelope import Envelope, Item, PayloadRef

Expand Down Expand Up @@ -901,7 +906,8 @@ def kill(self: Self) -> Optional[asyncio.Task[None]]: # type: ignore
self._worker.kill()
try:
# Return the pool cleanup task so caller can await it if needed
return self.loop.create_task(self._pool.aclose()) # type: ignore
with mark_sentry_task_internal():
return self.loop.create_task(self._pool.aclose()) # type: ignore
except RuntimeError:
logger.warning("Event loop not running, aborting kill.")
return None
Expand Down
21 changes: 21 additions & 0 deletions sentry_sdk/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations
import base64
import contextvars
import json
import linecache
import logging
Expand All @@ -12,6 +13,7 @@
import threading
import time
from collections import namedtuple
from contextlib import contextmanager
from datetime import datetime, timezone
from decimal import Decimal
from functools import partial, partialmethod, wraps
Expand Down Expand Up @@ -72,6 +74,25 @@

_installed_modules = None

_is_sentry_internal_task = contextvars.ContextVar(
"is_sentry_internal_task", default=False
)
Copy link

Choose a reason for hiding this comment

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

Bug: ContextVar Import Bypasses Compatibility Layer

The direct import of contextvars and use of contextvars.ContextVar bypasses the existing compatibility layer. This layer provides fallbacks for Python < 3.7 and certain gevent environments, so this change can cause ImportError on older Python versions and potential issues in gevent setups.

Fix in Cursor Fix in Web



def is_internal_task():
return _is_sentry_internal_task.get()


@contextmanager
def mark_sentry_task_internal():
"""Context manager to mark a task as Sentry internal."""
token = _is_sentry_internal_task.set(True)
try:
yield
finally:
_is_sentry_internal_task.reset(token)


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

FALSY_ENV_VALUES = frozenset(("false", "f", "n", "no", "off", "0"))
Expand Down
11 changes: 7 additions & 4 deletions sentry_sdk/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from time import sleep, time
from sentry_sdk._queue import Queue, FullError
from sentry_sdk.utils import logger
from sentry_sdk.utils import logger, mark_sentry_task_internal
from sentry_sdk.consts import DEFAULT_QUEUE_SIZE

from typing import TYPE_CHECKING
Expand Down Expand Up @@ -231,7 +231,8 @@ def start(self) -> None:
self._loop = asyncio.get_running_loop()
if self._queue is None:
self._queue = asyncio.Queue(maxsize=self._queue_size)
self._task = self._loop.create_task(self._target())
with mark_sentry_task_internal():
self._task = self._loop.create_task(self._target())
self._task_for_pid = os.getpid()
except RuntimeError:
# There is no event loop running
Expand Down Expand Up @@ -273,7 +274,8 @@ async def _wait_flush(self, timeout: float, callback: Optional[Any] = None) -> N

def flush(self, timeout: float, callback: Optional[Any] = None) -> Optional[asyncio.Task[None]]: # type: ignore[override]
if self.is_alive and timeout > 0.0 and self._loop and self._loop.is_running():
return self._loop.create_task(self._wait_flush(timeout, callback))
with mark_sentry_task_internal():
return self._loop.create_task(self._wait_flush(timeout, callback))
return None

def submit(self, callback: Callable[[], Any]) -> bool:
Expand All @@ -295,7 +297,8 @@ async def _target(self) -> None:
self._queue.task_done()
break
# Firing tasks instead of awaiting them allows for concurrent requests
task = asyncio.create_task(self._process_callback(callback))
with mark_sentry_task_internal():
task = asyncio.create_task(self._process_callback(callback))
# Create a strong reference to the task so it can be cancelled on kill
# and does not get garbage collected while running
self._active_tasks.add(task)
Expand Down
67 changes: 63 additions & 4 deletions tests/integrations/asyncio/test_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import sentry_sdk
from sentry_sdk.consts import OP
from sentry_sdk.integrations.asyncio import AsyncioIntegration, patch_asyncio
from sentry_sdk.utils import mark_sentry_task_internal


try:
from contextvars import Context, ContextVar
Expand Down Expand Up @@ -379,6 +381,55 @@ async def test_span_origin(
assert event["spans"][0]["origin"] == "auto.function.asyncio"


@minimum_python_38
@pytest.mark.asyncio(loop_scope="module")
async def test_internal_tasks_not_wrapped(sentry_init, capture_events):

sentry_init(integrations=[AsyncioIntegration()], traces_sample_rate=1.0)
events = capture_events()

# Create a user task that should be wrapped
async def user_task():
await asyncio.sleep(0.01)
return "user_result"

# Create an internal task that should NOT be wrapped
async def internal_task():
await asyncio.sleep(0.01)
return "internal_result"

with sentry_sdk.start_transaction(name="test_transaction"):
user_task_obj = asyncio.create_task(user_task())

with mark_sentry_task_internal():
internal_task_obj = asyncio.create_task(internal_task())

user_result = await user_task_obj
internal_result = await internal_task_obj

assert user_result == "user_result"
assert internal_result == "internal_result"

assert len(events) == 1
transaction = events[0]

user_spans = []
internal_spans = []

for span in transaction.get("spans", []):
if "user_task" in span.get("description", ""):
user_spans.append(span)
elif "internal_task" in span.get("description", ""):
internal_spans.append(span)

assert (
len(user_spans) > 0
), f"User task should have been traced. All spans: {[s.get('description') for s in transaction.get('spans', [])]}"
assert (
len(internal_spans) == 0
), f"Internal task should NOT have been traced. All spans: {[s.get('description') for s in transaction.get('spans', [])]}"


@minimum_python_38
def test_loop_close_patching(sentry_init):
sentry_init(integrations=[AsyncioIntegration()])
Expand All @@ -405,6 +456,12 @@ def test_loop_close_flushes_async_transport(sentry_init):

sentry_init(integrations=[AsyncioIntegration()])

# Save the current event loop to restore it later
try:
original_loop = asyncio.get_event_loop()
except RuntimeError:
original_loop = None

loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

Expand All @@ -415,14 +472,16 @@ def test_loop_close_flushes_async_transport(sentry_init):
mock_client = Mock()
mock_transport = Mock(spec=AsyncHttpTransport)
mock_client.transport = mock_transport
mock_client.close = AsyncMock(return_value=None)
mock_client.close_async = AsyncMock(return_value=None)

with patch("sentry_sdk.get_client", return_value=mock_client):
loop.close()

mock_client.close.assert_called_once()
mock_client.close.assert_awaited_once()
mock_client.close_async.assert_called_once()
mock_client.close_async.assert_awaited_once()

except Exception:
finally:
if not loop.is_closed():
loop.close()
if original_loop:
asyncio.set_event_loop(original_loop)
Loading