完善后端日志
This commit is contained in:
@@ -2,23 +2,102 @@
|
||||
FastAPI 应用主入口
|
||||
"""
|
||||
import logging
|
||||
import sys
|
||||
import uuid
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Callable
|
||||
from functools import wraps
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi import FastAPI, Request, Response
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from starlette.middleware.base import BaseHTTPMiddleware
|
||||
|
||||
from app.config import settings
|
||||
from app.api import api_router
|
||||
from app.core.database import mysql_db, mongodb, redis_db
|
||||
|
||||
# 配置日志
|
||||
logging.basicConfig(
|
||||
level=logging.INFO if settings.DEBUG else logging.WARNING,
|
||||
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
||||
)
|
||||
# ==================== 日志配置 ====================
|
||||
|
||||
def setup_logging():
|
||||
"""配置应用日志系统"""
|
||||
# 根日志配置
|
||||
log_level = logging.DEBUG if settings.DEBUG else logging.INFO
|
||||
|
||||
# 控制台处理器
|
||||
console_handler = logging.StreamHandler(sys.stdout)
|
||||
console_handler.setLevel(log_level)
|
||||
console_formatter = logging.Formatter(
|
||||
fmt="%(asctime)s | %(levelname)-8s | %(name)s:%(lineno)d | %(message)s",
|
||||
datefmt="%Y-%m-%d %H:%M:%S"
|
||||
)
|
||||
console_handler.setFormatter(console_formatter)
|
||||
|
||||
# 根日志器
|
||||
root_logger = logging.getLogger()
|
||||
root_logger.setLevel(log_level)
|
||||
root_logger.handlers = []
|
||||
root_logger.addHandler(console_handler)
|
||||
|
||||
# 第三方库日志级别
|
||||
for lib in ["uvicorn", "uvicorn.access", "fastapi", "httpx", "sqlalchemy"]:
|
||||
logging.getLogger(lib).setLevel(logging.WARNING)
|
||||
|
||||
return root_logger
|
||||
|
||||
# 初始化日志
|
||||
setup_logging()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# ==================== 请求日志中间件 ====================
|
||||
|
||||
class RequestLoggingMiddleware(BaseHTTPMiddleware):
|
||||
"""请求日志中间件 - 记录每个请求的详细信息"""
|
||||
|
||||
async def dispatch(self, request: Request, call_next: Callable) -> Response:
|
||||
# 生成请求ID
|
||||
request_id = str(uuid.uuid4())[:8]
|
||||
request.state.request_id = request_id
|
||||
|
||||
# 记录请求
|
||||
logger.info(f"→ [{request_id}] {request.method} {request.url.path}")
|
||||
|
||||
try:
|
||||
response = await call_next(request)
|
||||
|
||||
# 记录响应
|
||||
logger.info(
|
||||
f"← [{request_id}] {request.method} {request.url.path} "
|
||||
f"| 状态: {response.status_code} | 耗时: N/A"
|
||||
)
|
||||
|
||||
# 添加请求ID到响应头
|
||||
response.headers["X-Request-ID"] = request_id
|
||||
return response
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"✗ [{request_id}] {request.method} {request.url.path} | 异常: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
# ==================== 请求追踪装饰器 ====================
|
||||
|
||||
def log_async_function(func: Callable) -> Callable:
|
||||
"""异步函数日志装饰器"""
|
||||
@wraps(func)
|
||||
async def wrapper(*args, **kwargs):
|
||||
func_name = func.__name__
|
||||
logger.debug(f"→ {func_name} 开始执行")
|
||||
try:
|
||||
result = await func(*args, **kwargs)
|
||||
logger.debug(f"← {func_name} 执行完成")
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"✗ {func_name} 执行失败: {str(e)}")
|
||||
raise
|
||||
return wrapper
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""
|
||||
@@ -83,6 +162,9 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# 添加请求日志中间件
|
||||
app.add_middleware(RequestLoggingMiddleware)
|
||||
|
||||
# 注册 API 路由
|
||||
app.include_router(api_router, prefix=settings.API_V1_STR)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user