1
mirror of https://github.com/home-assistant/core synced 2024-09-06 10:29:55 +02:00
ha-core/homeassistant/components/logger/__init__.py

145 lines
3.9 KiB
Python
Raw Normal View History

"""Support for setting the level of logging for components."""
import logging
2015-11-04 21:30:02 +01:00
import voluptuous as vol
from homeassistant.core import ServiceCall, callback
import homeassistant.helpers.config_validation as cv
2019-07-31 21:25:30 +02:00
DOMAIN = "logger"
2015-11-04 21:30:02 +01:00
2019-07-31 21:25:30 +02:00
SERVICE_SET_DEFAULT_LEVEL = "set_default_level"
SERVICE_SET_LEVEL = "set_level"
2015-11-04 21:30:02 +01:00
LOGSEVERITY = {
2019-07-31 21:25:30 +02:00
"CRITICAL": 50,
"FATAL": 50,
"ERROR": 40,
"WARNING": 30,
"WARN": 30,
"INFO": 20,
"DEBUG": 10,
"NOTSET": 0,
2015-11-04 21:30:02 +01:00
}
DEFAULT_LOGSEVERITY = "DEBUG"
2019-07-31 21:25:30 +02:00
LOGGER_DEFAULT = "default"
LOGGER_LOGS = "logs"
LOGGER_FILTERS = "filters"
2015-11-04 21:30:02 +01:00
2019-07-31 21:25:30 +02:00
ATTR_LEVEL = "level"
2016-09-20 06:12:56 +02:00
_VALID_LOG_LEVEL = vol.All(vol.Upper, vol.In(LOGSEVERITY))
SERVICE_SET_DEFAULT_LEVEL_SCHEMA = vol.Schema({ATTR_LEVEL: _VALID_LOG_LEVEL})
SERVICE_SET_LEVEL_SCHEMA = vol.Schema({cv.string: _VALID_LOG_LEVEL})
2019-07-31 21:25:30 +02:00
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Optional(LOGGER_DEFAULT): _VALID_LOG_LEVEL,
vol.Optional(LOGGER_LOGS): vol.Schema({cv.string: _VALID_LOG_LEVEL}),
vol.Optional(LOGGER_FILTERS): vol.Schema({cv.string: [cv.is_regex]}),
2019-07-31 21:25:30 +02:00
}
)
},
extra=vol.ALLOW_EXTRA,
)
2015-11-04 21:30:02 +01:00
async def async_setup(hass, config):
"""Set up the logger component."""
hass.data[DOMAIN] = {}
logging.setLoggerClass(_get_logger_class(hass.data[DOMAIN]))
2015-11-04 21:30:02 +01:00
@callback
def set_default_log_level(level):
"""Set the default log level for components."""
_set_log_level(logging.getLogger(""), level)
2015-11-04 21:30:02 +01:00
@callback
def set_log_levels(logpoints):
"""Set the specified log levels."""
hass.data[DOMAIN].update(logpoints)
for key, value in logpoints.items():
_set_log_level(logging.getLogger(key), value)
2015-11-06 22:51:33 +01:00
# Set default log severity
set_default_log_level(config[DOMAIN].get(LOGGER_DEFAULT, DEFAULT_LOGSEVERITY))
if LOGGER_LOGS in config[DOMAIN]:
set_log_levels(config[DOMAIN][LOGGER_LOGS])
if LOGGER_FILTERS in config[DOMAIN]:
for key, value in config[DOMAIN][LOGGER_FILTERS].items():
logger = logging.getLogger(key)
_add_log_filter(logger, value)
@callback
def async_service_handler(service: ServiceCall) -> None:
"""Handle logger services."""
if service.service == SERVICE_SET_DEFAULT_LEVEL:
set_default_log_level(service.data.get(ATTR_LEVEL))
else:
set_log_levels(service.data)
hass.services.async_register(
2019-07-31 21:25:30 +02:00
DOMAIN,
SERVICE_SET_DEFAULT_LEVEL,
async_service_handler,
schema=SERVICE_SET_DEFAULT_LEVEL_SCHEMA,
)
hass.services.async_register(
2019-07-31 21:25:30 +02:00
DOMAIN,
SERVICE_SET_LEVEL,
async_service_handler,
schema=SERVICE_SET_LEVEL_SCHEMA,
)
2015-11-04 21:30:02 +01:00
return True
def _set_log_level(logger, level):
"""Set the log level.
Any logger fetched before this integration is loaded will use old class.
"""
getattr(logger, "orig_setLevel", logger.setLevel)(LOGSEVERITY[level])
def _add_log_filter(logger, patterns):
"""Add a Filter to the logger based on a regexp of the filter_str."""
def filter_func(logrecord):
return not any(p.search(logrecord.getMessage()) for p in patterns)
logger.addFilter(filter_func)
def _get_logger_class(hass_overrides):
"""Create a logger subclass.
logging.setLoggerClass checks if it is a subclass of Logger and
so we cannot use partial to inject hass_overrides.
"""
class HassLogger(logging.Logger):
"""Home Assistant aware logger class."""
def setLevel(self, level) -> None:
"""Set the log level unless overridden."""
if self.name in hass_overrides:
return
super().setLevel(level)
# pylint: disable=invalid-name
def orig_setLevel(self, level) -> None:
"""Set the log level."""
super().setLevel(level)
return HassLogger