import logging import logging.handlers import platform import os from typing import List, Optional # Дополнительная проверка для ОС Windows if platform.system() == "Windows": os.system('color') class CustomFormatter(logging.Formatter): COLORS = { "black" : "\x1b[30m", "red" : "\x1b[31m", "green" : "\x1b[32m", "yellow" : "\x1b[33m", "blue" : "\x1b[34m", "magenta" : "\x1b[35m", "cyan" : "\x1b[36m", "white" : "\x1b[37m", "reset": "\x1b[0m" } FORMATS = { logging.DEBUG: COLORS["green"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"], logging.INFO: COLORS["magenta"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"], logging.WARNING: COLORS["yellow"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"], logging.ERROR: COLORS["red"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"], logging.CRITICAL: COLORS["cyan"] + "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)" + COLORS["reset"] } def __init__(self): super().__init__(fmt="%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)") def format(self, record: logging.LogRecord) -> str: log_fmt = self.FORMATS.get(record.levelno) if log_fmt: self._style._fmt = log_fmt return super().format(record) class MultiLevelFilter(logging.Filter): def __init__(self, levels: List[int]): self.levels = levels def filter(self, record: logging.LogRecord) -> bool: return record.levelno in self.levels class LevelFilter(logging.Filter): def __init__(self, level: int): self.level = level def filter(self, record: logging.LogRecord) -> bool: return record.levelno == self.level class LoggerManager: LEVEL_MAPPING = { 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'WARNING': logging.WARNING, 'ERROR': logging.ERROR, 'CRITICAL': logging.CRITICAL } def __init__(self, name: str, level: int = logging.DEBUG, log_to_file: bool = False, file_name: str = 'app.log'): if not isinstance(name, str) or not name.strip(): print(f"Некорректное имя логгера: '{name}'. Устанавливается имя по умолчанию 'DefaultLogger'.") name = "DefaultLogger" self.logger = logging.getLogger(name) self.logger.setLevel(level) self.console_handler: Optional[logging.StreamHandler] = None self.file_handler: Optional[logging.FileHandler] = None self.log_filter: Optional[logging.Filter] = None self.setup_console_handler(level) if log_to_file: self.setup_file_handler(level, file_name) def setup_console_handler(self, level: int): """Настройка консольного обработчика и форматтера""" self.console_handler = logging.StreamHandler() self.console_handler.setLevel(level) self.console_handler.setFormatter(CustomFormatter()) self.logger.addHandler(self.console_handler) def setup_file_handler(self, level: int, file_name: str): """Настройка обработчика с ротацией файлов""" try: self.file_handler = logging.handlers.RotatingFileHandler( file_name, maxBytes=1024*1024, # Максимальный размер файла (1MB) #maxBytes=1024, # Максимальный размер файла (1кб) backupCount=5 # Количество ротируемых файлов ) self.file_handler.setLevel(level) file_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)") self.file_handler.setFormatter(file_formatter) self.logger.addHandler(self.file_handler) except Exception as e: self.logger.error(f"Ошибка при настройке файлового логгера с ротацией: {e}") raise def enable_console_logging(self): """Включение логирования в консоль""" if self.console_handler: self.console_handler.setLevel(self.logger.level) self.logger.info("Логирование в консоль включено") def disable_console_logging(self): """Отключение логирования в консоль""" if self.console_handler: self.console_handler.setLevel(logging.CRITICAL + 1) # Уровень выше CRITICAL, чтобы игнорировать все сообщения self.logger.info("Логирование в консоль отключено") def enable_logging(self): """Включение логирования""" self.logger.disabled = False self.logger.info("Логирование включено") def disable_logging(self): """Отключение логирования""" self.logger.disabled = True self.logger.info("Логирование отключено") def enable_file_logging(self, file_name: str = 'app.log', log_dir: str = 'logs'): if not os.path.exists(log_dir): os.makedirs(log_dir) log_path = os.path.join(log_dir, file_name) if self.file_handler: self.logger.removeHandler(self.file_handler) self.file_handler.close() self.setup_file_handler(self.logger.level, log_path) self.logger.info(f"Логирование в файл '{log_path}' включено") def disable_file_logging(self): """Отключение логирования в файл""" if self.file_handler: self.logger.removeHandler(self.file_handler) self.file_handler.close() self.file_handler = None self.logger.info("Логирование в файл отключено") def set_level(self, level: str): """Установка уровня логирования""" if level in self.LEVEL_MAPPING: self.logger.setLevel(self.LEVEL_MAPPING[level]) if self.console_handler: self.console_handler.setLevel(self.LEVEL_MAPPING[level]) if self.file_handler: self.file_handler.setLevel(self.LEVEL_MAPPING[level]) self.logger.info(f"Уровень логирования установлен на {level}") else: self.logger.error(f"Некорректный уровень логирования: {level}. Используйте один из: {list(self.LEVEL_MAPPING.keys())}") def set_filter(self, level: str): """Установка фильтра для логирования""" if level in self.LEVEL_MAPPING: self.clear_filter() self.log_filter = LevelFilter(self.LEVEL_MAPPING[level]) self.logger.addFilter(self.log_filter) self.logger.info(f"Фильтр уровня логирования установлен на {level}") else: self.logger.error(f"Некорректный уровень фильтра: {level}. Используйте один из: {list(self.LEVEL_MAPPING.keys())}") def set_filter_list(self, levels: List[str]): """Установка списка фильтров для логирования""" if not levels: self.logger.error("Список уровней фильтра не должен быть пустым.") return valid_levels = [self.LEVEL_MAPPING[level] for level in levels if level in self.LEVEL_MAPPING] if not valid_levels: self.logger.error(f"Некорректные уровни фильтра: {levels}. Используйте один из: {list(self.LEVEL_MAPPING.keys())}") return self.clear_filter() self.log_filter = MultiLevelFilter(valid_levels) self.logger.addFilter(self.log_filter) self.logger.info(f"Фильтр уровней логирования установлен на {levels}") def reset_level(self): """Сброс уровня логирования до уровня DEBUG""" self.set_level('DEBUG') def clear_filter(self): """Очистка установленного фильтра""" if self.log_filter: self.logger.removeFilter(self.log_filter) self.log_filter = None self.logger.info("Фильтр логирования очищен") if __name__ == "__main__": import time import datetime logger_manager = LoggerManager("TestLogger") #logger_manager.enable_console_logging() # Включение логирования в консоль #logger_manager.disable_console_logging() # Отключение логирования в консоль #logger_manager.disable_logging() # Отключение логирования #logger_manager.enable_logging() # Включение логирования #logger_manager.set_level('INFO') # Установка уровня логирования на INFO #logger_manager.set_filter_list(['DEBUG' ,'WARNING', 'ERROR' ]) # Установка списка фильтров для логирования #logger_manager.set_filter('INFO') # Фильтрация сообщений только уровня INFO #logger_manager.clear_filter() # Очистка установленного фильтра #logger_manager.reset_level() # Сброс уровня логирования до уровня DEBUG for i in range(6): # Включение и отключение логирования в файл logger_manager.enable_file_logging(f"{datetime.datetime.now().strftime('%Y-%m-%d %H-%M'),i}.log") #logger_manager.disable_file_logging() # Логирование сообщений logger = logger_manager.logger logger.debug(f"debug message {i}") logger.info(f"info message {i}") logger.warning(f"warning message {i}") logger.error(f"error message {i}") logger.critical(f"critical message {i}") time.sleep(1)