|
import logging |
|
|
|
|
|
|
|
def hex_to_ansi(hex_color, is_background=False): |
|
"""Convert a hex color code to an ANSI escape sequence.""" |
|
hex_color = hex_color.lstrip("#") |
|
if len(hex_color) != 6: |
|
raise ValueError("Invalid hex color format. Use #RRGGBB.") |
|
|
|
r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) |
|
return f"\033[{48 if is_background else 38};2;{r};{g};{b}m" |
|
|
|
|
|
class ColoredFormatter(logging.Formatter): |
|
|
|
COLORS = { |
|
"DEBUG": {"HEADER": "#1E3A8A", "TIMESTAMP": "#2563EB"}, |
|
"INFO": {"HEADER": "#166534", "TIMESTAMP": "#22C55E"}, |
|
"WARNING": {"HEADER": "#92400E", "TIMESTAMP": "#FACC15"}, |
|
"ERROR": {"HEADER": "#7F1D1D", "TIMESTAMP": "#EF4444"}, |
|
"CRITICAL": {"HEADER": "#581C87", "TIMESTAMP": "#C084FC"}, |
|
} |
|
|
|
def format(self, record): |
|
|
|
filename = record.pathname.split("/")[-1] |
|
line_no = record.lineno |
|
level_name = record.levelname |
|
|
|
|
|
level_colors = self.COLORS.get(level_name, self.COLORS["INFO"]) |
|
header_color = hex_to_ansi(level_colors["HEADER"]) |
|
timestamp_color = hex_to_ansi(level_colors["TIMESTAMP"]) |
|
reset_color = "\033[0m" |
|
|
|
|
|
header = f"{header_color}[{level_name}|{filename}:{line_no}]{reset_color}" |
|
|
|
|
|
timestamp = f"{timestamp_color}{self.formatTime(record, self.datefmt)}{reset_color}" |
|
|
|
|
|
message = f"\033[37m{record.getMessage()}{reset_color}" |
|
|
|
return f"{header} {timestamp} >> {message}" |
|
|
|
|
|
|
|
logger = logging.getLogger(__name__) |
|
logger.setLevel(logging.INFO) |
|
console_handler = logging.StreamHandler() |
|
formatter = ColoredFormatter(datefmt="%Y-%m-%d %H:%M:%S") |
|
console_handler.setFormatter(formatter) |
|
logger.addHandler(console_handler) |