1
0
mirror of https://github.com/elisspace/core.git synced 2026-08-29 15:43:55 +00:00

Add profiler service to investigate ssl object leaks

related issue https://github.com/aio-libs/aiohttp/issues/7252

related PR https://github.com/home-assistant/core/pull/93013
This commit is contained in:
J. Nick Koston
2023-05-13 09:21:23 +09:00
parent 18a7c59e1c
commit bc2d3e99e6
2 changed files with 54 additions and 15 deletions

View File

@@ -4,7 +4,6 @@ from asyncio.sslproto import SSLProtocol, _SSLProtocolTransport
from contextlib import suppress
from datetime import timedelta
from functools import _lru_cache_wrapper
import json
import logging
import reprlib
import ssl
@@ -22,10 +21,8 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_SCAN_INTERVAL, CONF_TYPE
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.json import ExtendedJSONEncoder
from homeassistant.helpers.service import async_register_admin_service
from .const import DOMAIN
@@ -88,9 +85,6 @@ async def async_setup_entry( # noqa: C901
domain_data = hass.data[DOMAIN] = {}
async def _async_run_profile(call: ServiceCall) -> None:
_LOGGER.warning(
"Modules: %s", json.dumps(sys.modules, indent=2, cls=ExtendedJSONEncoder)
)
async with lock:
await _async_generate_profile(hass, call)
@@ -218,15 +212,6 @@ async def async_setup_entry( # noqa: C901
maybe_lru.get_stats(),
)
_LOGGER.critical(
"Cache stats for LRU template_states: %s",
template.CACHED_TEMPLATE_LRU.get_stats(), # type: ignore[attr-defined]
)
_LOGGER.critical(
"Cache stats for LRU template_states_no_collect: %s",
template.CACHED_TEMPLATE_NO_COLLECT_LRU.get_stats(), # type: ignore[attr-defined]
)
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():

View File

@@ -15,6 +15,7 @@ from homeassistant.components.profiler import (
CONF_SECONDS,
SERVICE_DUMP_LOG_OBJECTS,
SERVICE_LOG_EVENT_LOOP_SCHEDULED,
SERVICE_LOG_SSL,
SERVICE_LOG_THREAD_FRAMES,
SERVICE_LRU_STATS,
SERVICE_MEMORY,
@@ -387,3 +388,56 @@ async def test_log_object_sources(
await hass.services.async_call(
DOMAIN, SERVICE_STOP_LOG_OBJECT_SOURCES, {}, blocking=True
)
async def test_log_ssl(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) -> None:
"""Test logging ssl objects."""
entry = MockConfigEntry(domain=DOMAIN)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
class SSLProtocol:
def __init__(self):
"""Mock an SSLProtocol."""
self._transport = None
class SSLObject:
def __init__(self):
"""Mock an SSLObject."""
self._transport = None
def getpeercert(self, binary_form=False):
"""Mock getpeercert."""
return {"subject": (("commonName", "test"),)}
def server_hostname(self):
"""Mock server_hostname."""
return "test"
class _SSLProtocolTransport:
def __init__(self):
"""Mock an _SSLProtocolTransport."""
ssl_protocol = SSLProtocol()
ssl_object = SSLObject()
ssl_protocol_transport = _SSLProtocolTransport()
assert hass.services.has_service(DOMAIN, SERVICE_LOG_SSL)
def _mock_by_type(type_):
if type_ == "SSLProtocol":
return [ssl_protocol]
if type_ == "SSLObject":
return [ssl_object]
if type_ == "_SSLProtocolTransport":
return [ssl_protocol_transport]
raise ValueError("Unknown type")
with patch("objgraph.by_type", side_effect=_mock_by_type):
await hass.services.async_call(DOMAIN, SERVICE_LOG_SSL, blocking=True)
assert "SSLProtocol" in caplog.text
assert "SSLObject" in caplog.text
assert "_SSLProtocolTransport" in caplog.text