feat(error_handling): 增强 API 错误处理和日志记录

- 扩展 ErrorLog 数据模型,增加 model_name, error_type, error_code 字段,以记录更详细的错误信息。
- 在 GeminiChatService 和 OpenAIChatService 中添加了 try-except 块,用于捕获 API 调用(包括普通和流式调用)时发生的异常。
- 实现从异常消息中通过正则表达式提取 HTTP 状态码的功能。
- 调用 add_error_log 服务将详细的错误信息(包括模型、错误类型、代码、请求体)持久化到数据库。
- 更新了 error_logs 前端页面,增加显示模型名称列及详情。
- 优化数据库连接池配置 (pool_recycle=3600),提高连接稳定性。
This commit is contained in:
snaily
2025-04-10 15:40:02 +08:00
parent 0f28173b0e
commit d94d24f96c
7 changed files with 103 additions and 10 deletions
+40 -3
View File
@@ -1,6 +1,7 @@
# app/services/chat_service.py
import json
import re
from typing import Any, AsyncGenerator, Dict, List
from app.config.config import settings
@@ -10,6 +11,7 @@ from app.handler.stream_optimizer import gemini_optimizer
from app.log.logger import get_gemini_logger
from app.service.client.api_client import GeminiApiClient
from app.service.key.key_manager import KeyManager
from app.database.services import add_error_log
logger = get_gemini_logger()
@@ -145,8 +147,27 @@ class GeminiChatService:
) -> Dict[str, Any]:
"""生成内容"""
payload = _build_payload(model, request)
response = await self.api_client.generate_content(payload, model, api_key)
return self.response_handler.handle_response(response, model, stream=False)
try:
response = await self.api_client.generate_content(payload, model, api_key)
return self.response_handler.handle_response(response, model, stream=False)
except Exception as e:
logger.error(f"Normal API call failed with error: {str(e)}")
error_code = None
error_log_msg = str(e)
# 尝试从异常消息中解析状态码
match = re.search(r"status code (\d+)", error_log_msg)
if match:
error_code = int(match.group(1))
await add_error_log(
gemini_key=api_key,
model_name=model,
error_type="gemini_chat_service",
error_log=error_log_msg,
error_code=error_code,
request_msg=payload
)
raise e # 重新抛出异常,以便上层处理
async def stream_generate_content(
self, model: str, request: GeminiRequest, api_key: str
@@ -185,9 +206,25 @@ class GeminiChatService:
break
except Exception as e:
retries += 1
error_log_msg = str(e)
logger.warning(
f"Streaming API call failed with error: {str(e)}. Attempt {retries} of {max_retries}"
f"Streaming API call failed with error: {error_log_msg}. Attempt {retries} of {max_retries}"
)
# 解析错误信息并记录到数据库
error_code = None
match = re.search(r"status code (\d+)", error_log_msg)
if match:
error_code = int(match.group(1))
await add_error_log(
gemini_key=api_key,
model_name=model,
error_log=error_log_msg,
error_code=error_code,
request_msg=payload
)
# 尝试切换 API Key
api_key = await self.key_manager.handle_api_failure(api_key)
logger.info(f"Switched to new API key: {api_key}")
if retries >= max_retries:
+42 -5
View File
@@ -1,6 +1,7 @@
# app/services/chat_service.py
import json
import re
from copy import deepcopy
from typing import Any, AsyncGenerator, Dict, List, Optional, Union
@@ -13,6 +14,7 @@ from app.log.logger import get_openai_logger
from app.service.client.api_client import GeminiApiClient
from app.service.image.image_create_service import ImageCreateService
from app.service.key.key_manager import KeyManager
from app.database.services import add_error_log
logger = get_openai_logger()
@@ -189,10 +191,28 @@ class OpenAIChatService:
self, model: str, payload: Dict[str, Any], api_key: str
) -> Dict[str, Any]:
"""处理普通聊天完成"""
response = await self.api_client.generate_content(payload, model, api_key)
return self.response_handler.handle_response(
response, model, stream=False, finish_reason="stop"
)
try:
response = await self.api_client.generate_content(payload, model, api_key)
return self.response_handler.handle_response(
response, model, stream=False, finish_reason="stop"
)
except Exception as e:
logger.error(f"Normal API call failed with error: {str(e)}")
error_code = None
error_log_msg = str(e)
# 尝试从异常消息中解析状态码
match = re.search(r"status code (\d+)", error_log_msg)
if match:
error_code = int(match.group(1))
await add_error_log(
gemini_key=api_key,
model_name=model,
error_log=error_log_msg,
error_code=error_code,
request_msg=payload
)
raise e # 重新抛出异常,以便上层处理
async def _handle_stream_completion(
self, model: str, payload: Dict[str, Any], api_key: str
@@ -241,9 +261,26 @@ class OpenAIChatService:
break # 成功后退出循环
except Exception as e:
retries += 1
error_log_msg = str(e)
logger.warning(
f"Streaming API call failed with error: {str(e)}. Attempt {retries} of {max_retries}"
f"Streaming API call failed with error: {error_log_msg}. Attempt {retries} of {max_retries}"
)
# 解析错误信息并记录到数据库
error_code = None
match = re.search(r"status code (\d+)", error_log_msg)
if match:
error_code = int(match.group(1))
print(model)
await add_error_log(
gemini_key=api_key,
model_name=model,
error_type="openai_chat_service",
error_log=error_log_msg,
error_code=error_code,
request_msg=payload
)
# 尝试切换 API Key
api_key = await self.key_manager.handle_api_failure(api_key)
logger.info(f"Switched to new API key: {api_key}")
if retries >= max_retries: