"""Логирование: в journald (stdout) и одновременно в живой журнал панели. Перенесённые из DMRhub модули зовут `get_logger(__name__)` и пишут через него — эта прослойка позволяет не трогать их код и при этом показывать всё в панели. """ from __future__ import annotations import logging import sys _sink = None # выставляется в main(): объект State с методом .event(kind, text) def set_sink(state) -> None: global _sink _sink = state class _PanelHandler(logging.Handler): """Дублирует записи в журнал панели. Уровень -> цвет строки в интерфейсе.""" _KIND = { logging.DEBUG: "info", logging.INFO: "info", logging.WARNING: "warn", logging.ERROR: "error", logging.CRITICAL: "error", } def emit(self, record: logging.LogRecord) -> None: if _sink is None: return try: _sink.event(self._KIND.get(record.levelno, "info"), record.getMessage()) except Exception: # логирование не должно ронять сервер pass def get_logger(name: str) -> logging.Logger: return logging.getLogger(name) def setup(level: str = "INFO") -> None: root = logging.getLogger() root.setLevel(getattr(logging, level.upper(), logging.INFO)) if not any(isinstance(h, logging.StreamHandler) for h in root.handlers): h = logging.StreamHandler(sys.stdout) h.setFormatter(logging.Formatter("%(asctime)s %(levelname)-7s %(name)s: %(message)s", datefmt="%H:%M:%S")) root.addHandler(h) if not any(isinstance(h, _PanelHandler) for h in root.handlers): root.addHandler(_PanelHandler())