| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | import loggingimport osimport sysfrom datetime import datetimefrom typing import Optionaldef setup_logging(verbose: bool = False, log_file: Optional[str] = None, log_dir: Optional[str] = None):    """    设置日志系统        Args:        verbose: 是否启用详细日志        log_file: 日志文件名        log_dir: 日志目录    """    # 确定日志级别    log_level = logging.DEBUG if verbose else logging.INFO        # 创建根logger    root_logger = logging.getLogger()    root_logger.setLevel(log_level)        # 清除已有的处理器    root_logger.handlers.clear()        # 设置日志格式    console_format = "%(asctime)s [%(levelname)s] %(message)s"    file_format = "%(asctime)s [%(levelname)s] [%(name)s] %(message)s"    date_format = "%Y-%m-%d %H:%M:%S"        # 控制台处理器    console_handler = logging.StreamHandler(sys.stdout)    console_handler.setLevel(log_level)    console_formatter = logging.Formatter(console_format, datefmt=date_format)    console_handler.setFormatter(console_formatter)    root_logger.addHandler(console_handler)        # 文件处理器(如果指定)    if log_file:        # 确定日志文件路径        if log_dir:            os.makedirs(log_dir, exist_ok=True)            log_path = os.path.join(log_dir, log_file)        else:            log_path = log_file                # 添加时间戳到日志文件名        base_name, ext = os.path.splitext(log_path)        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")        log_path = f"{base_name}_{timestamp}{ext}"                file_handler = logging.FileHandler(log_path, encoding='utf-8')        file_handler.setLevel(log_level)        file_formatter = logging.Formatter(file_format, datefmt=date_format)        file_handler.setFormatter(file_formatter)        root_logger.addHandler(file_handler)                # 记录日志文件位置        root_logger.info(f"日志文件: {os.path.abspath(log_path)}")        # 设置schema_tools模块的日志级别    schema_tools_logger = logging.getLogger("schema_tools")    schema_tools_logger.setLevel(log_level)        # 设置第三方库的日志级别(避免过多输出)    logging.getLogger("asyncio").setLevel(logging.WARNING)    logging.getLogger("asyncpg").setLevel(logging.WARNING)    logging.getLogger("openai").setLevel(logging.WARNING)    logging.getLogger("httpx").setLevel(logging.WARNING)    logging.getLogger("urllib3").setLevel(logging.WARNING)        # 返回schema_tools的logger    return schema_tools_loggerclass ColoredFormatter(logging.Formatter):    """带颜色的日志格式化器(用于控制台)"""        # ANSI颜色代码    COLORS = {        'DEBUG': '\033[36m',     # 青色        'INFO': '\033[32m',      # 绿色        'WARNING': '\033[33m',   # 黄色        'ERROR': '\033[31m',     # 红色        'CRITICAL': '\033[35m',  # 紫色    }    RESET = '\033[0m'        def format(self, record):        # 保存原始级别名        levelname = record.levelname                # 添加颜色        if levelname in self.COLORS:            record.levelname = f"{self.COLORS[levelname]}{levelname}{self.RESET}"                # 格式化消息        formatted = super().format(record)                # 恢复原始级别名        record.levelname = levelname                return formatteddef get_colored_console_handler(level=logging.INFO):    """获取带颜色的控制台处理器"""    handler = logging.StreamHandler(sys.stdout)    handler.setLevel(level)        # 检查是否支持颜色(Windows需要特殊处理)    if sys.platform == "win32":        try:            import colorama            colorama.init()            use_color = True        except ImportError:            use_color = False    else:        # Unix/Linux/Mac通常支持ANSI颜色        use_color = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()        if use_color:        formatter = ColoredFormatter(            "%(asctime)s [%(levelname)s] %(message)s",            datefmt="%Y-%m-%d %H:%M:%S"        )    else:        formatter = logging.Formatter(            "%(asctime)s [%(levelname)s] %(message)s",            datefmt="%Y-%m-%d %H:%M:%S"        )        handler.setFormatter(formatter)    return handlerclass TableProcessingLogger:    """表处理专用日志器"""        def __init__(self, logger_name: str = "schema_tools.TableProcessor"):        self.logger = logging.getLogger(logger_name)        self.current_table = None        self.start_time = None        def start_table(self, table_name: str):        """开始处理表"""        self.current_table = table_name        self.start_time = datetime.now()        self.logger.info(f"{'='*60}")        self.logger.info(f"开始处理表: {table_name}")        self.logger.info(f"开始时间: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")        def end_table(self, success: bool = True):        """结束处理表"""        if self.start_time:            duration = (datetime.now() - self.start_time).total_seconds()            status = "成功" if success else "失败"            self.logger.info(f"处理{status},耗时: {duration:.2f}秒")        self.logger.info(f"{'='*60}\n")        self.current_table = None        self.start_time = None        def log_step(self, step_name: str, message: str = None):        """记录处理步骤"""        if message:            self.logger.info(f"  [{step_name}] {message}")        else:            self.logger.info(f"  [{step_name}]")        def log_warning(self, message: str):        """记录警告"""        self.logger.warning(f"  ⚠ {message}")        def log_error(self, message: str):        """记录错误"""        self.logger.error(f"  ✗ {message}")
 |