本文介绍如何在 fastapi 中结合 loguru,通过 `contextualize` 机制为每次 http 请求动态注入 url 等上下文信息,并自动体现在日志格式中,无需修改每条日志语句即可实现请求级精细化追踪。
在 FastAPI 应用中集成 Loguru 进行请求级日志监控时,一个常见且关键的需求是:让每条日志自动携带当前请求的 URL、请求 ID 或其他上下文信息,而无需在每个 logger.debug() 调用中手动拼接。直接修改全局 format 字符串不可行(因为它是静态配置),但 Loguru 提供了更优雅、线程安全的解决方案——contextualize()。
Loguru 允许在日志格式中引用 {extra[key]} 占位符,并通过 logger.contextualize() 为当前执行上下文(包括异步任务)临时注入键值对。该上下文会自动透传至该作用域内所有日志记录,且天然支持 asyncio 任务隔离(即不同请求的日志不会互相污染)。
from loguru import logger
import sys
LOG_LEVEL = "DEBUG"
# 移除默认 handler,重置配置
logger.remove()
log_format = (
"{time:YYYY-MM-DD HH:mm:ss.SSS zz} | "
"{extra[request_url]} | " # ← 动态插入请求路径
"{level: <8} | "
"Line {line: >4} ({file}): {message}"
)
# 设置默认 extra 值(必须!否则未 contextualize 时会报 KeyError)
logger.configure(extra={"request_url": "N/A"})
# 添加控制台与文件 handler,均使用同一 format
logger.add(sys.stdout, level=LOG_LEVEL, format=log_format, colorize=True, backtrace=True, diagnose=True)
logger.add("app.log", rotation="2 MB", level=LOG_LEVEL, format=log_format, colorize=False, backtrace=True, diagnose=True)
from fastapi import FastAPI, Request, Response
app = FastAPI()
@app.middleware("http")
async def log_request_context(request: Request, call_next):
# 提取路径(或 request.url 含协议/域名,按需选择)
url_path = str(request.url.path)
with logger.contextualize(request_url=url_path):
logger.debug(f"Request started: {request.method} {url_path}")
try:
response = await call_next(request)
logger.debug(f"Request completed with status {response.status_code}")
return response
except Exception as e:
logger.exception("Unhandled exception during request")
raise@app.get("/users/{user_id}")
def get_user(user_id: int):
logger.info(f"Fetching user {user_id}") # ← 自动带上 request_url 前缀
return {"id": user_id, "name": "Alice"}✅ 示例日志输出:
2025-06-15 14:22:31.892 CST | /users/123 | DEBUG | Line 123 (main.py): Request started: GET /users/123 2025-06-15 14:22:31.895 CST | /users/123 | INFO | Line 128 (main.py): Fetching user 123 2025-06-15 14:22:31.897 CST | /users/123 | DEBUG | Line 125 (main.py): Request completed with status 200
通过该方案,你无需侵入业务代码即可实现请求维度的结构化日志追踪,大幅提升分布式环境下的问题定位效率。