Use built in queue log handlers to avoid formatting logs in the event loop (#35633)

* Use built in queue log handlers to avoid formatting logs in the event loop

Logging is now formatted and written in another thread to
ensure there is minimal impact on the event loop when
a log message is processed.

This change replaces the existing AsyncHandler log handler
as python 3.7+ now offers an off the shelf solution

* add a simple test

* s/async_migrate_log_handlers_to_queue/async_activate_log_queue_handler/g
This commit is contained in:
J. Nick Koston 2020-05-16 09:29:58 -05:00 committed by GitHub
parent d3ae8a938c
commit 73616520c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 140 deletions

View file

@ -14,7 +14,6 @@ import voluptuous as vol
from homeassistant import config as conf_util, config_entries, core, loader
from homeassistant.components import http
from homeassistant.const import (
EVENT_HOMEASSISTANT_CLOSE,
EVENT_HOMEASSISTANT_STOP,
REQUIRED_NEXT_PYTHON_DATE,
REQUIRED_NEXT_PYTHON_VER,
@ -22,7 +21,7 @@ from homeassistant.const import (
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.typing import ConfigType
from homeassistant.setup import DATA_SETUP, async_setup_component
from homeassistant.util.logging import AsyncHandler
from homeassistant.util.logging import async_activate_log_queue_handler
from homeassistant.util.package import async_get_user_site, is_virtual_env
from homeassistant.util.yaml import clear_secret_cache
@ -278,17 +277,8 @@ def async_enable_logging(
err_handler.setLevel(logging.INFO if verbose else logging.WARNING)
err_handler.setFormatter(logging.Formatter(fmt, datefmt=datefmt))
async_handler = AsyncHandler(hass.loop, err_handler)
async def async_stop_async_handler(_: Any) -> None:
"""Cleanup async handler."""
logging.getLogger("").removeHandler(async_handler) # type: ignore
await async_handler.async_close(blocking=True)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, async_stop_async_handler)
logger = logging.getLogger("")
logger.addHandler(async_handler) # type: ignore
logger.addHandler(err_handler)
logger.setLevel(logging.INFO)
# Save the log file location for access by other components.
@ -296,6 +286,8 @@ def async_enable_logging(
else:
_LOGGER.error("Unable to set up error log %s (access denied)", err_log_path)
async_activate_log_queue_handler(hass)
async def async_mount_local_lib_path(config_dir: str) -> str:
"""Add local library to Python Path.