From ce09bb4c7205649d885bad087e101a1f6a2df383 Mon Sep 17 00:00:00 2001 From: houxu Date: Tue, 12 Aug 2025 14:44:08 +0800 Subject: [PATCH] Update mcp and protobuf package version compatibility issue --- failslow/requirements.txt | 2 +- failslow/setup.py | 2 +- .../mcp_server => systrace_mcp}/README.md | 100 ++++---- .../config/ftp_config.json | 0 .../config/openapi.yml | 0 .../service/systrace-mcpserver.service | 0 .../mcp_server => systrace_mcp}/setup.py | 10 +- .../systrace_mcp}/__init__.py | 0 .../systrace_mcp}/fail_slow_detection_api.py | 0 .../systrace_mcp}/mcp_data.py | 40 ++-- .../systrace_mcp}/mcp_server.py | 214 +++++++++--------- .../systrace_mcp}/openapi_server.py | 10 +- .../systrace_mcp}/remote_file_fetcher.py | 0 .../systrace_mcp}/report_api.py | 160 ++++++------- 14 files changed, 266 insertions(+), 272 deletions(-) rename {failslow/mcp_server => systrace_mcp}/README.md (94%) rename {failslow/mcp_server => systrace_mcp}/config/ftp_config.json (100%) rename {failslow/mcp_server => systrace_mcp}/config/openapi.yml (100%) rename {failslow/mcp_server => systrace_mcp}/service/systrace-mcpserver.service (100%) rename {failslow/mcp_server => systrace_mcp}/setup.py (88%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/__init__.py (100%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/fail_slow_detection_api.py (100%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/mcp_data.py (97%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/mcp_server.py (83%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/openapi_server.py (92%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/remote_file_fetcher.py (100%) rename {failslow/mcp_server => systrace_mcp/systrace_mcp}/report_api.py (97%) diff --git a/failslow/requirements.txt b/failslow/requirements.txt index 65c9685..81c41b5 100644 --- a/failslow/requirements.txt +++ b/failslow/requirements.txt @@ -6,4 +6,4 @@ xarray==2023.10.0 matplotlib scikit_learn==0.24.2 joblib==0.14.1 -protobuf==3.20.3 \ No newline at end of file +protobuf \ No newline at end of file diff --git a/failslow/setup.py b/failslow/setup.py index 618f377..26d89be 100644 --- a/failslow/setup.py +++ b/failslow/setup.py @@ -46,7 +46,7 @@ setup( "matplotlib", "joblib", "scikit_learn", - "protobuf==3.20.3" + "protobuf" ], entry_points={ "console_scripts": [ diff --git a/failslow/mcp_server/README.md b/systrace_mcp/README.md similarity index 94% rename from failslow/mcp_server/README.md rename to systrace_mcp/README.md index b590f8f..473db0e 100644 --- a/failslow/mcp_server/README.md +++ b/systrace_mcp/README.md @@ -1,51 +1,51 @@ -# README - -# 安装部署 -## 前置条件 -支持的python版本:3.7+; -failslow 依赖于 systrace 采集的数据通信算子数据,请先完成 训练任务的 通信算子采集; - -failslow-mcpserver 支持本地或者远程获取远程目标服务器的systrace 采集的通信算子数据,需要在配置文件中指定通信算子数据的路径。 -failslow-openapi 支持本地或者远程获取远程目标服务器的systrace 采集的通信算子数据,需要在配置文件中指定通信算子数据的路径。 - -## 从本仓库源码安装运行(适用于开发者) -### 下载源码 - git clone https://gitee.com/openeuler/sysTrace.git -### 安装 failslow -工程./systrace目录下执行下面命令: -python3 setup.py install -### 运行 -systrace-failslow - -### 安装mcpserver -工程./systrace/mcp_server目录下执行下面命令: -python3 setup.py install -### 运行 -systrace-mcpserver #开启mcp server服务 服务端口为 12145 - -systrace-openapi #开启openapi server服务 服务端口 12146 - - -配置远程获取数据,修改./config/ftp_config.json文件 -~~~json -{ - "servers": [ - { - "ip": "192.168.122.196", #远程目标服务器的ip - "port": 22, #远程目标服务器的ssh端口 - "user": "root", #用户名 - "password": "Huawei12#$", #密码 - "perception_remote_dir": "/home/hx/sysTrace_dataloader/timeline", #远程目标服务器systrace采集的timeline数据保存路径 - "detection_remote_dir": "/home/hx/sysTrace_dataloader/mspti",#远程目标服务器systrace采集的mspti数据保存路径 - } - ], - "enable": "False" #True 为开启远程获取数据,False为关闭只使用本地文件进行分析 -} - -~~~ - - -### 数据分析 -**算子执行**:3ms左右,计算慢导致的异常时7-8ms -**算子下发**: 表示算子下发到算子开始执行的时间 600ms左右 +# README + +# 安装部署 +## 前置条件 +支持的python版本:3.7+; +failslow 依赖于 systrace 采集的数据通信算子数据,请先完成 训练任务的 通信算子采集; + +failslow-mcpserver 支持本地或者远程获取远程目标服务器的systrace 采集的通信算子数据,需要在配置文件中指定通信算子数据的路径。 +failslow-openapi 支持本地或者远程获取远程目标服务器的systrace 采集的通信算子数据,需要在配置文件中指定通信算子数据的路径。 + +## 从本仓库源码安装运行(适用于开发者) +### 下载源码 + git clone https://gitee.com/openeuler/sysTrace.git +### 安装 failslow +工程./systrace目录下执行下面命令: +python3 setup.py install +### 运行 +systrace-failslow + +### 安装mcpserver +工程./systrace/systrace_mcp目录下执行下面命令: +python3 setup.py install +### 运行 +systrace-mcpserver #开启mcp server服务 服务端口为 12145 + +systrace-openapi #开启openapi server服务 服务端口 12146 + + +配置远程获取数据,修改./config/ftp_config.json文件 +~~~json +{ + "servers": [ + { + "ip": "192.168.122.196", #远程目标服务器的ip + "port": 22, #远程目标服务器的ssh端口 + "user": "root", #用户名 + "password": "Huawei12#$", #密码 + "perception_remote_dir": "/home/hx/sysTrace_dataloader/timeline", #远程目标服务器systrace采集的timeline数据保存路径 + "detection_remote_dir": "/home/hx/sysTrace_dataloader/mspti",#远程目标服务器systrace采集的mspti数据保存路径 + } + ], + "enable": "False" #True 为开启远程获取数据,False为关闭只使用本地文件进行分析 +} + +~~~ + + +### 数据分析 +**算子执行**:3ms左右,计算慢导致的异常时7-8ms +**算子下发**: 表示算子下发到算子开始执行的时间 600ms左右 **通信慢**: sendrecv:几十ms到1200ms \ No newline at end of file diff --git a/failslow/mcp_server/config/ftp_config.json b/systrace_mcp/config/ftp_config.json similarity index 100% rename from failslow/mcp_server/config/ftp_config.json rename to systrace_mcp/config/ftp_config.json diff --git a/failslow/mcp_server/config/openapi.yml b/systrace_mcp/config/openapi.yml similarity index 100% rename from failslow/mcp_server/config/openapi.yml rename to systrace_mcp/config/openapi.yml diff --git a/failslow/mcp_server/service/systrace-mcpserver.service b/systrace_mcp/service/systrace-mcpserver.service similarity index 100% rename from failslow/mcp_server/service/systrace-mcpserver.service rename to systrace_mcp/service/systrace-mcpserver.service diff --git a/failslow/mcp_server/setup.py b/systrace_mcp/setup.py similarity index 88% rename from failslow/mcp_server/setup.py rename to systrace_mcp/setup.py index 0fef521..20fe073 100644 --- a/failslow/mcp_server/setup.py +++ b/systrace_mcp/setup.py @@ -20,8 +20,8 @@ ser = "/usr/lib/systemd/system/systrac-mcpserver.service" if os.path.isfile(ser): os.remove(ser) setup( - name="systrace_mcpserver", - version="1.0.0", + name="systrace_mcp", + version="1.1.1", author="xu hou", author_email="houxu5@h-partners.com", description="MCP Server for SystraceFail Slow Detection for AI Model Training and Inference", @@ -34,13 +34,13 @@ setup( ], install_requires=[ "systrace_failslow", - "mcp==1.10.1", + "mcp", "paramiko" ], entry_points={ "console_scripts": [ - "systrace-mcpserver=mcp_server.mcp_server:main", - "systrace-openapi=mcp_server.openapi_server:main" + "systrace-mcpserver=systrace_mcp.mcp_server:main", + "systrace-openapi=systrace_mcp.openapi_server:main" ] } ) \ No newline at end of file diff --git a/failslow/mcp_server/__init__.py b/systrace_mcp/systrace_mcp/__init__.py similarity index 100% rename from failslow/mcp_server/__init__.py rename to systrace_mcp/systrace_mcp/__init__.py diff --git a/failslow/mcp_server/fail_slow_detection_api.py b/systrace_mcp/systrace_mcp/fail_slow_detection_api.py similarity index 100% rename from failslow/mcp_server/fail_slow_detection_api.py rename to systrace_mcp/systrace_mcp/fail_slow_detection_api.py diff --git a/failslow/mcp_server/mcp_data.py b/systrace_mcp/systrace_mcp/mcp_data.py similarity index 97% rename from failslow/mcp_server/mcp_data.py rename to systrace_mcp/systrace_mcp/mcp_data.py index a1cadb5..4ab38a4 100644 --- a/failslow/mcp_server/mcp_data.py +++ b/systrace_mcp/systrace_mcp/mcp_data.py @@ -1,20 +1,20 @@ -from typing_extensions import TypedDict, List -from dataclasses import dataclass, field -from typing import List, Dict, Any - -class AnomalyInfo(TypedDict): - """劣化详细信息结构""" - metric_name: str #是否发生性能劣化 - threshold: float - actual_value: float - timestamp: int - -class PerceptionResult(TypedDict): - """慢节点感知结果结构""" - is_anomaly: bool #是否发生性能劣化 - anomaly_count_times: int #劣化次数 - anomaly_info: List[AnomalyInfo] #劣化详细信息 - start_time: int # Unix timestamp in milliseconds 劣化开始时间 - end_time: int # Unix timestamp in milliseconds 劣化结束时间 - anomaly_type: str # 劣化类型 - task_id: str #服务ip +from typing_extensions import TypedDict, List +from dataclasses import dataclass, field +from typing import List, Dict, Any + +class AnomalyInfo(TypedDict): + """劣化详细信息结构""" + metric_name: str #是否发生性能劣化 + threshold: float + actual_value: float + timestamp: int + +class PerceptionResult(TypedDict): + """慢节点感知结果结构""" + is_anomaly: bool #是否发生性能劣化 + anomaly_count_times: int #劣化次数 + anomaly_info: List[AnomalyInfo] #劣化详细信息 + start_time: int # Unix timestamp in milliseconds 劣化开始时间 + end_time: int # Unix timestamp in milliseconds 劣化结束时间 + anomaly_type: str # 劣化类型 + task_id: str #服务ip diff --git a/failslow/mcp_server/mcp_server.py b/systrace_mcp/systrace_mcp/mcp_server.py similarity index 83% rename from failslow/mcp_server/mcp_server.py rename to systrace_mcp/systrace_mcp/mcp_server.py index 5725021..bed7f4e 100644 --- a/failslow/mcp_server/mcp_server.py +++ b/systrace_mcp/systrace_mcp/mcp_server.py @@ -1,110 +1,104 @@ -from typing import Union - -import json - -from mcp.server import FastMCP - -from failslow.response.response import AIJobDetectResult -from failslow.util.logging_utils import get_default_logger -from failslow.util.constant import MODEL_CONFIG_PATH -from failslow.main import main as slow_node_detection_api - -from mcp_server.report_api import generate_normal_report, generate_degraded_report, generate_default_report -from mcp_server.mcp_data import PerceptionResult -from mcp_server.fail_slow_detection_api import run_slow_node_perception -from mcp_server.remote_file_fetcher import sync_server_by_ip_and_type - -logger = get_default_logger(__name__) -# 仅在 Linux 环境下强制使用 spawn 方式 -import multiprocessing -import os -if os.name == "posix": # posix 表示 Linux/macOS - multiprocessing.set_start_method("spawn", force=True) -# 创建MCP Server -mcp = FastMCP("SysTrace MCP Server", host="0.0.0.0", port=12145) - - -@mcp.prompt(title="self_introduction", - description="工具定位") -def self_introduction() -> str: - return "面向运维、开发人员,支持自然语言对接,实现启发式调优,实现3个工具接口,分别为性能劣化感知工具,慢卡定界工具,报告输出工具。" - - -@mcp.prompt(title="劣化感知", - description="调用逻辑:1. 当用户询问特定任务ID的机器性能是否劣化时调用。2. 检测结果将决定后续流程走向。\ - 3. 调用完成后如果出现劣化现象,则把当前工具得到的结果作为入参,调用slow_node_detection_tool方法 ,如果没有出现劣化现象,则调用报告工具返回报告给用户。\ - 4. 本方法得到的结果必须再调用generate_report 生成报告给到用户" - ) -@mcp.tool( - name="slow_node_perception_tool", - title="检测指定任务ID的机器性能是否发生劣化工具" -) -def slow_node_perception_tool(task_id: str) -> PerceptionResult: - """ - 这是检测指定task_id的机器性能是否发生劣化的工具; - 入参 task_id ,如 192.168.2.122; - 返回 PerceptionResult 如果is_anomaly=false,该结果需要调用generate_report_tool再返回给用户;如果is_anomaly=True,该结果必须调用slow_node_detection_tool得到报告 - """ - print("性能劣化感知工具 开启") - print("task_id = " + task_id) - - with open(MODEL_CONFIG_PATH, 'r', encoding='utf-8') as reader: - model_args = json.load(reader) - sync_server_by_ip_and_type(task_id, "perception") - res = run_slow_node_perception(model_args,task_id) - return res - - -@mcp.prompt(title="慢卡定界", - description="调用逻辑:1. 仅在感知工具返回is_anomaly=True时调用。2. 接收感知工具的全量性能数据作为输入。 3. 本方法得到的结果必须再调用generate_report 生成报告给到用户") -@mcp.tool(name="slow_node_detection_tool", - title="检查工具:当检测到性能劣化时诊断具体问题点,即定界工具") -def slow_node_detection_tool(performance_data: PerceptionResult) -> AIJobDetectResult: - """ - 这是针对slow_node_perception_tool工具返回is_anomaly=True时调用的慢卡定界工具 - 输入: - performance_data: 感知工具返回的完整性能数据PerceptionResult; - 输出:AIJobDetectResult,该结果必须要调用generate_report_tool得到报告再返回给用户 - """ - print("慢卡定界工具") - print("performance_data = " + str(performance_data)) - sync_server_by_ip_and_type(performance_data["task_id"], "detection") - _res = slow_node_detection_api() - print(json.dumps(_res)) - return _res - - -@mcp.prompt(title="报告生成工具", - description="调用slow_node_perception_tool 或 slow_node_detection_tool 后把结果传入generate_report ") -@mcp.tool() -def generate_report_tool(source_data: Union[dict, str], report_type: str) -> dict: - """ - 使用 报告工具:生成最终Markdown格式报告 - 输入: - source_data 感知或定界的结果 - report_type 是否劣化 normal anomaly - 您是一个专业的性能劣化分析人员,擅长分析服务器运行健康状态,生成报告,报告标题“AI训练任务性能诊断报告”。一下内容如实回答,不要发散。注意训练任务使用的是NPU卡,不是GPU,不要带有GPU相关字眼。未劣化时,直接给结论,不要发散,没有cpu、磁盘等指标之类的字眼。 - 当前时间:{{ time }},可以作为时间参照。 - 先判断是否性能劣化,{report_type}为normal 未劣化,anomaly 劣化; - 未劣化分析步骤如下: - 1、总览:根据里的{start_time}{end_time}得到开始和结束时间,结论是当前AI训练任务运行正常,将持续监测。 - 劣化分析步骤如下: - 1、总览:根据里的{time}得到检测时间,{abnormalNodeCount}异常节点数量,{compute}{network}{storage}异常类型true为异常,false正常; - 2、细节:每条节点的具体卡号{objectId}、异常指标{kpiId}(其中:HcclAllGather表示集合通信库的AllGather时序序列指标;HcclReduceScatter表示集合通信库的ReduceScatter时序序列指标;HcclAllReduce表示集合通信库的AllReduce时序序列指标;),检测方法{methodType}(SPACE 多节点空间对比检测器,TIME 单节点时间检测器),以表格形式呈现; - 3、针对这个节点给出检测建议,如果是计算类型,建议检测卡的状态,算子下发以及算子执行的代码,对慢节点进行隔离;如果是网络问题,建议检测组网的状态,使用压测节点之间的连通状态;如果是存储问题,建议检测存储的磁盘以及用户脚本中的dataloader和保存模型代码。 - """ - print("调用了报告工具,report_type = " + report_type) - # 根据报告类型调用对应的生成方法 - if report_type == "normal": - return json.dumps(generate_normal_report(source_data)) - elif report_type == "anomaly": - return json.dumps(generate_degraded_report(source_data)) - else: - # 默认报告类型 - return generate_default_report(source_data) - -def main(): - # 初始化并启动服务 - mcp.run(transport='sse') -if __name__ == "__main__": - main() +from typing import Union + +import json + +from mcp.server import FastMCP + +from failslow.response.response import AIJobDetectResult +from failslow.util.logging_utils import get_default_logger +from failslow.util.constant import MODEL_CONFIG_PATH +from failslow.main import main as slow_node_detection_api + +from systrace_mcp.report_api import generate_normal_report, generate_degraded_report, generate_default_report +from systrace_mcp.mcp_data import PerceptionResult +from systrace_mcp.fail_slow_detection_api import run_slow_node_perception +from systrace_mcp.remote_file_fetcher import sync_server_by_ip_and_type + +logger = get_default_logger(__name__) +# 仅在 Linux 环境下强制使用 spawn 方式 +import multiprocessing +import os +if os.name == "posix": # posix 表示 Linux/macOS + multiprocessing.set_start_method("spawn", force=True) +# 创建MCP Server +mcp = FastMCP("SysTrace MCP Server", host="0.0.0.0", port=12145) + + +@mcp.prompt(description="工具定位") +def self_introduction() -> str: + return "面向运维、开发人员,支持自然语言对接,实现启发式调优,实现3个工具接口,分别为性能劣化感知工具,慢卡定界工具,报告输出工具。" + + +@mcp.prompt(description="调用逻辑:1. 当用户询问特定任务ID的机器性能是否劣化时调用。2. 检测结果将决定后续流程走向。\ + 3. 调用完成后如果出现劣化现象,则把当前工具得到的结果作为入参,调用slow_node_detection_tool方法 ,如果没有出现劣化现象,则调用报告工具返回报告给用户。\ + 4. 本方法得到的结果必须再调用generate_report 生成报告给到用户" + ) +@mcp.tool( + name="slow_node_perception_tool" +) +def slow_node_perception_tool(task_id: str) -> PerceptionResult: + """ + 这是检测指定task_id的机器性能是否发生劣化的工具; + 入参 task_id ,如 192.168.2.122; + 返回 PerceptionResult 如果is_anomaly=false,该结果需要调用generate_report_tool再返回给用户;如果is_anomaly=True,该结果必须调用slow_node_detection_tool得到报告 + """ + print("性能劣化感知工具 开启") + print("task_id = " + task_id) + + with open(MODEL_CONFIG_PATH, 'r', encoding='utf-8') as reader: + model_args = json.load(reader) + sync_server_by_ip_and_type(task_id, "perception") + res = run_slow_node_perception(model_args,task_id) + return res + + +@mcp.prompt(description="调用逻辑:1. 仅在感知工具返回is_anomaly=True时调用。2. 接收感知工具的全量性能数据作为输入。 3. 本方法得到的结果必须再调用generate_report 生成报告给到用户") +@mcp.tool(name="slow_node_detection_tool") +def slow_node_detection_tool(performance_data: PerceptionResult) -> AIJobDetectResult: + """ + 这是针对slow_node_perception_tool工具返回is_anomaly=True时调用的慢卡定界工具 + 输入: + performance_data: 感知工具返回的完整性能数据PerceptionResult; + 输出:AIJobDetectResult,该结果必须要调用generate_report_tool得到报告再返回给用户 + """ + print("慢卡定界工具") + print("performance_data = " + str(performance_data)) + sync_server_by_ip_and_type(performance_data["task_id"], "detection") + _res = slow_node_detection_api() + print(json.dumps(_res)) + return _res + + +@mcp.prompt(description="调用slow_node_perception_tool 或 slow_node_detection_tool 后把结果传入generate_report ") +@mcp.tool() +def generate_report_tool(source_data: Union[dict, str], report_type: str) -> dict: + """ + 使用 报告工具:生成最终Markdown格式报告 + 输入: + source_data 感知或定界的结果 + report_type 是否劣化 normal anomaly + 您是一个专业的性能劣化分析人员,擅长分析服务器运行健康状态,生成报告,报告标题“AI训练任务性能诊断报告”。一下内容如实回答,不要发散。注意训练任务使用的是NPU卡,不是GPU,不要带有GPU相关字眼。未劣化时,直接给结论,不要发散,没有cpu、磁盘等指标之类的字眼。 + 当前时间:{{ time }},可以作为时间参照。 + 先判断是否性能劣化,{report_type}为normal 未劣化,anomaly 劣化; + 未劣化分析步骤如下: + 1、总览:根据里的{start_time}{end_time}得到开始和结束时间,结论是当前AI训练任务运行正常,将持续监测。 + 劣化分析步骤如下: + 1、总览:根据里的{time}得到检测时间,{abnormalNodeCount}异常节点数量,{compute}{network}{storage}异常类型true为异常,false正常; + 2、细节:每条节点的具体卡号{objectId}、异常指标{kpiId}(其中:HcclAllGather表示集合通信库的AllGather时序序列指标;HcclReduceScatter表示集合通信库的ReduceScatter时序序列指标;HcclAllReduce表示集合通信库的AllReduce时序序列指标;),检测方法{methodType}(SPACE 多节点空间对比检测器,TIME 单节点时间检测器),以表格形式呈现; + 3、针对这个节点给出检测建议,如果是计算类型,建议检测卡的状态,算子下发以及算子执行的代码,对慢节点进行隔离;如果是网络问题,建议检测组网的状态,使用压测节点之间的连通状态;如果是存储问题,建议检测存储的磁盘以及用户脚本中的dataloader和保存模型代码。 + """ + print("调用了报告工具,report_type = " + report_type) + # 根据报告类型调用对应的生成方法 + if report_type == "normal": + return json.dumps(generate_normal_report(source_data)) + elif report_type == "anomaly": + return json.dumps(generate_degraded_report(source_data)) + else: + # 默认报告类型 + return generate_default_report(source_data) + +def main(): + # 初始化并启动服务 + mcp.run(transport='sse') +if __name__ == "__main__": + main() diff --git a/failslow/mcp_server/openapi_server.py b/systrace_mcp/systrace_mcp/openapi_server.py similarity index 92% rename from failslow/mcp_server/openapi_server.py rename to systrace_mcp/systrace_mcp/openapi_server.py index ea5b154..a352d33 100644 --- a/failslow/mcp_server/openapi_server.py +++ b/systrace_mcp/systrace_mcp/openapi_server.py @@ -11,10 +11,10 @@ from failslow.response.response import AIJobDetectResult from failslow.main import main as slow_node_detection_api from failslow.util.logging_utils import get_default_logger from failslow.util.constant import MODEL_CONFIG_PATH -from mcp_server.mcp_data import PerceptionResult -from mcp_server.fail_slow_detection_api import run_slow_node_perception -from mcp_server.remote_file_fetcher import sync_server_by_ip_and_type -from mcp_server.report_api import generate_normal_report, generate_degraded_report, generate_default_report +from systrace_mcp.mcp_data import PerceptionResult +from systrace_mcp.fail_slow_detection_api import run_slow_node_perception +from systrace_mcp.remote_file_fetcher import sync_server_by_ip_and_type +from systrace_mcp.report_api import generate_normal_report, generate_degraded_report, generate_default_report # 仅在 Linux 环境下强制使用 spawn 方式 import multiprocessing @@ -121,7 +121,7 @@ async def slow_node_perception(ip: str = Query("127.0.0.1", description="节点I def main(): """启动服务""" - logger.info("启动性能调优数据采集接口服务...") + logger.info("启动systrace运维接口服务...") uvicorn.run(app, host="0.0.0.0", port=12146) diff --git a/failslow/mcp_server/remote_file_fetcher.py b/systrace_mcp/systrace_mcp/remote_file_fetcher.py similarity index 100% rename from failslow/mcp_server/remote_file_fetcher.py rename to systrace_mcp/systrace_mcp/remote_file_fetcher.py diff --git a/failslow/mcp_server/report_api.py b/systrace_mcp/systrace_mcp/report_api.py similarity index 97% rename from failslow/mcp_server/report_api.py rename to systrace_mcp/systrace_mcp/report_api.py index abe1dba..a5a9448 100644 --- a/failslow/mcp_server/report_api.py +++ b/systrace_mcp/systrace_mcp/report_api.py @@ -1,80 +1,80 @@ -import json -from datetime import datetime - - -def generate_normal_report(data: dict) -> dict: - """生成无劣化的正常报告""" - # 解析时间戳为可读格式 - timestamp = data.get("start_time") - start_time = datetime.fromtimestamp(timestamp // 1000).strftime("%Y-%m-%d %H:%M:%S") if timestamp else "未知时间" - timestamp = data.get("end_time") - end_time = datetime.fromtimestamp(timestamp // 1000).strftime("%Y-%m-%d %H:%M:%S") if timestamp else "未知时间" - data["start_time"] = start_time - data["end_time"] = end_time - - return data - - -def generate_degraded_report(data: dict) -> dict: - """ - 生成设备异常状态的JSON报告 - - 参数: - data: 包含设备状态信息的字典 - - 返回: - 格式化的JSON报告字典 - """ - # 解析时间戳为可读格式 - timestamp = data.get("timestamp") - detect_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") if timestamp else "未知时间" - # 提取异常信息 - abnormalDetail = data.get("abnormalDetail", []) - abnormal_count = len(abnormalDetail) - - - # 整理异常节点详情 - abnormal_nodes = [] - for abnormal in abnormalDetail: - abnormal_nodes.append({ - "objectId": abnormal.get("objectId"), - "serverIp": abnormal.get("serverIp"), - "deviceInfo": abnormal.get("deviceInfo"), - "methodType": abnormal.get("methodType"), - "kpiId":abnormal.get("kpiId"), - "relaIds": abnormal.get("relaIds", []) - }) - - # 整理正常节点信息 - normal_nodes = [item["deviceInfo"] for item in data.get("normalDetail", [])] - - # 构建JSON报告 - report = { - "reportName": "AI训练任务性能诊断报告", - "overview": { - "detectTime": detect_time, - "abnormalNodeCount": abnormal_count, - "compute": data.get("compute") , - "network": data.get("network") , - "storage": data.get("storage") , - }, - "abnormalNodes": abnormal_nodes, - "normalNodes": { - "count": len(normal_nodes), - "devices": normal_nodes - }, - "errorMessage": data.get("errorMsg", "") - } - - return report - - -def generate_default_report(data: dict) -> dict: - """生成默认报告(当类型不匹配时),返回JSON格式字典""" - return { - "report_title": "机器性能分析报告", - "warning": "报告类型未识别,以下是原始数据摘要", - "raw_data": data, - "report_type": "default" - } - +import json +from datetime import datetime + + +def generate_normal_report(data: dict) -> dict: + """生成无劣化的正常报告""" + # 解析时间戳为可读格式 + timestamp = data.get("start_time") + start_time = datetime.fromtimestamp(timestamp // 1000).strftime("%Y-%m-%d %H:%M:%S") if timestamp else "未知时间" + timestamp = data.get("end_time") + end_time = datetime.fromtimestamp(timestamp // 1000).strftime("%Y-%m-%d %H:%M:%S") if timestamp else "未知时间" + data["start_time"] = start_time + data["end_time"] = end_time + + return data + + +def generate_degraded_report(data: dict) -> dict: + """ + 生成设备异常状态的JSON报告 + + 参数: + data: 包含设备状态信息的字典 + + 返回: + 格式化的JSON报告字典 + """ + # 解析时间戳为可读格式 + timestamp = data.get("timestamp") + detect_time = datetime.fromtimestamp(timestamp).strftime("%Y-%m-%d %H:%M:%S") if timestamp else "未知时间" + # 提取异常信息 + abnormalDetail = data.get("abnormalDetail", []) + abnormal_count = len(abnormalDetail) + + + # 整理异常节点详情 + abnormal_nodes = [] + for abnormal in abnormalDetail: + abnormal_nodes.append({ + "objectId": abnormal.get("objectId"), + "serverIp": abnormal.get("serverIp"), + "deviceInfo": abnormal.get("deviceInfo"), + "methodType": abnormal.get("methodType"), + "kpiId":abnormal.get("kpiId"), + "relaIds": abnormal.get("relaIds", []) + }) + + # 整理正常节点信息 + normal_nodes = [item["deviceInfo"] for item in data.get("normalDetail", [])] + + # 构建JSON报告 + report = { + "reportName": "AI训练任务性能诊断报告", + "overview": { + "detectTime": detect_time, + "abnormalNodeCount": abnormal_count, + "compute": data.get("compute") , + "network": data.get("network") , + "storage": data.get("storage") , + }, + "abnormalNodes": abnormal_nodes, + "normalNodes": { + "count": len(normal_nodes), + "devices": normal_nodes + }, + "errorMessage": data.get("errorMsg", "") + } + + return report + + +def generate_default_report(data: dict) -> dict: + """生成默认报告(当类型不匹配时),返回JSON格式字典""" + return { + "report_title": "机器性能分析报告", + "warning": "报告类型未识别,以下是原始数据摘要", + "raw_data": data, + "report_type": "default" + } + -- Gitee