Saqr/saqr/utils/logger.py

63 lines
1.6 KiB
Python

from __future__ import annotations
import json
import logging
from typing import Dict
from saqr.core.paths import CONFIG_DIR, LOGS_DIR
_LOGGER_CACHE: Dict[str, logging.Logger] = {}
def _load_log_cfg() -> dict:
cfg_path = CONFIG_DIR / "logging.json"
try:
with open(cfg_path, "r") as f:
return json.load(f)
except Exception:
return {}
def _level_from_name(name: str) -> int:
return getattr(logging, str(name).upper(), logging.INFO)
def get_logger(category: str, name: str) -> logging.Logger:
"""Return a cached logger that writes to runtime/logs/<category>/<name>.log."""
key = f"{category}.{name}"
if key in _LOGGER_CACHE:
return _LOGGER_CACHE[key]
log_cfg = _load_log_cfg()
log_dir = LOGS_DIR / category
log_dir.mkdir(parents=True, exist_ok=True)
logger = logging.getLogger(key)
level_name = (
log_cfg.get("categories", {}).get(category)
or log_cfg.get("level", "INFO")
)
logger.setLevel(_level_from_name(level_name))
logger.propagate = False
if logger.handlers:
logger.handlers.clear()
fmt = logging.Formatter(
log_cfg.get("format", "%(asctime)s | %(name)s | %(levelname)s | %(message)s")
)
if log_cfg.get("file", True):
fh = logging.FileHandler(log_dir / f"{name}.log", encoding="utf-8")
fh.setFormatter(fmt)
logger.addHandler(fh)
if log_cfg.get("console", False):
sh = logging.StreamHandler()
sh.setFormatter(fmt)
logger.addHandler(sh)
_LOGGER_CACHE[key] = logger
return logger