feat: Add global exception handling

This commit is contained in:
shiyu
2025-08-25 19:08:30 +08:00
parent 3d0bdd6557
commit dbd87a7c37
3 changed files with 30 additions and 3 deletions

View File

@@ -0,0 +1,25 @@
from fastapi import Request, status
from fastapi.responses import JSONResponse
from services.logging import LogService
import traceback
async def global_exception_handler(request: Request, exc: Exception):
"""
全局异常处理
"""
error_details = {
"method": request.method,
"url": str(request.url),
"headers": dict(request.headers),
"exception": str(exc),
"traceback": traceback.format_exc(),
}
await LogService.error(
source="global_exception_handler",
message=f"Unhandled exception: {exc}",
details=error_details
)
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content={"error": "Internal Server Error", "detail": str(exc)},
)

View File

@@ -0,0 +1,46 @@
import time
from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from services.logging import LogService
from models.database import UserAccount
import jwt
from jwt.exceptions import InvalidTokenError
from services.auth import ALGORITHM
from services.config import ConfigCenter
class LoggingMiddleware(BaseHTTPMiddleware):
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
start_time = time.time()
user_id = None
if "authorization" in request.headers:
token_str = request.headers.get("authorization")
try:
if token_str and token_str.startswith("Bearer "):
token = token_str.split(" ")[1]
payload = jwt.decode(token, ConfigCenter.get_secret_key("SECRET_KEY"), algorithms=[ALGORITHM])
username = payload.get("sub")
if username:
user_account = await UserAccount.get_or_none(username=username)
if user_account:
user_id = user_account.id
except (InvalidTokenError, Exception):
pass
response = await call_next(request)
process_time = (time.time() - start_time) * 1000
details = {
"client_ip": request.client.host,
"method": request.method,
"path": request.url.path,
"headers": dict(request.headers),
"status_code": response.status_code,
"process_time_ms": round(process_time, 2)
}
message = f"{request.method} {request.url.path} - {response.status_code}"
await LogService.api(message, details, user_id)
return response