Skip to content

Commit

Permalink
Avoid useless stat() syscalls for every logger record (#114987)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
bdraco committed Apr 6, 2024
1 parent 00db97a commit bf5cf38
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
15 changes: 14 additions & 1 deletion homeassistant/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand All @@ -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.
Expand Down
10 changes: 10 additions & 0 deletions tests/test_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -1398,3 +1398,13 @@ async def async_setup(hass, config):
# 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
)

0 comments on commit bf5cf38

Please sign in to comment.