""" 日志配置模块 """ import logging import sys from typing import Optional from logging.handlers import TimedRotatingFileHandler, RotatingFileHandler import os import platform from config import settings def setup_logger( name: str, level: Optional[str] = None, log_file: Optional[str] = None ) -> logging.Logger: """ 配置和获取logger(多进程安全版本) Args: name: logger名称 level: 日志级别 log_file: 日志文件路径 Returns: 配置好的logger实例 """ # 获取日志级别 if level is None: level = settings.LOG_LEVEL log_level = getattr(logging, level.upper(), logging.INFO) # 创建logger logger = logging.getLogger(name) logger.setLevel(log_level) # 避免重复添加handler if logger.handlers: return logger # 创建formatter formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 控制台handler console_handler = logging.StreamHandler(sys.stdout) console_handler.setLevel(log_level) console_handler.setFormatter(formatter) logger.addHandler(console_handler) # 文件handler(如果配置了日志文件) if log_file or settings.LOG_FILE: file_path = log_file or settings.LOG_FILE # 为每个进程生成唯一的日志文件名(避免文件锁定) process_id = os.getpid() process_hash = hash(f"{process_id}_{name}") % 10000 # 简单的hash # 生成唯一的日志文件名 base_name, ext = os.path.splitext(file_path) unique_file_path = f"{base_name}_{process_hash:04d}{ext}" try: # 使用进程安全的文件handler file_handler = TimedRotatingFileHandler( unique_file_path, when='midnight', # 每天午夜轮转 interval=1, # 间隔1天 backupCount=0, # 永久保留 encoding='utf-8' ) file_handler.setLevel(log_level) file_handler.setFormatter(formatter) logger.addHandler(file_handler) # 记录使用的日志文件路径 logger.info(f"Logger initialized with file: {unique_file_path}") except Exception as e: logger.warning(f"Failed to create log file handler: {e}") # 回退到控制台日志 logger.warning("Falling back to console logging only") return logger # 创建根logger root_logger = setup_logger("sur_face_feature") def get_logger(name: str) -> logging.Logger: """ 获取指定名称的logger Args: name: logger名称 Returns: logger实例 """ return setup_logger(name)