import logging import os import sys from logging.handlers import RotatingFileHandler from pathlib import Path BASE_DIR = Path(__file__).resolve().parent DEFAULT_LOG_DIR = BASE_DIR / "logs" DEFAULT_LOG_FILE_NAME = "gmv_sync.log" LOGGER_NAME = "gmv_analytics" LOG_FORMAT = "[%(asctime)s] %(message)s" DATE_FORMAT = "%Y-%m-%d %H:%M:%S" _IS_CONFIGURED = False def _build_handlers() -> list[logging.Handler]: log_dir = Path(os.getenv("LOG_DIR", str(DEFAULT_LOG_DIR))) log_file_name = os.getenv("LOG_FILE_NAME", DEFAULT_LOG_FILE_NAME) log_file_path = log_dir / log_file_name log_dir.mkdir(parents=True, exist_ok=True) formatter = logging.Formatter(LOG_FORMAT, datefmt=DATE_FORMAT) console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(formatter) file_handler = RotatingFileHandler( log_file_path, maxBytes=int(os.getenv("LOG_MAX_BYTES", str(10 * 1024 * 1024))), backupCount=int(os.getenv("LOG_BACKUP_COUNT", "7")), encoding="utf-8", ) file_handler.setFormatter(formatter) return [console_handler, file_handler] def setup_logging(force: bool = False) -> logging.Logger: global _IS_CONFIGURED logger = logging.getLogger(LOGGER_NAME) if _IS_CONFIGURED and not force: return logger level_name = os.getenv("LOG_LEVEL", "INFO").strip().upper() level = getattr(logging, level_name, logging.INFO) handlers = _build_handlers() if force: for handler in list(logger.handlers): logger.removeHandler(handler) handler.close() logger.setLevel(level) logger.propagate = False for handler in handlers: logger.addHandler(handler) _IS_CONFIGURED = True return logger def get_logger() -> logging.Logger: return setup_logging()