import logging import os import sys import uuid from datetime import datetime from logging.handlers import RotatingFileHandler from pathlib import Path LOG_DIR = Path(__file__).resolve().parent.parent / "logs" LOG_DIR.mkdir(exist_ok=True) LOG_FORMAT = logging.Formatter( "[%(asctime)s] [%(levelname)s] [%(name)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) MAX_LOG_FILES = 20 _root_handler: RotatingFileHandler | None = None _console_handler: logging.StreamHandler | None = None def _init_handlers(): global _root_handler, _console_handler if _root_handler: return ts = datetime.now().strftime("%Y%m%d_%H%M%S") uid = uuid.uuid4().hex[:6] log_file = LOG_DIR / f"turbosu_{ts}_{uid}.log" _root_handler = RotatingFileHandler( log_file, maxBytes=10 * 1024 * 1024, backupCount=20, encoding="utf-8" ) _root_handler.setLevel(logging.DEBUG) _root_handler.setFormatter(LOG_FORMAT) _console_handler = logging.StreamHandler(sys.stdout) _console_handler.setLevel(logging.INFO) _console_handler.setFormatter(LOG_FORMAT) logs = sorted(LOG_DIR.glob("turbosu_*.log*"), key=lambda p: p.stat().st_mtime) while len(logs) > MAX_LOG_FILES: oldest = logs.pop(0) try: oldest.unlink() except OSError: pass def setup_logger(name: str, level: int = logging.DEBUG) -> logging.Logger: _init_handlers() logger = logging.getLogger(name) logger.setLevel(level) logger.propagate = False if not logger.handlers: logger.addHandler(_root_handler) logger.addHandler(_console_handler) return logger def get_logger(name: str) -> logging.Logger: return setup_logger(name)