""" Structured logging configuration. Sets up file + console handlers with proper formatting. """ from __future__ import annotations import logging import logging.handlers import sys from pathlib import Path def configure_logging(log_level: str = "INFO", log_dir: str = "logs") -> None: """Configure root logger with rotating file and console handlers.""" log_path = Path(log_dir) log_path.mkdir(parents=True, exist_ok=True) level = getattr(logging, log_level.upper(), logging.INFO) fmt = logging.Formatter( "%(asctime)s [%(levelname)-8s] %(name)s: %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) # Root logger root = logging.getLogger() root.setLevel(level) root.handlers.clear() # Console handler console = logging.StreamHandler(sys.stdout) console.setFormatter(fmt) console.setLevel(level) root.addHandler(console) # Rotating file handler file_handler = logging.handlers.RotatingFileHandler( log_path / "app.log", maxBytes=10 * 1024 * 1024, # 10 MB backupCount=5, encoding="utf-8", ) file_handler.setFormatter(fmt) file_handler.setLevel(level) root.addHandler(file_handler) # Error-only file error_handler = logging.handlers.RotatingFileHandler( log_path / "errors.log", maxBytes=5 * 1024 * 1024, backupCount=3, encoding="utf-8", ) error_handler.setFormatter(fmt) error_handler.setLevel(logging.ERROR) root.addHandler(error_handler) # Suppress noisy libs logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger("playwright").setLevel(logging.WARNING)