moved default logging config to a yaml file

This commit is contained in:
John Lancaster
2024-05-07 23:31:38 -05:00
parent a7b27cf916
commit d481a1344f
8 changed files with 121 additions and 82 deletions

View File

@@ -1,14 +0,0 @@
version: 1
disable_existing_loggers: false
formatters:
rich:
style: "{"
format: "[room]{appname}[/] {message}"
datefmt: '%H:%M:%S.%f'
handlers:
rich:
formatter: rich
'()': 'rich.logging.RichHandler'
markup: True
show_path: false
omit_repeated_times: false

View File

@@ -0,0 +1,26 @@
version: 1
disable_existing_loggers: false
formatters:
rich:
style: "{"
format: "[room]{room}[/] {message}"
# format: "{message}"
datefmt: '%H:%M:%S.%f'
rich_component:
style: "{"
format: "[room]{room}[/] [component]{component}[/] {message}"
# format: "{message}"
datefmt: '%H:%M:%S.%f'
handlers:
rich:
formatter: rich
'()': 'rich.logging.RichHandler'
markup: True
show_path: false
omit_repeated_times: false
rich_component:
formatter: rich_component
'()': 'rich.logging.RichHandler'
markup: True
show_path: false
omit_repeated_times: false

View File

@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, List
from appdaemon.plugins.mqtt.mqttapi import Mqtt
from .console import setup_component_logging
from . import console
from .model import ButtonConfig
if TYPE_CHECKING:
@@ -20,9 +20,9 @@ class Button(Mqtt):
logger: Logger
async def initialize(self):
self.config = ButtonConfig(**self.args)
self.logger = setup_component_logging(self)
self.app: 'RoomController' = await self.get_app(self.args['app'])
self.logger = console.load_rich_config(self.app.name, type(self).__name__)
self.config = ButtonConfig(**self.args)
self.log(f'Connected to AD app [room]{self.app.name}[/]', level='DEBUG')
self.button = self.config.button

View File

@@ -1,13 +1,13 @@
import json
import logging
import logging.config
from pathlib import Path
import re
from abc import ABC
from dataclasses import asdict
from importlib.resources import files
import yaml
from appdaemon.adapi import ADAPI
from rich.console import Console
from rich.highlighter import RegexHighlighter
from rich.theme import Theme
@@ -46,12 +46,38 @@ class RCHighlighter(RegexHighlighter):
]
def load_rich_config():
with files('room_control.config').joinpath('rich_logging.yaml').open('r') as f:
def load_rich_config(
room: str = None, component: str = None, level: str = 'INFO'
) -> logging.LoggerAdapter:
logger_name = f'Appdaemon.{room}'
if component is not None:
logger_name += f'.{component}'
with files('room_control').joinpath('.rich_logging.yaml').open('r') as f:
RICH_CFG = yaml.safe_load(f)
RICH_CFG['handlers']['rich']['console'] = console
RICH_CFG['handlers']['rich']['highlighter'] = RCHighlighter()
return RICH_CFG
RICH_CFG['handlers']['rich_component']['console'] = console
RICH_CFG['handlers']['rich_component']['highlighter'] = RCHighlighter()
RICH_CFG['loggers'] = {
logger_name: {
'handlers': ['rich' if component is None else 'rich_component'],
'propagate': False,
'level': level,
}
}
extra = {'room': room}
if component is not None:
extra['component'] = component
logging.config.dictConfig(RICH_CFG)
logger = logging.getLogger(logger_name)
adapter = logging.LoggerAdapter(logger, extra)
return adapter
RICH_HANDLER_CFG = {
@@ -163,51 +189,50 @@ def room_logging_config(name: str):
}
def component_logging_config(parent_room: str, component: str):
logger_name = f'AppDaemon.{parent_room}.{component}'
# def component_logging_config(parent_room: str, component: str):
# logger_name = f'AppDaemon.{parent_room}.{component}'
cfg = load_rich_config()
# cfg = load_rich_config()
# LOG_CFG = {
# 'version': 1,
# 'disable_existing_loggers': False,
# 'formatters': {
# 'rich_component': {
# 'style': '{',
# 'format': '[room]{room}[/] [component]{component}[/] {message}',
# 'datefmt': '%H:%M:%S.%f',
# },
# },
# 'handlers': {
# 'rich_component': {
# 'formatter': 'rich_component',
# **RICH_HANDLER_CFG,
# },
# },
# 'loggers': {
# logger_name: {
# # 'level': 'INFO',
# 'propagate': True,
# 'handlers': ['rich_component'],
# }
# },
# }
# return LOG_CFG
LOG_CFG = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'rich_component': {
'style': '{',
'format': '[room]{room}[/] [component]{component}[/] {message}',
'datefmt': '%H:%M:%S.%f',
},
},
'handlers': {
'rich_component': {
'formatter': 'rich_component',
**RICH_HANDLER_CFG,
},
},
'loggers': {
logger_name: {
# 'level': 'INFO',
'propagate': True,
'handlers': ['rich_component'],
}
},
}
return LOG_CFG
# def setup_component_logging(self) -> logging.Logger:
# """Creates a logger for a subcomponent with a RichHandler"""
# component = type(self).__name__
# parent = self.args['app']
# cfg_dict = component_logging_config(parent_room=parent, component=component)
# logger_name = next(iter(cfg_dict['loggers']))
def setup_component_logging(self) -> logging.Logger:
"""Creates a logger for a subcomponent with a RichHandler"""
component = type(self).__name__
parent = self.args['app']
cfg_dict = component_logging_config(parent_room=parent, component=component)
logger_name = next(iter(cfg_dict['loggers']))
try:
logging.config.dictConfig(cfg_dict)
except Exception:
console.print_exception()
else:
logger = logging.getLogger(logger_name)
logger = logging.LoggerAdapter(logger, {'room': parent, 'component': component})
return logger
# try:
# logging.config.dictConfig(cfg_dict)
# except Exception:
# console.print_exception()
# else:
# logger = logging.getLogger(logger_name)
# logger = logging.LoggerAdapter(logger, {'room': parent, 'component': component})
# return logger

