"""Centralized logging configuration for the project. Provides a get_logger(name) helper so modules can get a properly configured logger. """ from __future__ import annotations import logging import logging.handlers import os from typing import Optional LOG_FILENAME = os.path.join(os.path.dirname(os.path.dirname(__file__)), "skee_gap.log") def _configure_root_logger(level: int = logging.DEBUG, logfile: Optional[str] = LOG_FILENAME) -> None: root = logging.getLogger() if root.handlers: return # already configured root.setLevel(level) fmt = logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s") sh = logging.StreamHandler() sh.setLevel(level) sh.setFormatter(fmt) root.addHandler(sh) # try to add file handler where possible try: fh = logging.handlers.RotatingFileHandler(logfile, maxBytes=5 * 1024 * 1024, backupCount=3, encoding="utf-8") fh.setLevel(level) fh.setFormatter(fmt) root.addHandler(fh) except Exception: # allow running without file logging root.debug("Could not create log file handler; continuing without file logging") def get_logger(name: str, level: int = logging.DEBUG) -> logging.Logger: _configure_root_logger(level=level) return logging.getLogger(name)