60 lines
1.9 KiB
Python
60 lines
1.9 KiB
Python
"""stats 路由:token 统计概览"""
|
||
|
||
from fastapi import APIRouter, Depends
|
||
|
||
from ..core.db import get_pool
|
||
from ..core.deps import current_admin
|
||
|
||
router = APIRouter(prefix="/api/stats", tags=["stats"])
|
||
|
||
|
||
@router.get("")
|
||
async def stats(admin: dict = Depends(current_admin)):
|
||
pool = await get_pool()
|
||
|
||
total = await pool.fetchval("SELECT COUNT(*) FROM mcp_token")
|
||
active = await pool.fetchval("SELECT COUNT(*) FROM mcp_token WHERE status = 'active'")
|
||
revoked = await pool.fetchval("SELECT COUNT(*) FROM mcp_token WHERE status = 'revoked'")
|
||
|
||
# 各 service_scope 活跃分布
|
||
scope_rows = await pool.fetch(
|
||
"SELECT service_scope, COUNT(*) AS cnt FROM mcp_token WHERE status = 'active' GROUP BY service_scope"
|
||
)
|
||
by_scope = {r["service_scope"]: r["cnt"] for r in scope_rows}
|
||
|
||
# 近 24h 调用次数(基于 last_used_at)
|
||
calls_24h = await pool.fetchval(
|
||
"SELECT COUNT(*) FROM mcp_token WHERE last_used_at > now() - interval '24 hours'"
|
||
)
|
||
|
||
# 近 24h 活跃客户端
|
||
clients_24h = await pool.fetchval(
|
||
"SELECT COUNT(DISTINCT client_id) FROM mcp_token WHERE last_used_at > now() - interval '24 hours'"
|
||
)
|
||
|
||
# 最近 10 条调用记录
|
||
recent_rows = await pool.fetch(
|
||
"""SELECT token_prefix, client_id, last_used_svc, last_used_at
|
||
FROM mcp_token WHERE last_used_at IS NOT NULL
|
||
ORDER BY last_used_at DESC LIMIT 10"""
|
||
)
|
||
recent = [
|
||
{
|
||
"token_prefix": r["token_prefix"],
|
||
"client_id": r["client_id"],
|
||
"service": r["last_used_svc"],
|
||
"last_used_at": r["last_used_at"].isoformat() if r["last_used_at"] else None,
|
||
}
|
||
for r in recent_rows
|
||
]
|
||
|
||
return {
|
||
"total": total,
|
||
"active": active,
|
||
"revoked": revoked,
|
||
"by_scope": by_scope,
|
||
"calls_24h": calls_24h,
|
||
"clients_24h": clients_24h,
|
||
"recent": recent,
|
||
}
|