from enum import Enum import logging import sys import copy from ppp_utils import format_output class DEBUG_LEVEL(Enum): none = "none" minimal = "minimal" full = "full" class PromptPostProcessorLogFactory: # pylint: disable=too-few-public-methods """ Factory class for creating loggers for the PromptPostProcessor module. """ class ColoredFormatter(logging.Formatter): """ A custom logging formatter that adds color to log records based on their level. Attributes: COLORS (dict): A dictionary mapping log levels to ANSI escape codes for colors. Methods: format(record): Formats the log record with color based on its level. """ COLORS = { "DEBUG": "\033[0;36m", # CYAN "INFO": "\033[0;32m", # GREEN "WARNING": "\033[0;33m", # YELLOW "ERROR": "\033[0;31m", # RED "CRITICAL": "\033[0;37;41m", # WHITE ON RED "RESET": "\033[0m", # RESET COLOR } def format(self, record): """ Formats the log record with color based on the log level. Args: record (LogRecord): The log record to be formatted. Returns: str: The formatted log record. """ colored_record = copy.copy(record) levelname = colored_record.levelname seq = self.COLORS.get(levelname, self.COLORS["RESET"]) colored_record.levelname = f"{seq}{levelname:8s}{self.COLORS['RESET']}" return super().format(colored_record) def __init__(self, filename = None): """ Initializes the PromptPostProcessor class. This method sets up the logger for the PromptPostProcessor class and configures its log level and handlers. Args: filename (str, optional): The name of the file to log to. Defaults to None. app (SUPPORTED_APPS): The application for which the logger is being created. Returns: None """ ppplog = logging.getLogger("PromptPostProcessor") ppplog.propagate = False if not ppplog.handlers: handler = logging.StreamHandler(sys.stdout) handler.setFormatter(self.ColoredFormatter("%(asctime)s %(levelname)s %(message)s")) ppplog.addHandler(handler) if filename is not None: file_handler = logging.FileHandler(filename, encoding="utf-8") file_handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s")) ppplog.addHandler(file_handler) ppplog.setLevel(logging.DEBUG) self.log = PromptPostProcessorLogCustomAdapter(ppplog) class PromptPostProcessorLogCustomAdapter(logging.LoggerAdapter): """ Custom logger adapter for the PromptPostProcessor. This adapter adds a prefix to log messages to indicate that they are related to the PromptPostProcessor. """ def process(self, msg, kwargs): """ Process the log message and keyword arguments. Args: msg (str): The log message. kwargs (dict): The keyword arguments. Returns: tuple: A tuple containing the processed log message and keyword arguments. """ return f"[PPP] {msg}", kwargs def log(logger: logging.Logger, debug_level: DEBUG_LEVEL, kind: int, message: str, min_level: DEBUG_LEVEL | None = None, formatted: bool = True, exc_info: bool = False): if logger: if min_level is None: if kind == logging.DEBUG: min_level = DEBUG_LEVEL.full elif kind == logging.INFO: min_level = DEBUG_LEVEL.minimal else: min_level = DEBUG_LEVEL.none i_debug_level = list(DEBUG_LEVEL).index(debug_level) i_min_level = list(DEBUG_LEVEL).index(min_level) if i_debug_level >= i_min_level: logger.log(kind, format_output(message) if formatted else message, exc_info=exc_info)