Files
Mofox-Core/ui_log_adapter.py
雅诺狐 3edcc9d169 ruff
2025-12-08 15:48:40 +08:00

161 lines
4.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Bot服务UI日志适配器
在最小侵入的情况下捕获Bot的日志并发送到UI
"""
import logging
import os
import sys
import threading
import time
# 添加MoFox-UI路径以导入ui_logger
ui_path = os.path.join(os.path.dirname(__file__), "..", "MoFox-UI")
if os.path.exists(ui_path):
sys.path.insert(0, ui_path)
try:
from ui_logger import get_ui_logger
ui_logger = get_ui_logger("Bot")
UI_LOGGER_AVAILABLE = True
except ImportError:
UI_LOGGER_AVAILABLE = False
else:
UI_LOGGER_AVAILABLE = False
class UILogHandler(logging.Handler):
"""自定义日志处理器将日志发送到UI"""
def __init__(self, max_retries=3):
"""
初始化UI日志处理器
Args:
max_retries: 最大重试次数默认3次
"""
super().__init__()
self.ui_logger = ui_logger if UI_LOGGER_AVAILABLE else None
self.max_retries = max_retries
self.retry_delay = 0.1 # 重试延迟时间(秒)
def _send_log_with_retry(self, msg, level):
"""
带重试机制的日志发送方法
Args:
msg: 日志消息
level: 日志级别('info', 'warning', 'error', 'debug'
Returns:
bool: 发送是否成功
"""
if not self.ui_logger:
return False
for attempt in range(self.max_retries):
try:
if level == "info":
self.ui_logger.info(msg)
elif level == "warning":
self.ui_logger.warning(msg)
elif level == "error":
self.ui_logger.error(msg)
elif level == "debug":
self.ui_logger.debug(msg)
else:
self.ui_logger.info(msg)
return True
except Exception as e:
if attempt == self.max_retries - 1:
print(f"[UI日志适配器] 发送日志失败,已达最大重试次数 {self.max_retries}: {e}")
return False
time.sleep(self.retry_delay)
return False
def emit(self, record):
"""
处理日志记录(重写父类方法)
Args:
record: 日志记录对象
"""
if not self.ui_logger:
return
try:
msg = self.format(record)
level_mapping = {
"DEBUG": "debug",
"INFO": "info",
"WARNING": "warning",
"ERROR": "error",
"CRITICAL": "error",
}
ui_level = level_mapping.get(record.levelname, "info")
# 过滤掉DEBUG日志
if record.levelname == "DEBUG":
return
formatted_msg = msg
self._send_log_with_retry(formatted_msg, ui_level)
# 可选:记录发送状态
# if not success:
# print(f"[UI日志适配器] 日志发送失败: {ui_level} - {formatted_msg[:50]}...")
except Exception:
# 静默失败,不影响主程序
pass
def setup_ui_logging():
"""设置UI日志处理器"""
if not UI_LOGGER_AVAILABLE:
print("[UI日志适配器] UI Logger不可用跳过设置")
return
try:
print("[UI日志适配器] 开始设置UI日志处理器...")
root_logger = logging.getLogger()
for handler in root_logger.handlers:
if isinstance(handler, UILogHandler):
print("[UI日志适配器] UI日志处理器已存在跳过重复添加")
return
ui_handler = UILogHandler(max_retries=3)
ui_handler.setLevel(logging.INFO)
root_logger.addHandler(ui_handler)
print(f"[UI日志适配器] UI日志处理器已添加到根日志器当前处理器数量: {len(root_logger.handlers)}")
print(f"[UI日志适配器] 最大重试次数: {ui_handler.max_retries}")
# 发送启动信息
if UI_LOGGER_AVAILABLE:
success = ui_handler._send_log_with_retry("📝 Bot服务日志适配器已启动", "info")
print("[UI日志适配器] 启动信息已发送到UI" if success else "[UI日志适配器] 启动信息发送失败")
except Exception as e:
print(f"[UI日志适配器] 设置失败: {e}")
# 自动设置:模块被导入时执行
if __name__ != "__main__":
print("[UI日志适配器] 模块被导入准备设置UI日志...")
try:
setup_ui_logging()
except Exception as e:
print(f"[UI日志适配器] 立即设置失败,将延迟执行: {e}")
def delayed_setup():
"""延迟设置函数,在独立线程中执行"""
time.sleep(0.5) # 等待日志系统初始化
print("[UI日志适配器] 执行延迟设置...")
setup_ui_logging()
threading.Thread(target=delayed_setup, daemon=True).start()