"""日志工具""" """ utils/logger.py 统一日志模块,支持彩色终端输出与文件记录 """ import logging import sys from datetime import datetime from pathlib import Path # ── ANSI 颜色常量 ────────────────────────────────────────────── class Color: RESET = "\033[0m" BOLD = "\033[1m" CYAN = "\033[96m" GREEN = "\033[92m" YELLOW = "\033[93m" RED = "\033[91m" MAGENTA = "\033[95m" BLUE = "\033[94m" GREY = "\033[90m" # ── 自定义彩色 Formatter ─────────────────────────────────────── class ColorFormatter(logging.Formatter): LEVEL_COLORS = { logging.DEBUG: Color.GREY, logging.INFO: Color.CYAN, logging.WARNING: Color.YELLOW, logging.ERROR: Color.RED, logging.CRITICAL: Color.MAGENTA, } COMPONENT_COLORS = { "CLIENT": Color.BLUE, "LLM": Color.GREEN, "MCP": Color.YELLOW, "TOOL": Color.MAGENTA, "MEMORY": Color.CYAN, "SYSTEM": Color.GREY, } def format(self, record: logging.LogRecord) -> str: level_color = self.LEVEL_COLORS.get(record.levelno, Color.RESET) time_str = datetime.now().strftime("%H:%M:%S.%f")[:-3] # 从 logger 名称提取组件标签,例如 "agent.CLIENT" component = record.name.split(".")[-1].upper() comp_color = self.COMPONENT_COLORS.get(component, Color.RESET) prefix = ( f"{Color.GREY}[{time_str}]{Color.RESET} " f"{comp_color}{Color.BOLD}[{component:6s}]{Color.RESET} " f"{level_color}{record.getMessage()}{Color.RESET}" ) return prefix # ── Logger 工厂函数 ──────────────────────────────────────────── def get_logger(component: str, level: int = logging.DEBUG) -> logging.Logger: """ 获取指定组件的 Logger 实例。 Args: component: 组件名称,如 "CLIENT"、"LLM"、"MCP" level: 日志级别,默认 DEBUG Returns: 配置好的 Logger 实例 """ logger = logging.getLogger(f"agent.{component}") logger.setLevel(level) # 避免重复添加 Handler if logger.handlers: return logger # 终端 Handler(彩色) console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(ColorFormatter()) logger.addHandler(console_handler) # 文件 Handler(纯文本) log_dir = Path("logs") log_dir.mkdir(exist_ok=True) file_handler = logging.FileHandler(log_dir / "agent.log", encoding="utf-8") file_handler.setFormatter( logging.Formatter("[%(asctime)s] [%(name)s] %(levelname)s: %(message)s") ) logger.addHandler(file_handler) # 防止日志向上传播到 root logger logger.propagate = False return logger