57 lines
1.8 KiB
Python
57 lines
1.8 KiB
Python
import time
|
|
|
|
from fastapi import Request, HTTPException, status
|
|
from fastapi.responses import JSONResponse
|
|
from config.logging import logger
|
|
|
|
|
|
# 自定义异常类
|
|
class AppException(Exception):
|
|
def __init__(self, message: str, details=None):
|
|
self.message = message
|
|
self.details = details
|
|
|
|
|
|
# 全局异常处理中间件
|
|
async def global_exception_handler(request: Request, call_next):
|
|
try:
|
|
start_time = time.time()
|
|
|
|
# 请求摘要
|
|
logger.info(
|
|
f"<AuditSummary> {request.method} {request.url.path}"
|
|
)
|
|
|
|
response = await call_next(request)
|
|
|
|
# 耗时
|
|
time_taken = int((time.time() - start_time) * 1000)
|
|
logger.info(
|
|
f"<AuditSummary> Request URL {request.url.path} | Time Taken {time_taken} ms"
|
|
)
|
|
|
|
if response.status_code >= 400:
|
|
logger.warning(f"<AuditError> status={response.status_code}")
|
|
|
|
return response
|
|
|
|
except AppException as e:
|
|
# 记录业务异常
|
|
logger.error(f"<AuditError> {e.message} | details={e.details}")
|
|
return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST,
|
|
content={"message": e.message, "details": e.details})
|
|
|
|
except Exception as e:
|
|
# 记录未知异常(带堆栈信息)
|
|
logger.critical(f"<AuditError> {str(e)}", exc_info=True)
|
|
return JSONResponse(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
content={"code": 500, "message": "服务器内部错误", "details": str(e)})
|
|
|
|
|
|
def get_credentials_exception() -> HTTPException:
|
|
return HTTPException(
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
detail="Could not validate credentials",
|
|
headers={"WWW-Authenticate": "Bearer"},
|
|
)
|