From 9dc936f8b9a443a9052210c0b6d6e89369193f48 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 28 Mar 2023 12:02:35 -1000 Subject: [PATCH] Add sqlalchemy LRUs to the profiler lru service (#90428) --- homeassistant/components/profiler/__init__.py | 12 +++++++++++- tests/components/profiler/test_init.py | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/profiler/__init__.py b/homeassistant/components/profiler/__init__.py index b838f67d02e..27e302f47c4 100644 --- a/homeassistant/components/profiler/__init__.py +++ b/homeassistant/components/profiler/__init__.py @@ -35,6 +35,7 @@ SERVICE_LOG_THREAD_FRAMES = "log_thread_frames" SERVICE_LOG_EVENT_LOOP_SCHEDULED = "log_event_loop_scheduled" _LRU_CACHE_WRAPPER_OBJECT = _lru_cache_wrapper.__name__ +_SQLALCHEMY_LRU_OBJECT = "LRUCache" _KNOWN_LRU_CLASSES = ( "EventDataManager", @@ -67,7 +68,9 @@ LOG_INTERVAL_SUB = "log_interval_subscription" _LOGGER = logging.getLogger(__name__) -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: +async def async_setup_entry( # noqa: C901 + hass: HomeAssistant, entry: ConfigEntry +) -> bool: """Set up Profiler from a config entry.""" lock = asyncio.Lock() domain_data = hass.data[DOMAIN] = {} @@ -176,6 +179,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: maybe_lru.get_stats(), ) + for lru in objgraph.by_type(_SQLALCHEMY_LRU_OBJECT): + if (data := getattr(lru, "_data", None)) and isinstance(data, dict): + for key, value in dict(data).items(): + _LOGGER.critical( + "Cache data for sqlalchemy LRUCache %s: %s: %s", lru, key, value + ) + persistent_notification.create( hass, ( diff --git a/tests/components/profiler/test_init.py b/tests/components/profiler/test_init.py index af642c779e1..9466660dca4 100644 --- a/tests/components/profiler/test_init.py +++ b/tests/components/profiler/test_init.py @@ -11,6 +11,7 @@ import pytest from homeassistant.components.profiler import ( _LRU_CACHE_WRAPPER_OBJECT, + _SQLALCHEMY_LRU_OBJECT, CONF_SECONDS, SERVICE_DUMP_LOG_OBJECTS, SERVICE_LOG_EVENT_LOOP_SCHEDULED, @@ -254,9 +255,17 @@ async def test_lru_stats(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) domain_data = DomainData() assert hass.services.has_service(DOMAIN, SERVICE_LRU_STATS) + class LRUCache: + def __init__(self): + self._data = {"sqlalchemy_test": 1} + + sqlalchemy_lru_cache = LRUCache() + def _mock_by_type(type_): if type_ == _LRU_CACHE_WRAPPER_OBJECT: return [_dummy_test_lru_stats] + if type_ == _SQLALCHEMY_LRU_OBJECT: + return [sqlalchemy_lru_cache] return [domain_data] with patch("objgraph.by_type", side_effect=_mock_by_type): @@ -266,3 +275,4 @@ async def test_lru_stats(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) assert "(0, 0)" in caplog.text assert "_dummy_test_lru_stats" in caplog.text assert "CacheInfo" in caplog.text + assert "sqlalchemy_test" in caplog.text