From bf5cf382dc083fc5eb32d09d527a52a0675f6ef7 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 5 Apr 2024 16:00:09 -1000 Subject: [PATCH] Avoid useless stat() syscalls for every logger record (#114987) * Avoid useless stat() syscalls for every logger record shouldRollover will always return False since we do not use maxBytes as we are only using RotatingFileHandler for the backupCount option. Since every log record will stat the log file to see if it exists and if its a normal file, we can override the shouldRollover to reduce the logging overhead quite a bit https://github.com/python/cpython/blob/1d3225ae056245da75e4a443ccafcc8f4f982cf2/Lib/logging/handlers.py#L189 * assert False is False --- homeassistant/bootstrap.py | 15 ++++++++++++++- tests/test_bootstrap.py | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 373c5c0f38c..afb364e6d2f 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -574,7 +574,7 @@ def async_enable_logging( err_log_path, when="midnight", backupCount=log_rotate_days ) else: - err_handler = logging.handlers.RotatingFileHandler( + err_handler = _RotatingFileHandlerWithoutShouldRollOver( err_log_path, backupCount=1 ) @@ -598,6 +598,19 @@ def async_enable_logging( async_activate_log_queue_handler(hass) +class _RotatingFileHandlerWithoutShouldRollOver(logging.handlers.RotatingFileHandler): + """RotatingFileHandler that does not check if it should roll over on every log.""" + + def shouldRollover(self, record: logging.LogRecord) -> bool: + """Never roll over. + + The shouldRollover check is expensive because it has to stat + the log file for every log record. Since we do not set maxBytes + the result of this check is always False. + """ + return False + + async def async_mount_local_lib_path(config_dir: str) -> str: """Add local library to Python Path. diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py index de82aba9911..12eb52c06f4 100644 --- a/tests/test_bootstrap.py +++ b/tests/test_bootstrap.py @@ -1398,3 +1398,13 @@ async def test_setup_does_base_platforms_first(hass: HomeAssistant) -> None: # only that they are setup before other integrations. assert set(order[1:3]) == {"sensor", "binary_sensor"} assert order[3:] == ["root", "first_dep", "second_dep"] + + +def test_should_rollover_is_always_false(): + """Test that shouldRollover always returns False.""" + assert ( + bootstrap._RotatingFileHandlerWithoutShouldRollOver( + "any.log", delay=True + ).shouldRollover(Mock()) + is False + )