From f91f99de52aad038dfdf9a3030c559541b726009 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Mon, 6 Jan 2025 01:53:47 +0800 Subject: [PATCH 1/2] fix(log): update logger handlers without reset --- app/log.py | 58 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/app/log.py b/app/log.py index c25cbbca..7e3c93a5 100644 --- a/app/log.py +++ b/app/log.py @@ -1,5 +1,6 @@ import inspect import logging +import threading from logging.handlers import RotatingFileHandler from pathlib import Path from typing import Dict, Any, Optional @@ -95,6 +96,8 @@ class LoggerManager: _loggers: Dict[str, Any] = {} # 默认日志文件名称 _default_log_file = "moviepilot.log" + # 线程锁 + _lock = threading.Lock() @staticmethod def __get_caller(): @@ -133,7 +136,7 @@ class LoggerManager: @staticmethod def __setup_logger(log_file: str): """ - 设置日志 + 初始化日志实例 :param log_file:日志文件相对路径 """ @@ -143,13 +146,8 @@ class LoggerManager: # 创建新实例 _logger = logging.getLogger(log_file_path.stem) - if log_settings.DEBUG: - _logger.setLevel(logging.DEBUG) - - # 全局日志等级 - else: - loglevel = getattr(logging, log_settings.LOG_LEVEL.upper(), logging.INFO) - _logger.setLevel(loglevel) + # 设置日志级别 + _logger.setLevel(LoggerManager.__get_log_level()) # 移除已有的 handler,避免重复添加 for handler in _logger.handlers: @@ -179,16 +177,42 @@ class LoggerManager: """ 更新日志实例 """ - _new_loggers: Dict[str, Any] = {} - for log_file, _logger in self._loggers.items(): - # 移除已有的 handler,避免重复添加 - for handler in _logger.handlers: - _logger.removeHandler(handler) - # 重新设置日志实例 - _new_logger = self.__setup_logger(log_file=log_file) - _new_loggers[log_file] = _new_logger + with LoggerManager._lock: + for _logger in self._loggers.values(): + self.__update_logger_handlers(_logger) - self._loggers = _new_loggers + @staticmethod + def __update_logger_handlers(_logger: logging.Logger): + """ + 更新 Logger 的 handler 配置 + + :param _logger: 需要更新的 Logger 实例 + """ + # 更新现有 handler + for handler in _logger.handlers: + try: + if isinstance(handler, RotatingFileHandler): + # 更新最大文件大小和备份数量 + handler.maxBytes = log_settings.LOG_MAX_FILE_SIZE_BYTES + handler.backupCount = log_settings.LOG_BACKUP_COUNT + # 更新日志文件输出格式 + file_formatter = CustomFormatter(log_settings.LOG_FILE_FORMAT) + handler.setFormatter(file_formatter) + elif isinstance(handler, logging.StreamHandler): + # 更新控制台输出格式 + console_formatter = CustomFormatter(log_settings.LOG_CONSOLE_FORMAT) + handler.setFormatter(console_formatter) + except Exception as e: + logger.error(f"Failed to update handler: {handler}. Error: {e}") + # 更新日志级别 + _logger.setLevel(LoggerManager.__get_log_level()) + + @staticmethod + def __get_log_level(): + """ + 获取当前日志级别 + """ + return logging.DEBUG if log_settings.DEBUG else getattr(logging, log_settings.LOG_LEVEL.upper(), logging.INFO) def logger(self, method: str, msg: str, *args, **kwargs): """ From af2b4aa8679939b749835634dd6227e049379344 Mon Sep 17 00:00:00 2001 From: InfinityPacer <160988576+InfinityPacer@users.noreply.github.com> Date: Mon, 6 Jan 2025 17:46:35 +0800 Subject: [PATCH 2/2] perf(log): optimize get_caller for improved performance --- app/log.py | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/app/log.py b/app/log.py index 7e3c93a5..3cf3b9fc 100644 --- a/app/log.py +++ b/app/log.py @@ -1,5 +1,5 @@ -import inspect import logging +import sys import threading from logging.handlers import RotatingFileHandler from pathlib import Path @@ -109,27 +109,46 @@ class LoggerManager: caller_name = None # 调用者插件名称 plugin_name = None - for i in inspect.stack()[3:]: - filepath = Path(i.filename) + + try: + frame = sys._getframe(3) + except (AttributeError, ValueError): + # 如果无法获取帧,返回默认值 + return "log.py", None + + while frame: + filepath = Path(frame.f_code.co_filename) parts = filepath.parts + # 设定调用者文件名称 if not caller_name: - # 设定调用者文件名称 - if parts[-1] == "__init__.py": + if parts[-1] == "__init__.py" and len(parts) >= 2: caller_name = parts[-2] else: caller_name = parts[-1] + # 设定调用者插件名称 if "app" in parts: if not plugin_name and "plugins" in parts: - # 设定调用者插件名称 - plugin_name = parts[parts.index("plugins") + 1] - if plugin_name == "__init__.py": - plugin_name = "plugin" - break + try: + plugins_index = parts.index("plugins") + if plugins_index + 1 < len(parts): + plugin_candidate = parts[plugins_index + 1] + if plugin_candidate == "__init__.py": + plugin_name = "plugin" + else: + plugin_name = plugin_candidate + break + except ValueError: + pass if "main.py" in parts: - # 已经到达程序的入口 + # 已经到达程序的入口,停止遍历 break elif len(parts) != 1: - # 已经超出程序范围 + # 已经超出程序范围,停止遍历 + break + # 获取上一个帧 + try: + frame = frame.f_back + except AttributeError: break return caller_name or "log.py", plugin_name @@ -137,7 +156,6 @@ class LoggerManager: def __setup_logger(log_file: str): """ 初始化日志实例 - :param log_file:日志文件相对路径 """ log_file_path = log_settings.LOG_PATH / log_file @@ -185,7 +203,6 @@ class LoggerManager: def __update_logger_handlers(_logger: logging.Logger): """ 更新 Logger 的 handler 配置 - :param _logger: 需要更新的 Logger 实例 """ # 更新现有 handler