"""Colour-coded logging configuration for LLM GGUF tools. Provides a consistent logging interface with colour-coded output for different log levels, making it easier to identify warnings, errors, and informational messages at a glance during tool execution and debugging sessions. """ from __future__ import annotations from logging import ( CRITICAL, DEBUG, ERROR, INFO, WARNING, Formatter as LoggingFormatter, Logger, LogRecord, StreamHandler as LoggingStreamHandler, getLogger, ) from os import getenv as os_getenv from sys import stdout as sys_stdout from typing import ClassVar DEBUG_MODE = os_getenv("DEBUG", "false").lower() == "true" class ColourFormatter(LoggingFormatter): """Custom formatter adding colours to log messages based on severity level. Uses ANSI escape codes to provide visual distinction between different log levels in terminal output. Supports standard logging levels with appropriate colour coding: DEBUG (cyan), INFO (green), WARNING (yellow), ERROR (red), and CRITICAL (bold red) for immediate visual feedback. """ # ANSI colour codes COLOURS: ClassVar[dict[int, str]] = { DEBUG: "\033[36m", # Cyan INFO: "\033[32m", # Green WARNING: "\033[33m", # Yellow ERROR: "\033[31m", # Red CRITICAL: "\033[1;31m", # Bold Red } RESET = "\033[0m" # Emoji prefixes for different levels EMOJIS: ClassVar[dict[int, str]] = { DEBUG: "", # No emoji for debug logs INFO: "", # No emoji for regular info logs WARNING: "⚠️ ", ERROR: "❌", CRITICAL: "🔥", } def format(self, record: LogRecord) -> str: """Format log record with colour and emoji based on severity level. Enhances standard log formatting by prepending ANSI colour codes and emoji indicators, then appending reset codes to prevent colour bleeding. Maintains standard log structure whilst adding visual enhancements for improved readability in terminal environments. Returns: str: Formatted log message with colour and emoji. """ # Get colour for this level colour = self.COLOURS.get(record.levelno, "") emoji = self.EMOJIS.get(record.levelno, "") # Format the message with emoji (add space only if emoji exists) if emoji: record.msg = f"{emoji} {record.msg}" formatted = super().format(record) # Add colour codes return f"{colour}{formatted}{self.RESET}" # Create and configure the logger logger: Logger = getLogger("llm-gguf-tools") logger.setLevel(DEBUG if DEBUG_MODE else INFO) # Create console handler with colour formatter handler = LoggingStreamHandler(sys_stdout) handler.setLevel(DEBUG if DEBUG_MODE else INFO) # Set formatter without timestamp for cleaner output formatter = ColourFormatter(fmt="%(message)s", datefmt="%H:%M:%S") handler.setFormatter(formatter) logger.addHandler(handler) # Prevent propagation to root logger logger.propagate = False