yym68686 commited on
Commit
b197d5b
·
1 Parent(s): d4b22a2

✨ Feature: Add feature: The /stats endpoint supports passing an 'hours' parameter to specify the number of hours of historical statistics data to return

Browse files
Files changed (1) hide show
  1. main.py +29 -11
main.py CHANGED
@@ -902,12 +902,20 @@ def generate_api_key():
902
  return JSONResponse(content={"api_key": api_key})
903
 
904
  # 在 /stats 路由中返回成功和失败百分比
905
- from collections import defaultdict
906
  from sqlalchemy import func, desc, case
 
907
 
908
  @app.get("/stats", dependencies=[Depends(rate_limit_dependency)])
909
- async def get_stats(request: Request, token: str = Depends(verify_admin_api_key)):
 
 
 
 
910
  async with async_session() as session:
 
 
 
911
  # 1. 每个渠道下面每个模型的成功率
912
  channel_model_stats = await session.execute(
913
  select(
@@ -915,7 +923,9 @@ async def get_stats(request: Request, token: str = Depends(verify_admin_api_key)
915
  ChannelStat.model,
916
  func.count().label('total'),
917
  func.sum(case((ChannelStat.success == True, 1), else_=0)).label('success_count')
918
- ).group_by(ChannelStat.provider, ChannelStat.model)
 
 
919
  )
920
  channel_model_stats = channel_model_stats.fetchall()
921
 
@@ -925,14 +935,17 @@ async def get_stats(request: Request, token: str = Depends(verify_admin_api_key)
925
  ChannelStat.provider,
926
  func.count().label('total'),
927
  func.sum(case((ChannelStat.success == True, 1), else_=0)).label('success_count')
928
- ).group_by(ChannelStat.provider)
 
 
929
  )
930
  channel_stats = channel_stats.fetchall()
931
 
932
  # 3. 每个模型在所有渠道总的请求次数
933
  model_stats = await session.execute(
934
- select(ChannelStat.model, func.count().label('count'))
935
- .group_by(ChannelStat.model)
 
936
  .order_by(desc('count'))
937
  )
938
  model_stats = model_stats.fetchall()
