Files
taiji-AI-PAD/services/mcp-server/app/routes/monitoring.py
T
2026-01-07 10:46:55 +00:00

140 lines
5.2 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.
"""Monitoring endpoints that expose aggregated stats."""
from __future__ import annotations
import asyncio
import structlog
from fastapi import APIRouter, HTTPException, Depends
from typing import Optional
from monitoring import system_monitor
from app.auth import require_auth
logger = structlog.get_logger(__name__)
router = APIRouter(prefix="/api/v1/monitoring", tags=["monitoring"])
@router.get("/metrics")
async def get_system_metrics() -> dict:
"""Return live system metrics (CPU, memory, etc.)."""
try:
return await system_monitor.get_system_metrics()
except Exception as exc:
logger.error("获取系统指标失败", error=str(exc))
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/stats")
async def get_service_stats(service: str = "all") -> dict:
"""Return aggregate statistics for a specific subsystem."""
try:
return await system_monitor.get_service_stats(service)
except Exception as exc:
logger.error("获取服务统计失败", error=str(exc))
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/trends")
async def get_performance_trends(
metric: str = "executions", period: str = "24h", interval: str = "1h"
) -> dict:
"""Return trend data for executions or EU consumption."""
try:
return await system_monitor.get_performance_trends(metric, period, interval)
except Exception as exc:
logger.error("获取性能趋势失败", error=str(exc))
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/alerts")
async def get_system_alerts(severity: str | None = None) -> dict:
"""Return alert summaries with optional severity filtering."""
try:
alerts = await system_monitor.get_alerts(severity)
return {
"timestamp": await _current_timestamp(),
"alerts": alerts,
"count": len(alerts),
}
except Exception as exc:
logger.error("获取系统告警失败", error=str(exc))
raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/dashboard")
async def get_monitoring_dashboard(
principal: Optional[dict] = Depends(require_auth)
) -> dict:
"""
Aggregate health, metrics, stats, and alerts for dashboards.
如果用户已登录,返回租户级别的数据;否则返回全局数据。
返回数据包括:
1. 当前租户EU消耗过去24小时的消耗情况
2. 使用的模型和模型的使用情况、当前调用次数
3. 每周API调用的次数,7天的每一天调用多少次,包括成功和失败
4. 三个微服务的状态(mcp_server, data_ingestion, api_gateway)
"""
try:
# 获取租户ID(如果已登录)
tenant_id = principal.get("user_id") if principal else None
# 获取基础健康状态和告警
health_task = system_monitor.get_system_health()
alerts_task = system_monitor.get_alerts()
health, alerts = await asyncio.gather(health_task, alerts_task)
# 如果有租户ID,获取租户级别的数据
if tenant_id:
tenant_data = await system_monitor.get_tenant_dashboard(tenant_id)
return {
"timestamp": await _current_timestamp(),
"health": health,
# 租户级别的EU消耗(24小时)
"euConsumption24h": tenant_data.get("euConsumption24h", {}),
# 模型使用情况
"modelUsage": tenant_data.get("modelUsage", {}),
# 每周API调用统计(7天每天成功/失败)
"weeklyApiCalls": tenant_data.get("weeklyApiCalls", {}),
# 告警信息
"alerts": {
"items": alerts,
"count": len(alerts),
"critical_count": len([a for a in alerts if a.get("severity") == "critical"]),
"warning_count": len([a for a in alerts if a.get("severity") == "warning"]),
},
}
else:
# 未登录用户返回全局数据
metrics_task = system_monitor.get_system_metrics()
stats_task = system_monitor.get_service_stats("all")
metrics, stats = await asyncio.gather(metrics_task, stats_task)
return {
"timestamp": await _current_timestamp(),
"health": health,
"metrics": metrics,
"stats": stats.get("stats", {}),
"alerts": {
"items": alerts,
"count": len(alerts),
"critical_count": len([a for a in alerts if a.get("severity") == "critical"]),
"warning_count": len([a for a in alerts if a.get("severity") == "warning"]),
},
}
except Exception as exc:
logger.error("获取监控仪表板失败", error=str(exc))
raise HTTPException(status_code=500, detail=str(exc)) from exc
async def _current_timestamp() -> str:
"""Helper returning the current UTC timestamp string."""
from datetime import datetime
return datetime.utcnow().isoformat()