mirror of
https://github.com/snailyp/gemini-balance.git
synced 2026-09-05 23:56:37 +08:00
fix(api): 统一错误日志时间戳并传递 request_datetime
- 统一 add_error_log 的 request_time:优先使用 request_datetime, 否则使用 datetime.now(),去除 timezone.utc,避免与请求日志时区不一致 - 在 Gemini/OpenAI/Vertex/Embedding 等服务的异常处理处补充传入 request_datetime,使错误日志与请求日志可一一对应 - stats: 移除失败记录的错误日志时间窗匹配与 error_log_id 附带,降低查询开销 与误关联风险;建议通过统一时间戳(key + request_time)或独立错误日志 查询接口完成关联 - 调整部分导入顺序与长行换行等代码风格,无功能改动 BREAKING CHANGE: 统计详情接口不再返回 error_log_id 字段。需要关联错误日志的 客户端请改为基于 key 与 request_time 在错误日志接口中检索。
This commit is contained in:
@@ -178,9 +178,6 @@ class StatsService:
|
||||
|
||||
results = await database.fetch_all(query)
|
||||
|
||||
# 为失败调用尝试查找匹配的错误日志ID(时间窗口 +/- 5 分钟)
|
||||
from app.database.models import ErrorLog # 延迟导入避免循环依赖
|
||||
|
||||
details: list[dict] = []
|
||||
for row in results:
|
||||
status = "failure"
|
||||
@@ -196,30 +193,6 @@ class StatsService:
|
||||
"latency_ms": row["latency_ms"],
|
||||
}
|
||||
|
||||
# 如果失败,尝试附带一个相关的错误日志ID,便于前端拉取详情
|
||||
if status == "failure" and row["key"]:
|
||||
try:
|
||||
ts = row["timestamp"]
|
||||
start_win = ts - datetime.timedelta(minutes=5)
|
||||
end_win = ts + datetime.timedelta(minutes=5)
|
||||
err_query = (
|
||||
select(ErrorLog.id)
|
||||
.where(
|
||||
ErrorLog.gemini_key == row["key"],
|
||||
ErrorLog.request_time >= start_win,
|
||||
ErrorLog.request_time <= end_win,
|
||||
)
|
||||
.order_by(ErrorLog.request_time.desc())
|
||||
.limit(1)
|
||||
)
|
||||
err = await database.fetch_one(err_query)
|
||||
if err:
|
||||
record["error_log_id"] = err["id"]
|
||||
except Exception as _e:
|
||||
logger.debug(
|
||||
f"No matching error log found for key ending ...{row['key'][-4:] if row['key'] else ''}: {_e}"
|
||||
)
|
||||
|
||||
details.append(record)
|
||||
|
||||
logger.info(
|
||||
@@ -260,8 +233,6 @@ class StatsService:
|
||||
|
||||
results = await database.fetch_all(query)
|
||||
|
||||
from app.database.models import ErrorLog
|
||||
|
||||
details: list[dict] = []
|
||||
for row in results:
|
||||
status = "failure"
|
||||
@@ -277,29 +248,6 @@ class StatsService:
|
||||
"latency_ms": row["latency_ms"],
|
||||
}
|
||||
|
||||
if status == "failure" and row["key"]:
|
||||
try:
|
||||
ts = row["timestamp"]
|
||||
start_win = ts - datetime.timedelta(minutes=5)
|
||||
end_win = ts + datetime.timedelta(minutes=5)
|
||||
err_query = (
|
||||
select(ErrorLog.id)
|
||||
.where(
|
||||
ErrorLog.gemini_key == row["key"],
|
||||
ErrorLog.request_time >= start_win,
|
||||
ErrorLog.request_time < end_win,
|
||||
)
|
||||
.order_by(ErrorLog.request_time.desc())
|
||||
.limit(1)
|
||||
)
|
||||
err = await database.fetch_one(err_query)
|
||||
if err:
|
||||
record["error_log_id"] = err["id"]
|
||||
except Exception as _e:
|
||||
logger.debug(
|
||||
f"No matching error log found for key ending ...{row['key'][-4:] if row['key'] else ''}: {_e}"
|
||||
)
|
||||
|
||||
details.append(record)
|
||||
|
||||
logger.info(
|
||||
@@ -312,7 +260,9 @@ class StatsService:
|
||||
)
|
||||
raise
|
||||
|
||||
async def get_attention_keys_last_24h(self, include_keys: set[str], limit: int = 20, status_code: int = 429) -> list[dict]:
|
||||
async def get_attention_keys_last_24h(
|
||||
self, include_keys: set[str], limit: int = 20, status_code: int = 429
|
||||
) -> list[dict]:
|
||||
"""返回最近24小时内指定状态码(默认429)最多的Key列表,仅包含include_keys中的Key。
|
||||
|
||||
Returns: [{"key": str, "count": int, "status_code": int}, ...] 按次数降序
|
||||
@@ -344,7 +294,9 @@ class StatsService:
|
||||
if row["key"]
|
||||
]
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get attention keys ({status_code}) in last 24h: {e}")
|
||||
logger.error(
|
||||
f"Failed to get attention keys ({status_code}) in last 24h: {e}"
|
||||
)
|
||||
return []
|
||||
|
||||
async def get_key_usage_details_last_24h(self, key: str) -> Union[dict, None]:
|
||||
|
||||
Reference in New Issue
Block a user