# utils/logger.py import logging import os import traceback from logging.handlers import RotatingFileHandler from config.settings import LogConfig def setup_logger(): """设置日志""" # 获取日志配置 LOG_CONFIG = LogConfig.as_dict() # 创建日志目录 log_dir = os.path.dirname(LOG_CONFIG["file"]) if not os.path.exists(log_dir): os.makedirs(log_dir) # 设置日志级别 log_level = getattr(logging, LOG_CONFIG["level"].upper(), logging.INFO) # 设置日志格式 - 增加行号、函数名等信息 log_format = logging.Formatter(LOG_CONFIG.get("format", "%(asctime)s - %(name)s - %(levelname)s - %(message)s")) # 为警告和错误级别创建特殊格式 detailed_format = logging.Formatter( "%(asctime)s - %(name)s - %(levelname)s - [%(filename)s:%(lineno)d] - %(funcName)s() - %(message)s" ) # 创建根日志记录器 root_logger = logging.getLogger() root_logger.setLevel(log_level) # 清除现有处理器 for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) # 添加控制台处理器 console_handler = logging.StreamHandler() console_handler.setFormatter(log_format) # 为警告及以上级别设置详细格式 console_handler.setLevel(logging.INFO) root_logger.addHandler(console_handler) # 添加专门的错误控制台处理器,显示更多详细信息 error_console_handler = logging.StreamHandler() error_console_handler.setFormatter(detailed_format) error_console_handler.setLevel(logging.WARNING) # 只处理警告及以上级别 root_logger.addHandler(error_console_handler) # 添加文件处理器 file_handler = RotatingFileHandler( LOG_CONFIG["file"], maxBytes=10 * 1024 * 1024, # 10MB backupCount=5 ) file_handler.setFormatter(log_format) root_logger.addHandler(file_handler) # 添加专门的错误文件处理器,显示更多详细信息 error_file_handler = RotatingFileHandler( LOG_CONFIG.get("error_file", os.path.join(log_dir, "error.log")), maxBytes=10 * 1024 * 1024, # 10MB backupCount=5 ) error_file_handler.setFormatter(detailed_format) error_file_handler.setLevel(logging.WARNING) # 只处理警告及以上级别 root_logger.addHandler(error_file_handler) # 设置第三方库的日志级别 logging.getLogger("werkzeug").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) return root_logger class Logger: """ 日志记录器类 封装不同级别的日志记录功能 """ def __init__(self, name): """ 初始化日志记录器 Args: name (str): 日志记录器名称,通常为模块名称 """ # 获取指定名称的日志记录器 self.logger = logging.getLogger(name) self.name = name def debug(self, message, *args, **kwargs): """ 记录调试日志 Args: message: 日志消息 *args: 位置参数 **kwargs: 关键字参数 """ self.logger.debug(message, *args, **kwargs) def info(self, message, *args, **kwargs): """ 记录一般信息日志 Args: message: 日志消息 *args: 位置参数 **kwargs: 关键字参数 """ self.logger.info(message, *args, **kwargs) def warning(self, message, *args, exc_info=False, stack_info=False, **kwargs): """ 记录警告日志 Args: message: 日志消息 *args: 位置参数 exc_info: 是否包含异常信息,默认False stack_info: 是否包含堆栈信息,默认False **kwargs: 关键字参数 """ # 默认启用堆栈信息以便显示行号 # 如果不想显示整个堆栈跟踪,可以保持stack_info为False,系统会自动记录行号 self.logger.warning(message, *args, exc_info=exc_info, stack_info=stack_info, **kwargs) def error(self, message, *args, exc_info=True, stack_info=True, **kwargs): """ 记录错误日志 Args: message: 日志消息 *args: 位置参数 exc_info: 是否包含异常信息,默认True stack_info: 是否包含堆栈信息,默认True **kwargs: 关键字参数 """ # 由于我们已经在日志格式中添加了行号和文件名,这里不需要特殊处理 self.logger.error(message, *args, exc_info=exc_info, stack_info=stack_info, **kwargs) def critical(self, message, *args, exc_info=True, stack_info=True, **kwargs): """ 记录严重错误日志 Args: message: 日志消息 *args: 位置参数 exc_info: 是否包含异常信息,默认True stack_info: 是否包含堆栈信息,默认True **kwargs: 关键字参数 """ self.logger.critical(message, *args, exc_info=exc_info, stack_info=stack_info, **kwargs) def exception(self, message, *args, **kwargs): """ 记录异常日志,自动包含异常堆栈信息 Args: message: 日志消息 *args: 位置参数 **kwargs: 关键字参数 """ self.logger.exception(message, *args, **kwargs) def log_error_with_trace(self, message, e=None): """ 记录带有详细追踪信息的错误日志 Args: message: 日志消息 e: 异常对象,可选 """ error_msg = f"{message}" if e: error_msg += f": {str(e)}" # 使用traceback模块获取完整的堆栈跟踪 trace = traceback.format_exc() self.logger.error(f"{error_msg}\n{trace}") def log_startup(self, module_name, version=None): """ 记录模块启动日志 Args: module_name: 模块名称 version: 版本号,可选 """ version_str = f" v{version}" if version else "" self.logger.info(f"=== {module_name}{version_str} 启动完成 ===") def log_shutdown(self, module_name): """ 记录模块关闭日志 Args: module_name: 模块名称 """ self.logger.info(f"=== {module_name} 已关闭 ===") def get_logger(name): """ 获取指定名称的日志记录器 Args: name (str): 日志记录器名称,通常为模块名称 Returns: Logger: 日志记录器实例 """ # 确保全局日志配置已初始化 setup_logger() # 创建并返回Logger实例 return Logger(name)