Fastapi中利用中间件实现日志记录

FastAPI 的「中间件」机制让你能够在 不改动现有路由函数 的前提下,为每一次请求/响应统一地写日志。下面给出一份可直接落地的最小示例。

日志中间件代码封装

logger_config.py文件内容如下:

import logging
import os
import time
import uuid
from logging.handlers import RotatingFileHandler

from fastapi import Request

# 日志目录路径
LOG_DIR = "logs"
# 确保日志目录存在,如果不存在则创建
os.makedirs(LOG_DIR, exist_ok=True)
# 日志格式:时间 - 名称 - 级别 - 消息
LOG_FORMAT = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"

# 创建FastAPI应用日志记录器
logger = logging.getLogger("fastapi_app")
# 设置日志记录级别为INFO
logger.setLevel(logging.INFO)

# 创建文件处理器,用于将日志写入文件
# 设置日志文件最大为10MB,保留5个备份文件
file_handler = RotatingFileHandler(
    os.path.join(LOG_DIR, "app.log"),
    maxBytes=10 * 1024 * 1024,
    backupCount=5,
    encoding="utf-8"
)
# 设置日志格式
file_handler.setFormatter(logging.Formatter(LOG_FORMAT))
# 将文件处理器添加到日志记录器
logger.addHandler(file_handler)


def make_logging_middleware():
    """
    创建日志中间件函数,用于记录请求和响应信息
    Returns:
        返回一个异步中间件函数
    """

    async def logging_middleware(request: Request, call_next):
        # 记录请求开始时间
        start = time.time()
        # 获取请求ID,如果不存在则生成一个UUID的前8位
        rid = request.headers.get("x-request-id") or str(uuid.uuid4())[:8]
        # 获取客户端真实IP,如果不存在则使用客户端主机地址
        real_ip = request.headers.get("x-real-ip") or request.client.host
        # 获取用户代理信息
        ua = request.headers.get("user-agent", "-")
        # 获取查询参数,如果没有则使用"-"
        query = str(request.query_params) if request.query_params else "-"

        # 记录请求信息:请求方法、路径、查询参数、客户端IP、用户代理和请求ID
        logger.info(f"→ {request.method} {request.url.path} - "
                    f"query:{query} - Client:{real_ip} - ua:{ua} - rid:{rid}")

        # 调用下一个中间件或路由处理函数
        response = await call_next(request)

        # 计算请求处理耗时(毫秒)
        duration = round((time.time() - start) * 1000, 2)
        # 记录响应信息:请求方法、路径、状态码、处理耗时和请求ID
        logger.info(f"← {request.method} {request.url.path} - "
                    f"Status:{response.status_code} - Duration:{duration}ms - rid:{rid}")

        # 返回响应
        return response

    return logging_middleware

使用方法

main.py中使用中间件,代码内容如下:

from fastapi import FastAPI
from logger_config import make_logging_middleware  # 引入中间件工厂

app = FastAPI()

# 注册日志中间件(零侵入业务路由)
app.middleware("http")(make_logging_middleware())

# -----------------------
# 以下为示例业务路由
# -----------------------
@app.get("/")
def read_root():
    return {"Hello": "World"}

运行示例

# 开发
uvicorn main:app --reload

# 生产
uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4
# 您可以在使用 fastapi 或 uvicorn 命令时,通过 --workers CLI 选项启用多个工作进程(workers),以充分利用多核 CPU,以并行运行多个进程。
posted @ 2025-07-15 14:30  莫颀  阅读(273)  评论(0)    收藏  举报