@@ -940,6 +953,7 @@ async def get_stats(request: Request, token: str = Depends(verify_admin_api_key)
940
  # 4. 每个端点的请求次数
941
  endpoint_stats = await session.execute(
942
  select(RequestStat.endpoint, func.count().label('count'))
 
943
  .group_by(RequestStat.endpoint)
944
  .order_by(desc('count'))
945
  )
@@ -947,25 +961,29 @@ async def get_stats(request: Request, token: str = Depends(verify_admin_api_key)
947
 
948
  # 5. 每个ip请求的次数
949
  ip_stats = await session.execute(
950
- select(RequestStat.ip, func.count().label('count'))
951
- .group_by(RequestStat.ip)
 
952
  .order_by(desc('count'))
953
  )
954
  ip_stats = ip_stats.fetchall()
955
 
956
  # 处理统计数据并返回
957
  stats = {
 
958
  "channel_model_success_rates": [
959
  {
960
  "provider": stat.provider,
961
  "model": stat.model,
962
- "success_rate": stat.success_count / stat.total if stat.total > 0 else 0
 
963
  } for stat in sorted(channel_model_stats, key=lambda x: x.success_count / x.total if x.total > 0 else 0, reverse=True)
964
  ],
965
  "channel_success_rates": [
966
  {
967
  "provider": stat.provider,
968
- "success_rate": stat.success_count / stat.total if stat.total > 0 else 0
 
969
  } for stat in sorted(channel_stats, key=lambda x: x.success_count / x.total if x.total > 0 else 0, reverse=True)
970
  ],
971
  "model_request_counts": [
@@ -982,7 +1000,7 @@ async def get_stats(request: Request, token: str = Depends(verify_admin_api_key)
982
  ],
983
  "ip_request_counts": [
984
  {
985
- "ip": stat.ip,
986
  "count": stat.count
987
  } for stat in ip_stats
988
  ]
 
902
  return JSONResponse(content={"api_key": api_key})
903
 
904
  # 在 /stats 路由中返回成功和失败百分比
905
+ from datetime import datetime, timedelta, timezone
906
  from sqlalchemy import func, desc, case
907
+ from fastapi import Query
908
 
909
  @app.get("/stats", dependencies=[Depends(rate_limit_dependency)])
910
+ async def get_stats(
911
+ request: Request,
912
+ token: str = Depends(verify_admin_api_key),
913
+ hours: int = Query(default=24, ge=1, le=720, description="Number of hours to look back for stats (1-720)")
914
+ ):
915
  async with async_session() as session:
916
+ # 计算指定时间范围的开始时间
917
+ start_time = datetime.now(timezone.utc) - timedelta(hours=hours)
918
+
919
  # 1. 每个渠道下面每个模型的成功率
920
  channel_model_stats = await session.execute(
921
  select(
 
923
  ChannelStat.model,
924
  func.count().label('total'),
925
  func.sum(case((ChannelStat.success == True, 1), else_=0)).label('success_count')
926
+ )
927
+ .where(ChannelStat.timestamp >= start_time)
928
+ .group_by(ChannelStat.provider, ChannelStat.model)
929
  )
930
  channel_model_stats = channel_model_stats.fetchall()
931
 
 
935
  ChannelStat.provider,
936
  func.count().label('total'),
937
  func.sum(case((ChannelStat.success == True, 1), else_=0)).label('success_count')
938
+ )
939
+ .where(ChannelStat.timestamp >= start_time)
940
+ .group_by(ChannelStat.provider)
941
  )
942
  channel_stats = channel_stats.fetchall()
943
 
944
  # 3. 每个模型在所有渠道总的请求次数
945
  model_stats = await session.execute(
946
+ select(RequestStat.model, func.count().label('count'))
947
+ .where(RequestStat.timestamp >= start_time)
948
+ .group_by(RequestStat.model)
949
  .order_by(desc('count'))
950
  )
951
  model_stats = model_stats.fetchall()
 
953
  # 4. 每个端点的请求次数
954
  endpoint_stats = await session.execute(
955
  select(RequestStat.endpoint, func.count().label('count'))
956
+ .where(RequestStat.timestamp >= start_time)
957
  .group_by(RequestStat.endpoint)
958
  .order_by(desc('count'))
959
  )
 
961
 
962
  # 5. 每个ip请求的次数
963
  ip_stats = await session.execute(
964
+ select(RequestStat.client_ip, func.count().label('count'))
965
+ .where(RequestStat.timestamp >= start_time)
966
+ .group_by(RequestStat.client_ip)
967
  .order_by(desc('count'))
968
  )
969
  ip_stats = ip_stats.fetchall()
970
 
971
  # 处理统计数据并返回
972
  stats = {
973
+ "time_range": f"Last {hours} hours",
974
  "channel_model_success_rates": [
975
  {
976
  "provider": stat.provider,
977
  "model": stat.model,
978
+ "success_rate": stat.success_count / stat.total if stat.total > 0 else 0,
979
+ "total_requests": stat.total
980
  } for stat in sorted(channel_model_stats, key=lambda x: x.success_count / x.total if x.total > 0 else 0, reverse=True)
981
  ],
982
  "channel_success_rates": [
983
  {
984
  "provider": stat.provider,
985
+ "success_rate": stat.success_count / stat.total if stat.total > 0 else 0,
986
+ "total_requests": stat.total
987
  } for stat in sorted(channel_stats, key=lambda x: x.success_count / x.total if x.total > 0 else 0, reverse=True)
988
  ],
989
  "model_request_counts": [
 
1000
  ],
1001
  "ip_request_counts": [
1002
  {
1003
+ "ip": stat.client_ip,
1004
  "count": stat.count
1005
  } for stat in ip_stats
1006
  ]