Files
ad_toolbox/logger_interface.py
T
2026-09-27 22:54:08 +02:00

82 lines
2.5 KiB
Python

import traceback
from contextlib import contextmanager
from contextvars import ContextVar
from uuid import uuid4
_ACTIVE_LOG_GROUP = ContextVar('appdaemon_log_group', default=None)
@contextmanager
def log_group(kind, label=None, *, inherit=True):
"""Tag LoggerInterface messages in this synchronous operation with one group ID."""
parent = _ACTIVE_LOG_GROUP.get() if inherit else None
group = parent or {
'id': uuid4().hex[:12],
'kind': kind,
'label': str(label) if label is not None else '',
}
token = _ACTIVE_LOG_GROUP.set(group)
try:
yield group
finally:
_ACTIVE_LOG_GROUP.reset(token)
class LoggerInterface:
def __init__(self):
self.initialized = False
def __init__(self, ad_api, default_log='main_log', mute=False):
self.initialize_logger_interface(ad_api, default_log, mute)
def initialize_logger_interface(self, ad_api, default_log='main_log', mute=False):
self.ad_api = ad_api
self.default_log = default_log
self.mute = False
self.initialized = True
def log_group(self, kind, label=None):
return log_group(kind, label)
@staticmethod
def _tag_log_message(message):
group = _ACTIVE_LOG_GROUP.get()
if group is None:
return message
marker = f"[group={group['kind']}:{group['id']}]"
if isinstance(message, str) and marker in message:
return message
return f"{message} {marker}"
def mute_logger(self, mute: bool):
if mute:
self.ad_api.log(self._tag_log_message('Muting logger'), level='INFO', log=self.default_log)
self.mute = bool(mute)
def log_info(self, message):
assert self.initialized
if not self.mute:
self.ad_api.log(self._tag_log_message(message), level='INFO', log=self.default_log)
def log_warning(self, message):
assert self.initialized
self.ad_api.log(self._tag_log_message(message), level='WARNING', log=self.default_log)
def log_error(self, message, stop_app=False, dump_stack=False):
assert self.initialized
if dump_stack:
stack = '\n'
for line in traceback.format_stack()[:-1]:
stack += line.strip() + '\n'
else:
stack = ''
message = self._tag_log_message(message)
self.ad_api.log(message, level='ERROR', log=self.default_log)
self.ad_api.log(message + stack, level='ERROR', log='error_log')
if stop_app:
self.stop_app(self.name)