89 lines
2.7 KiB
Python
89 lines
2.7 KiB
Python
# 请求日志中间件 - 优化版
|
|
import time
|
|
import uuid
|
|
from fastapi import Request, Response
|
|
from app.core.logging_config import logger
|
|
|
|
|
|
async def logging_middleware(request: Request, call_next):
|
|
"""记录所有 API 请求的日志 - 优化版"""
|
|
|
|
# 生成请求 ID
|
|
request_id = str(uuid.uuid4())
|
|
start_time = time.time()
|
|
|
|
# 获取用户信息(如果已登录)
|
|
user_id = None
|
|
try:
|
|
auth_header = request.headers.get('Authorization', '')
|
|
if auth_header.startswith('Bearer '):
|
|
user_id = "authenticated"
|
|
except Exception as e:
|
|
# 静默失败,不影响主流程
|
|
pass
|
|
|
|
# 执行请求
|
|
response_status = 500
|
|
try:
|
|
response = await call_next(request)
|
|
response_status = response.status_code
|
|
except Exception as e:
|
|
duration = (time.time() - start_time) * 1000
|
|
try:
|
|
logger.error(
|
|
f"API 请求异常:{request.method} {request.url.path}",
|
|
extra={
|
|
'request_id': request_id,
|
|
'user_id': user_id,
|
|
'ip_address': request.client.host if request.client else None,
|
|
'duration_ms': duration,
|
|
'data': {
|
|
'method': request.method,
|
|
'path': request.url.path,
|
|
'query': str(request.query_params),
|
|
'error': str(e)
|
|
}
|
|
},
|
|
exc_info=True
|
|
)
|
|
except:
|
|
pass # 日志记录失败不影响主流程
|
|
raise
|
|
|
|
# 记录响应
|
|
duration = (time.time() - start_time) * 1000
|
|
|
|
try:
|
|
log_level = 'INFO'
|
|
if response_status >= 500:
|
|
log_level = 'ERROR'
|
|
elif response_status >= 400:
|
|
log_level = 'WARNING'
|
|
|
|
getattr(logger, log_level)(
|
|
f"API 请求完成:{request.method} {request.url.path}",
|
|
extra={
|
|
'request_id': request_id,
|
|
'user_id': user_id,
|
|
'ip_address': request.client.host if request.client else None,
|
|
'duration_ms': duration,
|
|
'data': {
|
|
'method': request.method,
|
|
'path': request.url.path,
|
|
'query': str(request.query_params),
|
|
'status_code': response_status
|
|
}
|
|
}
|
|
)
|
|
except Exception as e:
|
|
# 日志记录失败不影响主流程
|
|
pass
|
|
|
|
# 在响应头中添加请求 ID
|
|
try:
|
|
response.headers['X-Request-ID'] = request_id
|
|
except:
|
|
pass
|
|
|
|
return response
|