如何在FastAPI中间件中为Loguru动态更新每个请求的日志格式
在FastAPI中间件中用Loguru动态注入请求URL到日志格式的实现方案
你的需求完全可以实现,下面提供两种简洁高效的实现方式:
方法一:使用Loguru的绑定(bind)功能
Loguru支持通过bind()方法创建携带额外上下文信息的日志器实例,后续调用该实例的日志方法时,格式字符串可通过{extra[key]}引用绑定的信息。
修改你的代码如下:
import sys from fastapi import FastAPI, Request from loguru import logger LOG_LEVEL = 'DEBUG' # 调整日志格式,加入请求URL的占位符 log_format = "<green>{time:YYYY-MM-DD HH:mm:ss.SSS zz}</green> | <level>{level: <8}</level> | <cyan>{extra[url]}</cyan> | <yellow>Line {line: >4} ({file}):</yellow> <b>{message}</b>" logger.remove(0) logger.add(sys.stdout, level=LOG_LEVEL, format=log_format, colorize=True, backtrace=True, diagnose=True) logger.add('log.log', rotation='2 MB', level=LOG_LEVEL, format=log_format, colorize=False, backtrace=True, diagnose=True) app = FastAPI() @app.middleware("http") async def process_middleware(request: Request, call_next): # 绑定当前请求的URL到日志器(转成字符串避免对象序列化问题) bound_logger = logger.bind(url=str(request.url)) # 记录请求信息,此时日志会自动包含URL bound_logger.debug(f"收到请求,请求方法: {request.method}") response = await call_next(request) # 响应阶段的日志同样会携带URL bound_logger.debug(f"返回响应,状态码: {response.status_code}") return response
方法二:使用上下文管理器(contextualize)
如果希望中间件内所有日志都自动携带请求URL,用contextualize()上下文管理器更简洁,无需每次创建绑定日志器:
# 日志格式和初始化部分与方法一完全一致 @app.middleware("http") async def process_middleware(request: Request, call_next): # 进入上下文后,该块内的所有日志调用都会自动带上url参数 with logger.contextualize(url=str(request.url)): logger.debug(f"收到请求,请求方法: {request.method}") response = await call_next(request) logger.debug(f"返回响应,状态码: {response.status_code}") return response
关键注意事项
- 不要直接调用
logger.debug(request),Request对象的默认字符串表示包含大量冗余信息,建议提取method、client等关键字段记录。 - 如果需要扩展更多请求上下文(如客户端IP、请求头),可在绑定/上下文化时添加参数,比如
bind(url=str(request.url), client=request.client.host),然后在日志格式中加入{extra[client]}即可。 - 日志格式中的
{extra[key]}必须和绑定的key完全对应,否则会显示为空值。
内容的提问来源于stack exchange,提问作者NFeruch - FreePalestine
相关产品推荐
相关产品推荐

