Skip to content

Commit ef0c412

Browse files
committed
Inform users about what is hapenning during shutdown.
1 parent 7b005e1 commit ef0c412

File tree

1 file changed

+41
-13
lines changed

1 file changed

+41
-13
lines changed

sentry_sdk/integrations/asyncio.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import sys
2+
import signal
23

34
import sentry_sdk
45
from sentry_sdk.consts import OP
@@ -36,10 +37,25 @@ def patch_asyncio():
3637
loop = asyncio.get_running_loop()
3738
orig_task_factory = loop.get_task_factory()
3839

40+
# Add a shutdown handler to log a helpful message
41+
def shutdown_handler():
42+
logger.info(
43+
"AsyncIO is shutting down. If you see 'Task was destroyed but it is pending!' "
44+
"errors with '_task_with_sentry_span_creation', these are normal during shutdown "
45+
"and not a problem with your code or Sentry."
46+
)
47+
48+
try:
49+
loop.add_signal_handler(signal.SIGINT, shutdown_handler)
50+
loop.add_signal_handler(signal.SIGTERM, shutdown_handler)
51+
except (NotImplementedError, AttributeError):
52+
# Signal handlers might not be supported on all platforms
53+
pass
54+
3955
def _sentry_task_factory(loop, coro, **kwargs):
4056
# type: (asyncio.AbstractEventLoop, Coroutine[Any, Any, Any], Any) -> asyncio.Future[Any]
4157

42-
async def _coro_creating_hub_and_span():
58+
async def _task_with_sentry_span_creation():
4359
# type: () -> Any
4460
result = None
4561

@@ -56,20 +72,32 @@ async def _coro_creating_hub_and_span():
5672

5773
return result
5874

75+
task = None
76+
5977
# Trying to use user set task factory (if there is one)
6078
if orig_task_factory:
61-
return orig_task_factory(loop, _coro_creating_hub_and_span(), **kwargs)
62-
63-
# The default task factory in `asyncio` does not have its own function
64-
# but is just a couple of lines in `asyncio.base_events.create_task()`
65-
# Those lines are copied here.
66-
67-
# WARNING:
68-
# If the default behavior of the task creation in asyncio changes,
69-
# this will break!
70-
task = Task(_coro_creating_hub_and_span(), loop=loop, **kwargs)
71-
if task._source_traceback: # type: ignore
72-
del task._source_traceback[-1] # type: ignore
79+
task = orig_task_factory(
80+
loop, _task_with_sentry_span_creation(), **kwargs
81+
)
82+
83+
if task is None:
84+
# The default task factory in `asyncio` does not have its own function
85+
# but is just a couple of lines in `asyncio.base_events.create_task()`
86+
# Those lines are copied here.
87+
88+
# WARNING:
89+
# If the default behavior of the task creation in asyncio changes,
90+
# this will break!
91+
task = Task(_task_with_sentry_span_creation(), loop=loop, **kwargs)
92+
if task._source_traceback: # type: ignore
93+
del task._source_traceback[-1] # type: ignore
94+
95+
# Set the task name to include the original coroutine's name
96+
try:
97+
task.set_name(f"{get_name(coro)} (Sentry-wrapped)")
98+
except AttributeError:
99+
# set_name might not be available in all Python versions
100+
pass
73101

74102
return task
75103

0 commit comments

Comments
 (0)