监控和日志记录
为了更好地监控应用程序的性能并及时排查问题,蝙蝠侠希望拥有一份规范的访问日志——每个请求一行,记录请求方法、路径、状态码以及耗时。
Robyn 构建在 Python 标准的 logging 模块之上,因此你可以用两个中间件来组装请求/访问日志:一个 before_request 钩子用于启动计时器,一个 after_request 钩子在响应就绪后输出日志行。after_request 钩子可以同时接收 request 和 response,这正是你同时记录路径与状态码所需要的。而且由于 Robyn 在 before_request、处理器和 after_request 钩子之间共享 contextvars 上下文,使用 ContextVar 来存放开始时间会非常整洁。
请求 / 访问日志
import logging
import time
from contextvars import ContextVar
from robyn import Request, Response
# 专用于访问日志的 logger。它会继承 Robyn 的日志配置,
# 因此请将级别保持在 INFO 或更低(使用 `--log-level WARN` 运行会隐藏这些日志)。
logging.basicConfig(level=logging.INFO)
access_logger = logging.getLogger("robyn.access")
_request_start: ContextVar[float] = ContextVar("request_start")
@app.before_request()
def start_timer(request: Request):
_request_start.set(time.perf_counter())
return request
@app.after_request()
def log_request(request: Request, response: Response):
start = _request_start.get(None)
duration_ms = (time.perf_counter() - start) * 1000 if start is not None else 0.0
access_logger.info(
"%s %s -> %s (%.2fms)",
request.method,
request.url.path,
response.status_code,
duration_ms,
)
return response
将这两个钩子注册为全局钩子后,每个请求都会产生如下一行日志:
INFO:robyn.access:GET /crimes -> 200 (1.83ms)
几点值得注意:
- 双参数的
after_request(request, response)签名让你能在拿到响应的同时访问请求。如果你只需要响应,单参数的after_request(response)同样可用——Robyn 会根据你的函数参数自动选择调用方式。 - 即使某个
before_request钩子提前返回了响应,after_request钩子也始终会运行,因此你的访问日志能覆盖每一个响应。 - 优先使用
%s风格的日志参数(如上所示),而不是 f-string,这样只有在日志级别真正启用时才会进行字符串格式化。
借助监控和日志记录功能,蝙蝠侠现在能够轻松检测应用程序中的问题,分析其性能表现,确保系统始终保持最佳状态,随时准备协助他打击犯罪。
