TraceStudio-dev/server/tests/web1.1_server.py
2026-01-09 21:37:02 +08:00

314 lines
11 KiB
Python
Raw 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.

"""
TraceStudio 后端服务 - v1.1 测试版本
基于 FastAPI 的数据处理和节点执行引擎
此文件保留作为前端测试用途
"""
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
import sys
from pathlib import Path
# 添加父目录到 Python 路径
sys.path.insert(0, str(Path(__file__).parent.parent))
# 导入文件管理模块
from file_manager import router as file_router, init_base_structure
app = FastAPI(
title="TraceStudio Server v1.1",
description="ComfyUI 风格的 Unreal Insights 数据分析后端 - 测试版本",
version="1.1.0"
)
# 配置 CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 开发环境允许所有来源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册文件管理路由
app.include_router(file_router)
# 启动时初始化文件系统
@app.on_event("startup")
async def startup_event():
"""应用启动时初始化"""
init_base_structure()
print("🚀 TraceStudio Server v1.1 (测试版) 启动完成")
@app.get("/")
async def root():
"""服务健康检查"""
return {
"status": "running",
"service": "TraceStudio Server",
"version": "1.1.0",
"mode": "test"
}
@app.get("/api/plugins")
async def get_plugins():
"""
返回所有可用的算子(节点)列表
前端从这里获取可拖拽的节点类型
"""
return {
"plugins": {
# Loaders 类别
"CSVLoader": {
"display_name": "CSV 数据加载器",
"function": "Loader", # 节点功能:加载器
"category": "Loader/CSV", # 树状目录:加载器/CSV
"node_logic": "standard", # 普通节点
"supports_preview": True,
"inputs": [],
"outputs": [{"name": "table", "type": "DataTable"}],
"param_schema": {
"file_path": {
"type": "string",
"default": "",
"description": "CSV 文件路径"
},
"delimiter": {
"type": "string",
"default": ",",
"description": "分隔符"
}
}
},
"UTraceLoader": {
"display_name": "UTrace 文件加载器",
"function": "Loader", # 节点功能:加载器
"category": "Loader", # 树状目录:加载器/Trace
"node_logic": "standard",
"supports_preview": True,
"inputs": [],
"outputs": [{"name": "events", "type": "DataTable"}],
"param_schema": {
"trace_file": {
"type": "string",
"default": "",
"description": "utrace 文件路径"
}
}
},
# Transforms 类别
"FilterRows": {
"display_name": "行过滤器",
"function": "Transform", # 节点功能:转换器
"category": "Transform/Filter", # 树状目录:转换器/过滤
"node_logic": "standard",
"supports_preview": True,
"inputs": [{"name": "input", "type": "DataTable"}],
"outputs": [{"name": "output", "type": "DataTable"}],
"param_schema": {
"column": {
"type": "string",
"default": "",
"description": "要过滤的列名",
"dynamic": True # 需要动态获取列名
},
"condition": {
"type": "string",
"default": ">",
"description": "条件运算符"
},
"value": {
"type": "string",
"default": "0",
"description": "比较值"
}
}
},
"SelectColumns": {
"display_name": "列选择器",
"function": "Transform",
"category": "Transform/Select",
"node_logic": "standard",
"supports_preview": True,
"inputs": [{"name": "input", "type": "DataTable"}],
"outputs": [{"name": "output", "type": "DataTable"}],
"param_schema": {
"columns": {
"type": "string",
"default": "",
"description": "要保留的列名(逗号分隔)",
"dynamic": True
}
}
},
"Aggregator": {
"display_name": "数据聚合",
"function": "Transform",
"category": "Transform/Aggregate",
"node_logic": "aggregate", # 聚合节点
"allow_multiple_inputs": True, # 允许多输入
"supports_preview": True,
"inputs": [{"name": "input", "type": "DataTable"}],
"outputs": [{"name": "result", "type": "DataTable"}],
"param_schema": {
"group_by": {
"type": "string",
"default": "",
"description": "分组字段",
"dynamic": True
},
"agg_func": {
"type": "string",
"default": "mean",
"description": "聚合函数mean/sum/count"
}
}
},
# Filters 类别
"TimeRangeFilter": {
"display_name": "时间范围过滤",
"function": "Transform",
"category": "Transform/Filter",
"node_logic": "standard",
"supports_preview": True,
"inputs": [{"name": "input", "type": "DataTable"}],
"outputs": [{"name": "output", "type": "DataTable"}],
"param_schema": {
"time_column": {
"type": "string",
"default": "timestamp",
"description": "时间列名",
"dynamic": True
},
"start_time": {
"type": "integer",
"default": 0,
"description": "开始时间"
},
"end_time": {
"type": "integer",
"default": 1000,
"description": "结束时间"
}
}
},
# Visualizers 类别
"ChartVisualizer": {
"display_name": "图表可视化",
"function": "Visualizer",
"category": "Visualizer/Chart",
"node_logic": "standard",
"supports_preview": True,
"inputs": [{"name": "data", "type": "DataTable"}],
"outputs": [],
"param_schema": {
"chart_type": {
"type": "string",
"default": "line",
"description": "图表类型line/bar/scatter"
},
"x_column": {
"type": "string",
"default": "",
"description": "X 轴列名",
"dynamic": True
},
"y_column": {
"type": "string",
"default": "",
"description": "Y 轴列名",
"dynamic": True
}
}
},
"TableOutput": {
"display_name": "表格输出",
"function": "Visualizer",
"category": "Visualizer/Table",
"node_logic": "standard",
"supports_preview": True,
"inputs": [{"name": "data", "type": "DataTable"}],
"outputs": [],
"param_schema": {
"max_rows": {
"type": "integer",
"default": 100,
"description": "最大显示行数"
}
}
}
}
}
@app.post("/api/node/preview")
async def preview_node(payload: dict):
"""
预览节点的输出数据(采样模式)
这是一个占位实现,用于前端测试
"""
node = payload.get("node", {})
limit = payload.get("limit", 10)
# 模拟数据预览
node_type = node.get("type", "unknown")
if node_type == "Loader":
return {
"columns": ["timestamp", "frame_time", "cpu_usage", "memory_mb"],
"preview": [
{"timestamp": 0, "frame_time": 16.7, "cpu_usage": 45.2, "memory_mb": 1024},
{"timestamp": 16, "frame_time": 17.1, "cpu_usage": 48.5, "memory_mb": 1028},
{"timestamp": 32, "frame_time": 16.3, "cpu_usage": 43.8, "memory_mb": 1025},
{"timestamp": 48, "frame_time": 18.2, "cpu_usage": 52.1, "memory_mb": 1032},
{"timestamp": 64, "frame_time": 16.9, "cpu_usage": 46.7, "memory_mb": 1027},
][:limit]
}
elif node_type == "Transform":
return {
"columns": ["timestamp", "frame_time"],
"preview": [
{"timestamp": 0, "frame_time": 16.7},
{"timestamp": 16, "frame_time": 17.1},
{"timestamp": 32, "frame_time": 16.3},
][:limit]
}
else:
return {
"error": f"节点类型 '{node_type}' 暂未实现预览功能"
}
@app.post("/graph/execute")
async def execute_graph(payload: dict):
"""
执行完整的计算图
这是一个占位实现
"""
nodes = payload.get("nodes", [])
edges = payload.get("edges", [])
return {
"status": "success",
"message": f"成功执行了包含 {len(nodes)} 个节点和 {len(edges)} 条连接的计算图",
"execution_time": 0.123
}
if __name__ == "__main__":
print("🚀 启动 TraceStudio 测试服务器 v1.1...")
print("📡 访问 http://127.0.0.1:8000/docs 查看 API 文档")
print("⚠️ 这是测试版本,用于前端开发")
uvicorn.run(
app,
host="127.0.0.1",
port=8000,
reload=True # 开发模式自动重载
)