feat(api,ui): 新增按Key调用详情与错误日志查找并联动前端

引入按密钥维度的请求详情及错误日志关联,新增错误日志精确
查找接口,并扩展统计时间维度,提升故障定位与可观测性。

- 新增 /api/logs/errors/lookup 接口:支持按 gemini_key / timestamp /
  status_code 与时间窗口查找最接近的错误日志;ErrorLogDetailResponse
  增加 error_code 字段
- Stats 接口增强:get_api_call_details 返回 status_code、latency_ms,
  并在失败时尝试匹配 error_log_id;新增 /api/stats/key-details 获取指
  定密钥调用详情;新增 8h 时间段
- DB 层:add_error_log 支持传入 request_datetime(默认使用 UTC);新增
  find_error_log_by_info 封装按 key/时间窗口/状态码的查询
- 前端 keys_status:趋势图支持 8 小时区间;调用详情表新增状态码/耗时与
  失败详情按钮;可按 key 查看期内调用详情并查看匹配错误日志;优化统计
  摘要展示与模态层级(z-index)
- OpenAIChatService:错误记录携带请求时间;改进日志与健壮性处理
This commit is contained in:
snaily
2025-08-18 05:19:29 +08:00
parent 01312317a1
commit e9601ca76c
8 changed files with 607 additions and 133 deletions
+24
View File
@@ -230,3 +230,27 @@ def setup_api_stats_routes(app: FastAPI) -> None:
f"Error fetching API stats details for period {period}: {str(e)}"
)
return {"error": "Internal server error"}, 500
@app.get("/api/stats/key-details")
async def api_stats_key_details(request: Request, key: str, period: str):
"""获取指定密钥在指定时间段内的调用详情"""
try:
auth_token = request.cookies.get("auth_token")
if not auth_token or not verify_auth_token(auth_token):
logger.warning("Unauthorized access attempt to API key stats details")
return {"error": "Unauthorized"}, 401
logger.info(f"Fetching key call details for key=...{key[-4:] if key else ''}, period: {period}")
stats_service = StatsService()
details = await stats_service.get_key_call_details(key, period)
return details
except ValueError as e:
logger.warning(
f"Invalid period requested for key stats details: {period} - {str(e)}"
)
return {"error": str(e)}, 400
except Exception as e:
logger.error(
f"Error fetching key stats details for period {period}: {str(e)}"
)
return {"error": "Internal server error"}, 500