106 lines
4.4 KiB
Python
106 lines
4.4 KiB
Python
# [MODULE] Superset Tool Logger Utility
|
||
# @contract: Этот модуль предоставляет утилиту для настройки логирования в приложении.
|
||
# @semantic_layers:
|
||
# - [CONFIG]: Настройка логгера.
|
||
# - [UTILITY]: Вспомогательные функции.
|
||
# @coherence: Модуль должен быть семантически когерентен со стандартной библиотекой `logging`.
|
||
|
||
import logging
|
||
import sys
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
from typing import Optional
|
||
|
||
# [CONSTANTS]
|
||
|
||
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'
|
||
)
|
||
|
||
# Очищаем существующие обработчики
|
||
if self.logger.handlers:
|
||
for handler in self.logger.handlers[:]:
|
||
self.logger.removeHandler(handler)
|
||
|
||
# Файловый обработчик
|
||
if log_dir:
|
||
log_dir.mkdir(parents=True, exist_ok=True)
|
||
file_handler = logging.FileHandler(
|
||
log_dir / f"{name}_{self._get_timestamp()}.log"
|
||
)
|
||
file_handler.setFormatter(formatter)
|
||
self.logger.addHandler(file_handler)
|
||
|
||
# Консольный обработчик
|
||
if console:
|
||
console_handler = logging.StreamHandler()
|
||
console_handler.setFormatter(formatter)
|
||
self.logger.addHandler(console_handler)
|
||
|
||
def _get_timestamp(self) -> str:
|
||
return datetime.now().strftime("%Y%m%d")
|
||
|
||
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):
|
||
self.logger.exception(message)
|
||
|
||
def setup_logger(name: str, level: int = logging.INFO) -> logging.Logger:
|
||
# [FUNCTION] setup_logger
|
||
# [CONTRACT]
|
||
"""
|
||
Настраивает и возвращает логгер с заданным именем и уровнем.
|
||
|
||
@pre:
|
||
- `name` является непустой строкой.
|
||
- `level` является допустимым уровнем логирования из модуля `logging`.
|
||
@post:
|
||
- Возвращает настроенный экземпляр `logging.Logger`.
|
||
- Логгер имеет StreamHandler, выводящий в sys.stdout.
|
||
- Форматтер логгера включает время, уровень, имя и сообщение.
|
||
@side_effects:
|
||
- Создает и добавляет StreamHandler к логгеру.
|
||
@invariant:
|
||
- Логгер с тем же именем всегда возвращает один и тот же экземпляр.
|
||
"""
|
||
# [CONFIG] Настройка логгера
|
||
# [COHERENCE_CHECK_PASSED] Логика настройки соответствует описанию.
|
||
logger = logging.getLogger(name)
|
||
logger.setLevel(level)
|
||
|
||
# Создание форматтера
|
||
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s')
|
||
|
||
# Проверка наличия существующих обработчиков
|
||
if not logger.handlers:
|
||
# Создание StreamHandler для вывода в sys.stdout
|
||
handler = logging.StreamHandler(sys.stdout)
|
||
handler.setFormatter(formatter)
|
||
logger.addHandler(handler)
|
||
|
||
return logger
|