为MaiBot适配器增加插件级DEBUG日志开关
变更项:\n1. 新增 MaiBotAdapter.log_level 配置项,支持 INFO/DEBUG,默认非法值自动回落 INFO。\n2. 在插件内新增 _log_runtime 方法,根据 log_level 动态输出运行日志级别,便于在不改全局日志配置的情况下单独拉高该插件观测粒度。\n3. 将适配器关键运行日志(初始化、连接、收发包、ACK、路由判定、入队、回复决策)统一接入 _log_runtime。\n4. 在插件配置中增加详细中文注释,并按你的要求将 log_level 设为 DEBUG。
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
[MaiBotAdapter]
|
||||
enable = false
|
||||
enable = true
|
||||
|
||||
# 插件日志级别:
|
||||
# 1. INFO:输出关键生命周期与异常信息,日志量更小;
|
||||
# 2. DEBUG:输出完整运行细节(入队、路由判定、收发包、ACK 等);
|
||||
# 3. 你当前要求查看更细日志,默认改为 DEBUG。
|
||||
log_level = "DEBUG"
|
||||
|
||||
# 是否默认采集群消息到 MaiBot:
|
||||
# 1. 这是“把消息送给 MaiBot 做上下文与记忆”的总开关;
|
||||
|
||||
@@ -80,6 +80,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
self._reconnect_delay = 5
|
||||
self._queue_maxsize = 500
|
||||
self._max_send_retries = 3
|
||||
self._log_level = "INFO"
|
||||
|
||||
# 运行时状态。
|
||||
self._config_ready = False
|
||||
@@ -117,6 +118,9 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
self._reconnect_delay = max(1, int(plugin_config.get("reconnect_delay", 5) or 5))
|
||||
self._queue_maxsize = max(50, int(plugin_config.get("queue_maxsize", 500) or 500))
|
||||
self._max_send_retries = max(1, int(plugin_config.get("max_send_retries", 3) or 3))
|
||||
self._log_level = str(plugin_config.get("log_level", "INFO") or "INFO").strip().upper()
|
||||
if self._log_level not in {"DEBUG", "INFO"}:
|
||||
self._log_level = "INFO"
|
||||
|
||||
# 官方 API Server 至少需要 ws 地址与 api_key:
|
||||
# 1. 地址用于建立长期 WebSocket;
|
||||
@@ -126,7 +130,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
if not self._config_ready:
|
||||
self.LOG.warning(f"[{self.name}] api_server_ws_url/api_key 未配置完整,插件会加载成功但不会转发消息")
|
||||
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 初始化完成: enabled={self._enabled}, "
|
||||
f"collect_group_messages={self._collect_group_messages}, collect_private_messages={self._collect_private_messages}, "
|
||||
f"enable_reply_output={self._enable_reply_output}, reply_group_messages={self._reply_group_messages}, "
|
||||
@@ -137,7 +141,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
|
||||
def start(self) -> bool:
|
||||
self.status = PluginStatus.RUNNING
|
||||
self.LOG.info(f"[{self.name}] 插件已启动,等待首条消息后再懒启动长连接")
|
||||
self._log_runtime(f"[{self.name}] 插件已启动,等待首条消息后再懒启动长连接")
|
||||
return True
|
||||
|
||||
def stop(self) -> bool:
|
||||
@@ -192,7 +196,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
payload = self._build_outbound_payload(message=message, normalized_content=normalized_content)
|
||||
try:
|
||||
outbound_queue.put_nowait(payload)
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 消息已入队: route_type={payload['route_type']}, roomid={payload['roomid']}, "
|
||||
f"route_source={payload['route_source']}, sender={payload['sender']}, "
|
||||
f"msg_type={payload['message_type']}, queue_size={outbound_queue.qsize()}, "
|
||||
@@ -231,7 +235,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
asyncio.create_task(self._sender_loop(), name="maibot_adapter_sender_loop"),
|
||||
]
|
||||
self._runtime_started = True
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 后台运行时已启动: connection_uuid={self._connection_uuid}, "
|
||||
f"queue_maxsize={self._queue_maxsize}, heartbeat_interval={self._heartbeat_interval}"
|
||||
)
|
||||
@@ -270,7 +274,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
}
|
||||
ssl_option = None if self._verify_ssl else False
|
||||
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 正在连接 MaiBot API Server: url={self._api_server_ws_url}, "
|
||||
f"platform={self._platform_name}, connection_uuid={headers['x-uuid']}"
|
||||
)
|
||||
@@ -287,7 +291,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
if self._connected_event is not None:
|
||||
self._connected_event.set()
|
||||
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] MaiBot API Server 连接成功: url={self._api_server_ws_url}, "
|
||||
f"connection_uuid={headers['x-uuid']}"
|
||||
)
|
||||
@@ -303,7 +307,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
|
||||
if message.type == aiohttp.WSMsgType.TEXT:
|
||||
raw_text = str(message.data or "")
|
||||
self.LOG.info(f"[{self.name}] 收到 MaiBot 原始消息: {raw_text[:500]}")
|
||||
self._log_runtime(f"[{self.name}] 收到 MaiBot 原始消息: {raw_text[:500]}")
|
||||
payload = self._parse_json_message(raw_text)
|
||||
if payload is None:
|
||||
continue
|
||||
@@ -358,7 +362,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
}
|
||||
|
||||
await websocket.send_json(package)
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 已发送到 MaiBot: roomid={payload['roomid']}, sender={payload['sender']}, "
|
||||
f"msg_type={payload['message_type']}, package_id={package['msg_id']}, "
|
||||
f"content_preview={payload['normalized_content'][:120]}"
|
||||
@@ -395,11 +399,11 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
|
||||
if package_type == "sys_ack":
|
||||
acked_msg_id = str(((package.get("meta") or {}).get("acked_msg_id")) or "")
|
||||
self.LOG.info(f"[{self.name}] 收到 MaiBot ACK: package_id={package_id}, acked_msg_id={acked_msg_id}")
|
||||
self._log_runtime(f"[{self.name}] 收到 MaiBot ACK: package_id={package_id}, acked_msg_id={acked_msg_id}")
|
||||
return
|
||||
|
||||
if package_type != "sys_std":
|
||||
self.LOG.info(f"[{self.name}] 忽略非 sys_std 消息: package_type={package_type}, package_id={package_id}")
|
||||
self._log_runtime(f"[{self.name}] 忽略非 sys_std 消息: package_type={package_type}, package_id={package_id}")
|
||||
return
|
||||
|
||||
api_message = package.get("payload") or {}
|
||||
@@ -409,7 +413,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
|
||||
reply_text = self._extract_segment_text(message_segment).strip()
|
||||
if not reply_text:
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] MaiBot 返回了空文本或非文本片段,忽略发送: package_id={package_id}, "
|
||||
f"segment_type={message_segment.get('type')}"
|
||||
)
|
||||
@@ -423,7 +427,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
)
|
||||
return
|
||||
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 收到 MaiBot 回复: package_id={package_id}, route_type={route['route_type']}, "
|
||||
f"target={route['target']}, at_target={route.get('at_target', '')}, "
|
||||
f"platform={message_dim.get('platform')}, reply_preview={reply_text[:120]}"
|
||||
@@ -434,7 +438,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
async def _emit_reply(self, route: Dict[str, str], reply_text: str, api_message: Dict[str, Any]) -> None:
|
||||
"""按配置决定是否把 MaiBot 回复真正发回微信。"""
|
||||
if not self._enable_reply_output:
|
||||
self.LOG.info(f"[{self.name}] enable_reply_output=false,仅采集不发回微信")
|
||||
self._log_runtime(f"[{self.name}] enable_reply_output=false,仅采集不发回微信")
|
||||
return
|
||||
|
||||
bot = self._last_bot or getattr(self, "bot", None)
|
||||
@@ -448,16 +452,16 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
|
||||
if route_type == "group":
|
||||
if not self._reply_group_messages:
|
||||
self.LOG.info(f"[{self.name}] reply_group_messages=false,群回复已跳过: target={target}")
|
||||
self._log_runtime(f"[{self.name}] reply_group_messages=false,群回复已跳过: target={target}")
|
||||
return
|
||||
if self._respect_group_feature_switch and not self._group_reply_allowed(target):
|
||||
self.LOG.info(f"[{self.name}] 群功能开关未启用,仅采集不回群: target={target}")
|
||||
self._log_runtime(f"[{self.name}] 群功能开关未启用,仅采集不回群: target={target}")
|
||||
return
|
||||
if self._mention_user_on_group_reply and at_target:
|
||||
await bot.send_at_message(target, reply_text, [at_target])
|
||||
else:
|
||||
await bot.send_text_message(target, reply_text, at_target if at_target else "")
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 已发出 MaiBot 群回复: target={target}, at_target={at_target}, "
|
||||
f"reply_len={len(reply_text)}"
|
||||
)
|
||||
@@ -465,10 +469,10 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
|
||||
if route_type == "private":
|
||||
if not self._reply_private_messages:
|
||||
self.LOG.info(f"[{self.name}] reply_private_messages=false,私聊回复已跳过: target={target}")
|
||||
self._log_runtime(f"[{self.name}] reply_private_messages=false,私聊回复已跳过: target={target}")
|
||||
return
|
||||
await bot.send_text_message(target, reply_text, "")
|
||||
self.LOG.info(f"[{self.name}] 已发出 MaiBot 私聊回复: target={target}, reply_len={len(reply_text)}")
|
||||
self._log_runtime(f"[{self.name}] 已发出 MaiBot 私聊回复: target={target}, reply_len={len(reply_text)}")
|
||||
return
|
||||
|
||||
self.LOG.warning(f"[{self.name}] 未知路由类型,无法发送 MaiBot 回复: route={route}, api_message={api_message}")
|
||||
@@ -506,7 +510,7 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
group_name = self._resolve_group_name(message, roomid)
|
||||
|
||||
# 路由诊断日志:这里把关键字段一次性打全,便于定位“群消息为何被识别成私聊”。
|
||||
self.LOG.info(
|
||||
self._log_runtime(
|
||||
f"[{self.name}] 路由判定: route_type={route_type}, route_source={route_source}, "
|
||||
f"plugin_roomid={str(message.get('roomid', '') or '').strip()}, "
|
||||
f"wx_roomid={str(getattr(full_msg, 'roomid', '') or '').strip() if isinstance(full_msg, WxMessage) else ''}, "
|
||||
@@ -813,6 +817,13 @@ class MaiBotAdapterPlugin(MessagePluginInterface):
|
||||
return None
|
||||
return payload
|
||||
|
||||
def _log_runtime(self, message: str) -> None:
|
||||
"""根据插件配置动态输出运行日志级别。"""
|
||||
if self._log_level == "DEBUG":
|
||||
self.LOG.debug(message)
|
||||
return
|
||||
self.LOG.info(message)
|
||||
|
||||
def _is_supported_message(self, message: Dict[str, Any]) -> bool:
|
||||
"""仅接收 MaiBot 当前最适合做上下文理解的消息类型。"""
|
||||
full_msg = message.get("full_wx_msg")
|
||||
|
||||
Reference in New Issue
Block a user