ForcePilot/backend/server/routers/external_systems/dashboard_router.py

149 lines
6.2 KiB
Python
Raw Normal View History

"""Dashboard 子域 Router。
外部系统限界上下文的监控仪表板 API覆盖全局总览 / 系统维度 /
执行维度 / 告警维度 / 配额维度 / 健康维度 / 活动维度的跨子域聚合统计
所有端点通过 ``create_use_cases_from_db`` 装配 use_cases
``dashboard_service`` 端口调用用例
路径顺序约束 router 所有端点均为静态路径无动态路径参数无路由匹配歧义
端点按业务维度组织总览 系统 执行 告警 配额 健康 活动
与上文子域覆盖顺序保持一致
认证策略
- 所有端点均为只读查询使用 get_required_user支持 JWT + API Key 双模认证
"""
from __future__ import annotations
from datetime import datetime
from typing import Any, Literal
from fastapi import APIRouter, Depends, Query
from sqlalchemy.ext.asyncio import AsyncSession
from yuxi.external_systems.infrastructure.container import create_use_cases_from_db
from yuxi.external_systems.use_cases.dto.dashboard import (
GetActivitiesStatsInput,
GetAlertsStatsInput,
GetExecutionsStatsInput,
GetHealthStatsInput,
GetOverviewInput,
GetQuotasStatsInput,
GetSystemsStatsInput,
)
from yuxi.storage.postgres.models_business import User
from server.utils.auth_middleware import get_db, get_required_user
dashboard_router = APIRouter(prefix="/dashboard", tags=["external-systems-dashboard"])
# ---------------- Endpoints ----------------
@dashboard_router.get("/overview", response_model=dict)
async def get_overview(
start_time: datetime | None = Query(None, description="执行统计起始时间"),
end_time: datetime | None = Query(None, description="执行统计结束时间"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""全局总览。聚合 5 个子域的关键指标。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetOverviewInput(start=start_time, end=end_time)
output = await use_cases.dashboard_service.get_overview(input_dto)
return {"success": True, "data": output.model_dump()}
@dashboard_router.get("/systems", response_model=dict)
async def get_systems_stats(
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""系统维度统计。含启用状态/适配器类型/分类分组 + 熔断器状态。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetSystemsStatsInput()
output = await use_cases.dashboard_service.get_systems_stats(input_dto)
return {"success": True, "data": output.model_dump()}
@dashboard_router.get("/executions", response_model=dict)
async def get_executions_stats(
start_time: datetime | None = Query(None, description="执行统计起始时间"),
end_time: datetime | None = Query(None, description="执行统计结束时间"),
tool_limit: int = Query(20, ge=1, le=100, description="Top 工具数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""执行维度统计。含按状态/工具分组。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetExecutionsStatsInput(
start=start_time,
end=end_time,
tool_limit=tool_limit,
)
output = await use_cases.dashboard_service.get_executions_stats(input_dto)
return {"success": True, "data": output.model_dump()}
@dashboard_router.get("/alerts", response_model=dict)
async def get_alerts_stats(
severity_status: Literal["firing", "acknowledged", "resolved", "suppressed"] = Query(
"firing",
description="count_by_severity 的状态过滤告警状态firing/acknowledged/resolved/suppressed",
),
top_limit: int = Query(10, ge=1, le=50, description="Top 告警去重键数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""告警维度统计。含按状态/严重程度分组 + Top 告警去重键。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetAlertsStatsInput(
severity_status=severity_status,
top_limit=top_limit,
)
output = await use_cases.dashboard_service.get_alerts_stats(input_dto)
return {"success": True, "data": output.model_dump()}
@dashboard_router.get("/quotas", response_model=dict)
async def get_quotas_stats(
warning_limit: int = Query(20, ge=1, le=100, description="预警配额明细数量"),
critical_limit: int = Query(20, ge=1, le=100, description="临界配额明细数量"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""配额维度统计。含按窗口分组 + 预警/临界配额明细。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetQuotasStatsInput(
warning_limit=warning_limit,
critical_limit=critical_limit,
)
output = await use_cases.dashboard_service.get_quotas_stats(input_dto)
return {"success": True, "data": output.model_dump()}
@dashboard_router.get("/health", response_model=dict)
async def get_health_stats(
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""健康维度统计。含按健康状态分组。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetHealthStatsInput()
output = await use_cases.dashboard_service.get_health_stats(input_dto)
return {"success": True, "data": output.model_dump()}
@dashboard_router.get("/activities", response_model=dict)
async def get_activities_stats(
start_time: datetime | None = Query(None, description="活动统计起始时间"),
end_time: datetime | None = Query(None, description="活动统计结束时间"),
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_required_user),
) -> dict[str, Any]:
"""活动维度统计。含按操作类型分组。"""
use_cases = create_use_cases_from_db(db)
input_dto = GetActivitiesStatsInput(start=start_time, end=end_time)
output = await use_cases.dashboard_service.get_activities_stats(input_dto)
return {"success": True, "data": output.model_dump()}