Include a traceback for non-strict event loop blocking detection (#118620)
This commit is contained in:
parent
e976db8443
commit
8f94205014
6 changed files with 30 additions and 14 deletions
|
@ -31,17 +31,17 @@ class IntegrationFrame:
|
||||||
integration: str
|
integration: str
|
||||||
module: str | None
|
module: str | None
|
||||||
relative_filename: str
|
relative_filename: str
|
||||||
_frame: FrameType
|
frame: FrameType
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def line_number(self) -> int:
|
def line_number(self) -> int:
|
||||||
"""Return the line number of the frame."""
|
"""Return the line number of the frame."""
|
||||||
return self._frame.f_lineno
|
return self.frame.f_lineno
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def filename(self) -> str:
|
def filename(self) -> str:
|
||||||
"""Return the filename of the frame."""
|
"""Return the filename of the frame."""
|
||||||
return self._frame.f_code.co_filename
|
return self.frame.f_code.co_filename
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def line(self) -> str:
|
def line(self) -> str:
|
||||||
|
@ -119,7 +119,7 @@ def get_integration_frame(exclude_integrations: set | None = None) -> Integratio
|
||||||
integration=integration,
|
integration=integration,
|
||||||
module=found_module,
|
module=found_module,
|
||||||
relative_filename=found_frame.f_code.co_filename[index:],
|
relative_filename=found_frame.f_code.co_filename[index:],
|
||||||
_frame=found_frame,
|
frame=found_frame,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import functools
|
||||||
import linecache
|
import linecache
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
import traceback
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.core import async_get_hass_or_none
|
from homeassistant.core import async_get_hass_or_none
|
||||||
|
@ -54,12 +55,14 @@ def raise_for_blocking_call(
|
||||||
if not strict_core:
|
if not strict_core:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Detected blocking call to %s with args %s in %s, "
|
"Detected blocking call to %s with args %s in %s, "
|
||||||
"line %s: %s inside the event loop",
|
"line %s: %s inside the event loop\n"
|
||||||
|
"Traceback (most recent call last):\n%s",
|
||||||
func.__name__,
|
func.__name__,
|
||||||
mapped_args.get("args"),
|
mapped_args.get("args"),
|
||||||
offender_filename,
|
offender_filename,
|
||||||
offender_lineno,
|
offender_lineno,
|
||||||
offender_line,
|
offender_line,
|
||||||
|
"".join(traceback.format_stack(f=offender_frame)),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -79,10 +82,9 @@ def raise_for_blocking_call(
|
||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
(
|
"Detected blocking call to %s inside the event loop by %sintegration '%s' "
|
||||||
"Detected blocking call to %s inside the event loop by %sintegration '%s' "
|
"at %s, line %s: %s (offender: %s, line %s: %s), please %s\n"
|
||||||
"at %s, line %s: %s (offender: %s, line %s: %s), please %s"
|
"Traceback (most recent call last):\n%s",
|
||||||
),
|
|
||||||
func.__name__,
|
func.__name__,
|
||||||
"custom " if integration_frame.custom_integration else "",
|
"custom " if integration_frame.custom_integration else "",
|
||||||
integration_frame.integration,
|
integration_frame.integration,
|
||||||
|
@ -93,6 +95,7 @@ def raise_for_blocking_call(
|
||||||
offender_lineno,
|
offender_lineno,
|
||||||
offender_line,
|
offender_line,
|
||||||
report_issue,
|
report_issue,
|
||||||
|
"".join(traceback.format_stack(f=integration_frame.frame)),
|
||||||
)
|
)
|
||||||
|
|
||||||
if strict:
|
if strict:
|
||||||
|
|
|
@ -1689,8 +1689,10 @@ def help_test_all(module: ModuleType) -> None:
|
||||||
def extract_stack_to_frame(extract_stack: list[Mock]) -> FrameType:
|
def extract_stack_to_frame(extract_stack: list[Mock]) -> FrameType:
|
||||||
"""Convert an extract stack to a frame list."""
|
"""Convert an extract stack to a frame list."""
|
||||||
stack = list(extract_stack)
|
stack = list(extract_stack)
|
||||||
|
_globals = globals()
|
||||||
for frame in stack:
|
for frame in stack:
|
||||||
frame.f_back = None
|
frame.f_back = None
|
||||||
|
frame.f_globals = _globals
|
||||||
frame.f_code.co_filename = frame.filename
|
frame.f_code.co_filename = frame.filename
|
||||||
frame.f_lineno = int(frame.lineno)
|
frame.f_lineno = int(frame.lineno)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ async def test_extract_frame_integration(
|
||||||
integration_frame = frame.get_integration_frame()
|
integration_frame = frame.get_integration_frame()
|
||||||
assert integration_frame == frame.IntegrationFrame(
|
assert integration_frame == frame.IntegrationFrame(
|
||||||
custom_integration=False,
|
custom_integration=False,
|
||||||
_frame=mock_integration_frame,
|
frame=mock_integration_frame,
|
||||||
integration="hue",
|
integration="hue",
|
||||||
module=None,
|
module=None,
|
||||||
relative_filename="homeassistant/components/hue/light.py",
|
relative_filename="homeassistant/components/hue/light.py",
|
||||||
|
@ -42,7 +42,7 @@ async def test_extract_frame_resolve_module(
|
||||||
|
|
||||||
assert integration_frame == frame.IntegrationFrame(
|
assert integration_frame == frame.IntegrationFrame(
|
||||||
custom_integration=True,
|
custom_integration=True,
|
||||||
_frame=ANY,
|
frame=ANY,
|
||||||
integration="test_integration_frame",
|
integration="test_integration_frame",
|
||||||
module="custom_components.test_integration_frame",
|
module="custom_components.test_integration_frame",
|
||||||
relative_filename="custom_components/test_integration_frame/__init__.py",
|
relative_filename="custom_components/test_integration_frame/__init__.py",
|
||||||
|
@ -98,7 +98,7 @@ async def test_extract_frame_integration_with_excluded_integration(
|
||||||
|
|
||||||
assert integration_frame == frame.IntegrationFrame(
|
assert integration_frame == frame.IntegrationFrame(
|
||||||
custom_integration=False,
|
custom_integration=False,
|
||||||
_frame=correct_frame,
|
frame=correct_frame,
|
||||||
integration="mdns",
|
integration="mdns",
|
||||||
module=None,
|
module=None,
|
||||||
relative_filename="homeassistant/components/mdns/light.py",
|
relative_filename="homeassistant/components/mdns/light.py",
|
||||||
|
|
|
@ -1271,7 +1271,7 @@ async def test_hass_components_use_reported(
|
||||||
)
|
)
|
||||||
integration_frame = frame.IntegrationFrame(
|
integration_frame = frame.IntegrationFrame(
|
||||||
custom_integration=True,
|
custom_integration=True,
|
||||||
_frame=mock_integration_frame,
|
frame=mock_integration_frame,
|
||||||
integration="test_integration_frame",
|
integration="test_integration_frame",
|
||||||
module="custom_components.test_integration_frame",
|
module="custom_components.test_integration_frame",
|
||||||
relative_filename="custom_components/test_integration_frame/__init__.py",
|
relative_filename="custom_components/test_integration_frame/__init__.py",
|
||||||
|
@ -1969,7 +1969,7 @@ async def test_hass_helpers_use_reported(
|
||||||
"""Test that use of hass.components is reported."""
|
"""Test that use of hass.components is reported."""
|
||||||
integration_frame = frame.IntegrationFrame(
|
integration_frame = frame.IntegrationFrame(
|
||||||
custom_integration=True,
|
custom_integration=True,
|
||||||
_frame=mock_integration_frame,
|
frame=mock_integration_frame,
|
||||||
integration="test_integration_frame",
|
integration="test_integration_frame",
|
||||||
module="custom_components.test_integration_frame",
|
module="custom_components.test_integration_frame",
|
||||||
relative_filename="custom_components/test_integration_frame/__init__.py",
|
relative_filename="custom_components/test_integration_frame/__init__.py",
|
||||||
|
|
|
@ -27,6 +27,7 @@ async def test_raise_for_blocking_call_async_non_strict_core(
|
||||||
"""Test non_strict_core raise_for_blocking_call detects from event loop without integration context."""
|
"""Test non_strict_core raise_for_blocking_call detects from event loop without integration context."""
|
||||||
haloop.raise_for_blocking_call(banned_function, strict_core=False)
|
haloop.raise_for_blocking_call(banned_function, strict_core=False)
|
||||||
assert "Detected blocking call to banned_function" in caplog.text
|
assert "Detected blocking call to banned_function" in caplog.text
|
||||||
|
assert "Traceback (most recent call last)" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
async def test_raise_for_blocking_call_async_integration(
|
async def test_raise_for_blocking_call_async_integration(
|
||||||
|
@ -130,6 +131,11 @@ async def test_raise_for_blocking_call_async_integration_non_strict(
|
||||||
"please create a bug report at https://github.com/home-assistant/core/issues?"
|
"please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||||
"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+hue%22" in caplog.text
|
"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+hue%22" in caplog.text
|
||||||
)
|
)
|
||||||
|
assert "Traceback (most recent call last)" in caplog.text
|
||||||
|
assert (
|
||||||
|
'File "/home/paulus/homeassistant/components/hue/light.py", line 23'
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_raise_for_blocking_call_async_custom(
|
async def test_raise_for_blocking_call_async_custom(
|
||||||
|
@ -182,6 +188,11 @@ async def test_raise_for_blocking_call_async_custom(
|
||||||
"please create a bug report at https://github.com/home-assistant/core/issues?"
|
"please create a bug report at https://github.com/home-assistant/core/issues?"
|
||||||
"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+hue%22"
|
"q=is%3Aopen+is%3Aissue+label%3A%22integration%3A+hue%22"
|
||||||
) in caplog.text
|
) in caplog.text
|
||||||
|
assert "Traceback (most recent call last)" in caplog.text
|
||||||
|
assert (
|
||||||
|
'File "/home/paulus/config/custom_components/hue/light.py", line 23'
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_raise_for_blocking_call_sync(
|
async def test_raise_for_blocking_call_sync(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue