Async logging file handler (#4901)
* Async logging file handler * add time rotation handle * new layout * address paulus comments * fix lint
This commit is contained in:
parent
326cc83a17
commit
6d6abab358
2 changed files with 100 additions and 1 deletions
|
@ -20,6 +20,7 @@ import homeassistant.loader as loader
|
|||
import homeassistant.util.package as pkg_util
|
||||
from homeassistant.util.async import (
|
||||
run_coroutine_threadsafe, run_callback_threadsafe)
|
||||
from homeassistant.util.logging import AsyncHandler
|
||||
from homeassistant.util.yaml import clear_secret_cache
|
||||
from homeassistant.const import EVENT_COMPONENT_LOADED, PLATFORM_FORMAT
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
@ -548,8 +549,11 @@ def enable_logging(hass: core.HomeAssistant, verbose: bool=False,
|
|||
err_handler.setFormatter(
|
||||
logging.Formatter('%(asctime)s %(name)s: %(message)s',
|
||||
datefmt='%y-%m-%d %H:%M:%S'))
|
||||
|
||||
async_handler = AsyncHandler(hass.loop, err_handler)
|
||||
|
||||
logger = logging.getLogger('')
|
||||
logger.addHandler(err_handler)
|
||||
logger.addHandler(async_handler)
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
else:
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
"""Logging utilities."""
|
||||
import asyncio
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from .async import run_coroutine_threadsafe
|
||||
|
||||
|
||||
class HideSensitiveDataFilter(logging.Filter):
|
||||
|
@ -15,3 +19,94 @@ class HideSensitiveDataFilter(logging.Filter):
|
|||
record.msg = record.msg.replace(self.text, '*******')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
# pylint: disable=invalid-name
|
||||
class AsyncHandler(object):
|
||||
"""Logging handler wrapper to add a async layer."""
|
||||
|
||||
def __init__(self, loop, handler):
|
||||
"""Initialize async logging handler wrapper."""
|
||||
self.handler = handler
|
||||
self.loop = loop
|
||||
self._queue = asyncio.Queue(loop=loop)
|
||||
self._thread = threading.Thread(target=self._process)
|
||||
|
||||
# Delegate from handler
|
||||
self.setLevel = handler.setLevel
|
||||
self.setFormatter = handler.setFormatter
|
||||
self.addFilter = handler.addFilter
|
||||
self.removeFilter = handler.removeFilter
|
||||
self.filter = handler.filter
|
||||
self.flush = handler.flush
|
||||
self.handle = handler.handle
|
||||
self.handleError = handler.handleError
|
||||
self.format = handler.format
|
||||
|
||||
def close(self):
|
||||
"""Wrap close to handler."""
|
||||
self.emit(None)
|
||||
|
||||
def open(self):
|
||||
"""Wrap open to handler."""
|
||||
self._thread.start()
|
||||
self.handler.open()
|
||||
|
||||
def emit(self, record):
|
||||
"""Process a record."""
|
||||
ident = self.loop.__dict__.get("_thread_ident")
|
||||
|
||||
# inside eventloop
|
||||
if ident is not None and ident == threading.get_ident():
|
||||
self._queue.put_nowait(record)
|
||||
# from a thread/executor
|
||||
else:
|
||||
self.loop.call_soon_threadsafe(self._queue.put_nowait, record)
|
||||
|
||||
def __repr__(self):
|
||||
"""String name of this."""
|
||||
return str(self.handler)
|
||||
|
||||
def _process(self):
|
||||
"""Process log in a thread."""
|
||||
while True:
|
||||
record = run_coroutine_threadsafe(
|
||||
self._queue.get(), self.loop).result()
|
||||
|
||||
if record is None:
|
||||
self.handler.close()
|
||||
return
|
||||
|
||||
self.handler.emit(record)
|
||||
|
||||
def createLock(self):
|
||||
"""Ignore lock stuff."""
|
||||
pass
|
||||
|
||||
def acquire(self):
|
||||
"""Ignore lock stuff."""
|
||||
pass
|
||||
|
||||
def release(self):
|
||||
"""Ignore lock stuff."""
|
||||
pass
|
||||
|
||||
@property
|
||||
def level(self):
|
||||
"""Wrap property level to handler."""
|
||||
return self.handler.level
|
||||
|
||||
@property
|
||||
def formatter(self):
|
||||
"""Wrap property formatter to handler."""
|
||||
return self.handler.formatter
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Wrap property set_name to handler."""
|
||||
return self.handler.get_name()
|
||||
|
||||
@name.setter
|
||||
def set_name(self, name):
|
||||
"""Wrap property get_name to handler."""
|
||||
self.handler.name = name
|
||||
|
|
Loading…
Add table
Reference in a new issue