提交 7f4e853f authored 作者: 陈泽健's avatar 陈泽健

feat(performance): 批量执行进度WebSocket + 增强指标数据模型 + 合并报告PRD

- 新增 /ws/batch-progress WebSocket 固定分组(perf_batch)实时推送批量进度,
  须注册在 /ws/{task_id} 之前, 字段统一 snake_case(current_index/total_count/
  current_task_name/success_count/fail_count), 支持 ping/pong 保活
- frontend ProjectDetail.vue 批量进度字段 camelCase -> snake_case 对齐
- PerformanceTask 新增 16 项增强指标(p95/std_dev/latency/connect_time/peak_tps/
  apdex/错误分类计数)
- 新增 PerformanceBatchExecution / PerformanceProjectReport 模型 + 合并报告
  PRD 与执行计划文档
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 d0757333
此差异已折叠。
......@@ -291,6 +291,50 @@ async def get_task_results(
# ==================== Phase 3: WebSocket 实时监控 ====================
@router.websocket("/ws/batch-progress")
async def websocket_batch_progress(websocket: WebSocket):
"""
批量执行进度 WebSocket(固定分组,须注册在 /ws/{task_id} 之前)
客户端连接后订阅 perf_batch 分组,实时收到批量执行的进度广播。
消息格式(perf_batch_progress):
```json
{
"type": "perf_batch_progress",
"batch_id": "...",
"project_id": "...",
"current_index": 1,
"total_count": 5,
"current_task_id": "...",
"current_task_name": "任务名",
"current_status": "running",
"success_count": 1,
"fail_count": 0
}
```
current_status: running / completed / partially_failed / completed
"""
ws_group = "perf_batch"
await manager.connect(websocket, ws_group)
try:
# 保持连接,等待推送
while True:
try:
data = await websocket.receive_text()
msg = json.loads(data)
if msg.get("type") == "ping":
await manager.send_to(websocket, {"type": "pong"})
except json.JSONDecodeError:
pass
except WebSocketDisconnect:
logger.info("批量进度 WebSocket 断开连接")
except Exception as e:
logger.error(f"批量进度 WebSocket 异常: {e}")
finally:
await manager.disconnect(websocket, ws_group)
@router.websocket("/ws/{task_id}")
async def websocket_monitor(websocket: WebSocket, task_id: str):
"""
......
......@@ -377,11 +377,11 @@ function connectBatchWs() {
try {
const msg = JSON.parse(event.data)
if (msg.type === 'perf_batch_progress') {
batchCurrentIndex.value = msg.currentIndex
batchTotalCount.value = msg.totalCount
batchCurrentTaskName.value = msg.currentTaskName || ''
batchSuccessCount.value = msg.successCount || 0
batchFailCount.value = msg.failCount || 0
batchCurrentIndex.value = msg.current_index
batchTotalCount.value = msg.total_count
batchCurrentTaskName.value = msg.current_task_name || ''
batchSuccessCount.value = msg.success_count || 0
batchFailCount.value = msg.fail_count || 0
}
} catch {
// 忽略解析错误
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论