""" Structured logging setup with color support and multiple handlers. Provides a standardized logger configuration for the SQL Agent system with both console and file output capabilities. """ import logging import sys from typing import Optional from pathlib import Path class ColoredFormatter(logging.Formatter): """Custom formatter with color support for console output.""" COLORS = { "DEBUG": "\033[36m", # Cyan "INFO": "\033[32m", # Green "WARNING": "\033[33m", # Yellow "ERROR": "\033[31m", # Red "CRITICAL": "\033[35m", # Magenta } RESET = "\033[0m" def format(self, record: logging.LogRecord) -> str: """Format log record with color codes.""" color = self.COLORS.get(record.levelname, self.RESET) record.levelname = f"{color}{record.levelname}{self.RESET}" return super().format(record) def setup_logger( name: str, level: int = logging.INFO, log_file: Optional[Path] = None, use_color: bool = True, ) -> logging.Logger: """ Setup a structured logger with optional file output. Args: name: Logger name (typically __name__) level: Logging level (default: INFO) log_file: Optional path to write logs to use_color: Whether to use colored console output Returns: Configured logger instance """ logger = logging.getLogger(name) logger.setLevel(level) # Remove existing handlers for handler in logger.handlers[:]: logger.removeHandler(handler) # Console handler console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(level) if use_color: formatter = ColoredFormatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) else: formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) console_handler.setFormatter(formatter) logger.addHandler(console_handler) # File handler (optional) if log_file: log_file.parent.mkdir(parents=True, exist_ok=True) file_handler = logging.FileHandler(log_file) file_handler.setLevel(level) file_formatter = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S", ) file_handler.setFormatter(file_formatter) logger.addHandler(file_handler) return logger