# [MODULE] Superset Tool Logger Utility # PURPOSE: Предоставляет стандартизированный класс-обертку `SupersetLogger` для настройки и использования логирования в проекте. # COHERENCE: Модуль согласован со стандартной библиотекой `logging`, расширяя ее для нужд проекта. import logging import sys from datetime import datetime from pathlib import Path from typing import Optional # CONTRACT: # PURPOSE: Обеспечивает унифицированную настройку логгера с выводом в консоль и/или файл. # PRECONDITIONS: # - `name` должен быть строкой. # - `level` должен быть валидным уровнем логирования (например, `logging.INFO`). # POSTCONDITIONS: # - Создает и настраивает логгер с указанным именем и уровнем. # - Добавляет обработчики для вывода в файл (если указан `log_dir`) и в консоль (если `console=True`). # - Очищает все предыдущие обработчики для данного логгера, чтобы избежать дублирования. # PARAMETERS: # - name: str - Имя логгера. # - log_dir: Optional[Path] - Директория для сохранения лог-файлов. # - level: int - Уровень логирования. # - console: bool - Флаг для включения вывода в консоль. class SupersetLogger: def __init__( self, name: str = "superset_tool", log_dir: Optional[Path] = None, level: int = logging.INFO, console: bool = True ): self.logger = logging.getLogger(name) self.logger.setLevel(level) formatter = logging.Formatter( '%(asctime)s - %(levelname)s - %(message)s' ) # [ANCHOR] HANDLER_RESET # Очищаем существующие обработчики, чтобы избежать дублирования вывода при повторной инициализации. if self.logger.hasHandlers(): self.logger.handlers.clear() # [ANCHOR] FILE_HANDLER if log_dir: log_dir.mkdir(parents=True, exist_ok=True) timestamp = datetime.now().strftime("%Y%m%d") file_handler = logging.FileHandler( log_dir / f"{name}_{timestamp}.log", encoding='utf-8' ) file_handler.setFormatter(formatter) self.logger.addHandler(file_handler) # [ANCHOR] CONSOLE_HANDLER if console: console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(formatter) self.logger.addHandler(console_handler) # CONTRACT: # PURPOSE: (HELPER) Генерирует строку с текущей датой для имени лог-файла. # RETURN: str - Отформатированная дата (YYYYMMDD). def _get_timestamp(self) -> str: return datetime.now().strftime("%Y%m%d") # END_FUNCTION__get_timestamp # [INTERFACE] Методы логирования def info(self, message: str, extra: Optional[dict] = None, exc_info: bool = False): self.logger.info(message, extra=extra, exc_info=exc_info) def error(self, message: str, extra: Optional[dict] = None, exc_info: bool = False): self.logger.error(message, extra=extra, exc_info=exc_info) def warning(self, message: str, extra: Optional[dict] = None, exc_info: bool = False): self.logger.warning(message, extra=extra, exc_info=exc_info) def critical(self, message: str, extra: Optional[dict] = None, exc_info: bool = False): self.logger.critical(message, extra=extra, exc_info=exc_info) def debug(self, message: str, extra: Optional[dict] = None, exc_info: bool = False): self.logger.debug(message, extra=extra, exc_info=exc_info) def exception(self, message: str, *args, **kwargs): self.logger.exception(message, *args, **kwargs) # END_CLASS_SupersetLogger # END_MODULE_logger