Coqui-Xtts-Demo / utils /logger.py
Jimmy Vu
Add files
2e99c77
import logging
import sys
from pathlib import Path
from datetime import datetime
import colorama
from colorama import Fore, Back, Style
from typing import Optional, Union
import re
import traceback
import copy
import os
# Initialize colorama
colorama.init()
class ColoredFormatter(logging.Formatter):
"""Colored formatter for structured log output.
This formatter adds color-coding, icons, timestamps, and file location
information to log messages. It supports different color schemes for
different log levels and includes special formatting for exceptions.
Attributes:
COLORS (dict): Color schemes for different log levels, including:
- color: Foreground color
- style: Text style (dim, normal, bright)
- icon: Emoji icon for the log level
- bg: Background color (for critical logs)
"""
COLORS = {
'DEBUG': {
'color': Fore.CYAN,
'style': Style.DIM,
'icon': '🔍'
},
'INFO': {
'color': Fore.GREEN,
'style': Style.NORMAL,
'icon': 'ℹ️'
},
'WARNING': {
'color': Fore.YELLOW,
'style': Style.BRIGHT,
'icon': '⚠️'
},
'ERROR': {
'color': Fore.RED,
'style': Style.BRIGHT,
'icon': '❌'
},
'CRITICAL': {
'color': Fore.WHITE,
'style': Style.BRIGHT,
'bg': Back.RED,
'icon': '💀'
}
}
def format(self, record: logging.LogRecord) -> str:
"""Format a log record with color and structure.
This method formats log records with:
- Timestamp in HH:MM:SS.mmm format
- File location (filename:line)
- Color-coded level name with icon
- Color-coded message
- Formatted exception traceback if present
Args:
record (logging.LogRecord): Log record to format.
Returns:
str: Formatted log message with color and structure.
"""
colored_record = copy.copy(record)
# Get color scheme
scheme = self.COLORS.get(record.levelname, {
'color': Fore.WHITE,
'style': Style.NORMAL,
'icon': '•'
})
# Format timestamp
timestamp = datetime.fromtimestamp(record.created).strftime('%H:%M:%S.%f')[:-3]
# Get file location
file_location = f"{os.path.basename(record.pathname)}:{record.lineno}"
# Build components
components = []
# log formatting
components.extend([
f"{Fore.BLUE}{timestamp}{Style.RESET_ALL}",
f"{Fore.WHITE}{Style.DIM}{file_location}{Style.RESET_ALL}",
f"{scheme['color']}{scheme['style']}{scheme['icon']} {record.levelname:8}{Style.RESET_ALL}",
f"{scheme['color']}{record.msg}{Style.RESET_ALL}"
])
# Add exception info
if record.exc_info:
components.append(
f"\n{Fore.RED}{Style.BRIGHT}"
f"{''.join(traceback.format_exception(*record.exc_info))}"
f"{Style.RESET_ALL}"
)
return " | ".join(components)
def setup_logger(
name: Optional[Union[str, Path]] = None,
level: int = logging.INFO
) -> logging.Logger:
"""Set up a colored logger
This function creates or retrieves a logger with colored output and
automatic log interception. If a file path is provided as the name,
it will use the filename (without extension) as the logger name.
Args:
name (Optional[Union[str, Path]], optional): Logger name or __file__ for
module name. Defaults to None.
level (int, optional): Logging level. Defaults to logging.INFO.
Returns:
logging.Logger: Configured logger instance.
"""
# Get logger name from file path
if isinstance(name, (str, Path)) and Path(name).suffix == '.py':
name = Path(name).stem
# Get or create logger
logger = logging.getLogger(name)
logger.setLevel(level)
# Only add handler if none exists
if not logger.handlers:
# Create console handler
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(ColoredFormatter())
logger.addHandler(console_handler)
return logger