Source code for utils.logger

import os
import logging
import sys
from typing import Optional
import time

[docs] class ColorizedFormatter(logging.Formatter): """ 为不同级别的日志提供不同颜色的格式化器 """ # 定义ANSI颜色代码 COLORS = { 'DEBUG': '\033[36m', # 青色 'INFO': '\033[32m', # 绿色 'WARNING': '\033[33m', # 黄色 'ERROR': '\033[31m', # 红色 'CRITICAL': '\033[35m', # 紫色 'RESET': '\033[0m', # 重置 } def __init__(self, fmt=None, datefmt=None, style='%', use_colors=True, is_debug_format=False): super().__init__(fmt, datefmt, style) self.use_colors = use_colors self.is_debug_format = is_debug_format def format(self, record): # 保存原始的levelname levelname = record.levelname # 添加颜色,如果使用颜色且不是文件处理器 if self.use_colors and hasattr(record, 'use_color') and record.use_color: color_start = self.COLORS.get(levelname, self.COLORS['RESET']) color_end = self.COLORS['RESET'] record.levelname = f"{color_start}{levelname}{color_end}" # 对调试日志增加更多上下文信息 if self.is_debug_format and record.levelno == logging.DEBUG: # 添加文件名、行号等详细信息 record.message = record.getMessage() record.pathname = record.pathname.replace('\\', '/') filename = record.pathname.split('/')[-1] record.location = f"{filename}:{record.lineno}" else: # 对于非调试级别或非调试格式的日志,添加一个空的location字段 if not hasattr(record, 'location'): record.location = "" result = super().format(record) # 恢复原始的levelname,避免影响其他处理器 record.levelname = levelname return result
[docs] def setup_logging( name: str, level: str = "INFO", log_file: Optional[str] = None, console_output: bool = True, format_style: str = "simple", enable_colors: bool = True ) -> logging.Logger: """ 设置日志记录器 Args: name: 记录器名称 level: 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL) log_file: 日志文件路径,如果为None则不写入文件 console_output: 是否输出到控制台 format_style: 格式样式 ("simple", "detailed", "debug") enable_colors: 是否启用颜色(仅影响控制台输出) Returns: 配置好的Logger对象 """ # 获取日志级别 numeric_level = getattr(logging, level.upper(), logging.INFO) # 创建logger logger = logging.getLogger(name) logger.setLevel(numeric_level) # 清除已有的处理器 for handler in logger.handlers[:]: logger.removeHandler(handler) # 定义格式 formats = { "simple": "%(asctime)s [%(levelname)s] %(message)s", "detailed": "%(asctime)s [%(levelname)s] %(name)s: %(message)s", "debug": "%(asctime)s [%(levelname)s] %(name)s (%(location)s): %(message)s" } log_format = formats.get(format_style, formats["simple"]) date_format = "%H:%M:%S" # 控制台处理器 if console_output: console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(numeric_level) # 为控制台处理器创建格式化器 console_formatter = ColorizedFormatter( log_format, date_format, use_colors=enable_colors, is_debug_format=(format_style == "debug") ) console_handler.setFormatter(console_formatter) # 添加一个过滤器来标记是否应该使用颜色 def add_color_flag(record): record.use_color = True return True console_handler.addFilter(add_color_flag) logger.addHandler(console_handler) # 文件处理器 if log_file: # 确保日志目录存在 os.makedirs(os.path.dirname(log_file), exist_ok=True) file_handler = logging.FileHandler(log_file, encoding='utf-8') file_handler.setLevel(numeric_level) # 文件处理器不使用颜色 file_formatter = ColorizedFormatter( log_format, date_format, use_colors=False, is_debug_format=(format_style == "debug") ) file_handler.setFormatter(file_formatter) logger.addHandler(file_handler) return logger
[docs] def get_logger(name: str) -> logging.Logger: """ Get a logger with the specified name. Args: name: Name of the logger Returns: Logger instance """ return logging.getLogger(name)
# 创建默认logger default_logger = setup_logging("default")