import logging import os from logging.handlers import RotatingFileHandler # ── Log directory ──────────────────────────────────────────────────────────── LOG_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "logs") os.makedirs(LOG_DIR, exist_ok=True) LOG_FILE = os.path.join(LOG_DIR, "app.log") # ── Formatter ──────────────────────────────────────────────────────────────── LOG_FORMAT = "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s" DATE_FORMAT = "%Y-%m-%d %H:%M:%S" formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT) # ── Handlers ───────────────────────────────────────────────────────────────── # Rotating file: max 10 MB per file, keep 5 backups file_handler = RotatingFileHandler( LOG_FILE, maxBytes=10 * 1024 * 1024, # 10 MB backupCount=5, encoding="utf-8" ) file_handler.setFormatter(formatter) file_handler.setLevel(logging.DEBUG) console_handler = logging.StreamHandler() console_handler.setFormatter(formatter) console_handler.setLevel(logging.INFO) def get_logger(name: str) -> logging.Logger: """ Get a named logger that writes to both console and logs/app.log. Usage: from app.utils.logger import get_logger logger = get_logger(__name__) logger.info("Hello") """ logger = logging.getLogger(name) if not logger.handlers: logger.setLevel(logging.DEBUG) logger.addHandler(file_handler) logger.addHandler(console_handler) logger.propagate = False return logger