View File

@@ -1,18 +1,23 @@
from logging import Logger
from typing import TYPE_CHECKING
from appdaemon.plugins.hass.hassapi import Hass
from room_control import RoomController
from . import console
from .console import setup_component_logging
if TYPE_CHECKING:
from room_control import RoomController
class Door(Hass):
app: 'RoomController'
logger: Logger
async def initialize(self):
self.logger = setup_component_logging(self)
self.app: RoomController = await self.get_app(self.args['app'])
self.app: 'RoomController' = await self.get_app(self.args['app'])
self.logger = console.load_rich_config(
room=self.app.name, component=type(self).__name__
)
self.log(f'Connected to AD app [room]{self.app.name}[/]', level='DEBUG')
await self.listen_state(

View File

@@ -5,9 +5,9 @@ from typing import TYPE_CHECKING, Literal, Optional
from appdaemon.entity import Entity
from appdaemon.plugins.hass.hassapi import Hass
from pydantic import BaseModel, TypeAdapter, ValidationError
from pydantic import BaseModel, ValidationError
from .console import setup_component_logging
from . import console
if TYPE_CHECKING:
from room_control import RoomController
@@ -52,9 +52,8 @@ class Motion(Hass):
return self.sensor_state != self.ref_entity_state
def initialize(self):
self.logger = setup_component_logging(self)
self.app: 'RoomController' = self.get_app(self.args['app'])
self.log(f'Connected to AD app [room]{self.app.name}[/]', level='DEBUG')
self.logger = console.load_rich_config(self.app.name, type(self).__name__)
assert self.entity_exists(self.args['sensor'])
assert self.entity_exists(self.args['ref_entity'])
@@ -86,6 +85,8 @@ class Motion(Hass):
for handle, cb in self.callbacks():
self.log(f'Handle [yellow]{handle[:4]}[/]: {cb.function}', level='DEBUG')
self.log(f'Initialized [bold green]{type(self).__name__}[/]')
def callbacks(self):
"""Returns a dictionary of validated CallbackEntry objects that are associated with this app"""
self_callbacks = self.get_callback_entries().get(self.name, {})

View File

@@ -9,7 +9,7 @@ from appdaemon.entity import Entity
from appdaemon.plugins.hass.hassapi import Hass
from appdaemon.plugins.mqtt.mqttapi import Mqtt
from .console import room_logging_config
from . import console
from .model import ControllerStateConfig, RoomControllerConfig
logger = logging.getLogger(__name__)
@@ -34,14 +34,8 @@ class RoomController(Hass, Mqtt):
assert all(isinstance(s, ControllerStateConfig) for s in new), f'Invalid: {new}'
self._room_config.states = new
def configure_logging(self) -> dict:
logging.config.dictConfig(room_logging_config(self.name))
self.logger = logging.LoggerAdapter(
logging.getLogger(f'AppDaemon.{self.name}'), {'room': self.name}
)
def initialize(self):
self.configure_logging()
self.logger = console.load_rich_config(self.name)
self.app_entities = self.gather_app_entities()
# self.log(f'entities: {self.app_entities}')
self.refresh_state_times()
@@ -206,7 +200,9 @@ class RoomController(Hass, Mqtt):
elif isinstance(scene_kwargs, dict):
self.call_service('scene/apply', **scene_kwargs)
self.log(f'Applied scene:\n{json.dumps(scene_kwargs, indent=2)}', level='DEBUG')
self.log(
f'Applied scene:\n{json.dumps(scene_kwargs, indent=2)}', level='DEBUG'
)
elif scene_kwargs is None:
self.log('No scene, ignoring...')