"""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_dashboard_service_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 个子域的关键指标。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetOverviewInput(start=start_time, end=end_time) output = await 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]: """系统维度统计。含启用状态/适配器类型/分类分组 + 熔断器状态。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetSystemsStatsInput() output = await 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]: """执行维度统计。含按状态/工具分组。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetExecutionsStatsInput( start=start_time, end=end_time, tool_limit=tool_limit, ) output = await 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 告警去重键。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetAlertsStatsInput( severity_status=severity_status, top_limit=top_limit, ) output = await 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]: """配额维度统计。含按窗口分组 + 预警/临界配额明细。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetQuotasStatsInput( warning_limit=warning_limit, critical_limit=critical_limit, ) output = await 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]: """健康维度统计。含按健康状态分组。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetHealthStatsInput() output = await 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]: """活动维度统计。含按操作类型分组。""" dashboard_service = create_dashboard_service_from_db(db) input_dto = GetActivitiesStatsInput(start=start_time, end=end_time) output = await dashboard_service.get_activities_stats(input_dto) return {"success": True, "data": output.model_dump()}