新增系统健康快照并更新优化文档
This commit is contained in:
@@ -14,6 +14,7 @@ import yaml
|
||||
import toml
|
||||
from utils.markdown_to_image import get_md2img_health_snapshot, warmup_md2img_browser_sync
|
||||
from utils.ai.llm_registry import LLMRegistry
|
||||
from base.plugin_common.plugin_interface import PluginStatus
|
||||
|
||||
# 创建系统信息蓝图
|
||||
system_bp = Blueprint('system', __name__)
|
||||
@@ -364,6 +365,129 @@ def api_system_info():
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@system_bp.route('/api/system_health_summary')
|
||||
@login_required
|
||||
def api_system_health_summary():
|
||||
"""聚合首页可观测性所需的关键健康信号。"""
|
||||
try:
|
||||
server = current_app.dashboard_server
|
||||
robot = getattr(server, "robot", None)
|
||||
plugin_manager = getattr(server, "plugin_manager", None)
|
||||
plugin_map = getattr(plugin_manager, "plugins", {}) or {}
|
||||
|
||||
# 统计插件运行状态,便于首页快速判断“加载了多少、真正跑起来多少、是否有异常插件”。
|
||||
plugin_status_counter = {
|
||||
"total": len(plugin_map),
|
||||
"running": 0,
|
||||
"loaded": 0,
|
||||
"stopped": 0,
|
||||
"error": 0,
|
||||
"unloaded": 0,
|
||||
"unknown": 0,
|
||||
}
|
||||
for plugin in plugin_map.values():
|
||||
status = getattr(plugin, "status", None)
|
||||
if status == PluginStatus.RUNNING:
|
||||
plugin_status_counter["running"] += 1
|
||||
elif status == PluginStatus.LOADED:
|
||||
plugin_status_counter["loaded"] += 1
|
||||
elif status == PluginStatus.STOPPED:
|
||||
plugin_status_counter["stopped"] += 1
|
||||
elif status == PluginStatus.ERROR:
|
||||
plugin_status_counter["error"] += 1
|
||||
elif status == PluginStatus.UNLOADED:
|
||||
plugin_status_counter["unloaded"] += 1
|
||||
else:
|
||||
plugin_status_counter["unknown"] += 1
|
||||
|
||||
# 错误数量直接复用现有统计库,避免为了首页卡片再单独写一套 SQL。
|
||||
_, recent_error_count = server.stats_db.get_error_logs(days=1, page=1, limit=1)
|
||||
|
||||
# md2img 健康快照已经有现成实现,这里只做聚合,不主动预热运行时。
|
||||
md2img_snapshot = get_md2img_health_snapshot(ensure_runtime=False) or {}
|
||||
browser_ready = bool(
|
||||
md2img_snapshot.get("browser_ready")
|
||||
or md2img_snapshot.get("playwright_ready")
|
||||
or md2img_snapshot.get("ready")
|
||||
)
|
||||
runtime_ready = bool(
|
||||
md2img_snapshot.get("runtime_ready")
|
||||
or md2img_snapshot.get("runtime_initialized")
|
||||
or md2img_snapshot.get("initialized")
|
||||
)
|
||||
md2img_healthy = runtime_ready and browser_ready
|
||||
|
||||
# 首页只需要“够判断”的轻量结论,因此统一产出 status + summary 文本,前端无需重复拼装业务规则。
|
||||
robot_running = bool(getattr(robot, "ipad_running", False))
|
||||
robot_nickname = str(getattr(robot, "nickname", "") or "").strip()
|
||||
robot_wxid = str(getattr(robot, "wxid", "") or "").strip()
|
||||
robot_summary = "已连接并正在处理消息" if robot_running else "未连接或主循环未运行"
|
||||
if robot_nickname or robot_wxid:
|
||||
robot_summary = f"{robot_summary} · {robot_nickname or robot_wxid}"
|
||||
|
||||
if plugin_status_counter["error"] > 0:
|
||||
plugin_status = "warning"
|
||||
plugin_summary = f"异常 {plugin_status_counter['error']} 个,运行中 {plugin_status_counter['running']} / {plugin_status_counter['total']}"
|
||||
elif plugin_status_counter["running"] == 0 and plugin_status_counter["total"] > 0:
|
||||
plugin_status = "warning"
|
||||
plugin_summary = f"暂无运行中插件,共加载 {plugin_status_counter['total']} 个"
|
||||
else:
|
||||
plugin_status = "healthy"
|
||||
plugin_summary = f"运行中 {plugin_status_counter['running']} / {plugin_status_counter['total']}"
|
||||
|
||||
if recent_error_count > 0:
|
||||
error_status = "warning"
|
||||
error_summary = f"近 24 小时记录到 {recent_error_count} 条异常"
|
||||
else:
|
||||
error_status = "healthy"
|
||||
error_summary = "近 24 小时未记录到异常"
|
||||
|
||||
if md2img_healthy:
|
||||
md2img_status = "healthy"
|
||||
md2img_summary = "运行时与浏览器均已就绪"
|
||||
elif runtime_ready or browser_ready:
|
||||
md2img_status = "warning"
|
||||
md2img_summary = "运行时部分可用,建议检查预热状态"
|
||||
else:
|
||||
md2img_status = "danger"
|
||||
md2img_summary = "运行时未就绪,相关转图能力可能不可用"
|
||||
|
||||
return jsonify({
|
||||
"success": True,
|
||||
"data": {
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"robot": {
|
||||
"status": "healthy" if robot_running else "danger",
|
||||
"running": robot_running,
|
||||
"nickname": robot_nickname,
|
||||
"wxid": robot_wxid,
|
||||
"summary": robot_summary,
|
||||
},
|
||||
"plugins": {
|
||||
"status": plugin_status,
|
||||
"summary": plugin_summary,
|
||||
**plugin_status_counter,
|
||||
},
|
||||
"errors": {
|
||||
"status": error_status,
|
||||
"recent_24h_count": recent_error_count,
|
||||
"summary": error_summary,
|
||||
},
|
||||
"md2img": {
|
||||
"status": md2img_status,
|
||||
"healthy": md2img_healthy,
|
||||
"runtime_ready": runtime_ready,
|
||||
"browser_ready": browser_ready,
|
||||
"summary": md2img_summary,
|
||||
"detail": md2img_snapshot,
|
||||
},
|
||||
}
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"获取系统健康摘要失败: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
|
||||
|
||||
@system_bp.route('/api/wx_logs')
|
||||
@login_required
|
||||
def api_wx_logs():
|
||||
|
||||
Reference in New Issue
Block a user