89 lines
4.2 KiB
Python
89 lines
4.2 KiB
Python
# [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
|