nginx 通过 $request_time 变量可精确记录请求全链路处理耗时(毫秒级),需在 log_format 中显式定义(如 timed 格式)并配合 access_log 使用;结合 $upstream_connect_time、$upstream_header_time 和 $upstream_response_time 可定位性能瓶颈;补充 $status、$upstream_status、$http_x_request_id 和 $msec 等字段可支撑 slo 监控与链路追踪。

要在 Nginx 日志中准确记录请求从接收到发送完毕的全链路总耗时,并支持毫秒级监控,核心是正确启用并组合使用 $request_time 及其关联变量。它不是“端到端用户体验延迟”,而是 Nginx 自身处理流程的真实耗时,精度已达毫秒(如 0.042 表示 42ms),无需额外模块或 Lua 脚本。
确保 $request_time 正确写入日志格式
在 nginx.conf 的 http 块内定义或修改 log_format,显式包含 $request_time,且不加引号、不包裹空格:
- 推荐写法(清晰、兼容性强):
log_format timed '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time'; - 注意不能复用
combined等内置名称覆盖,必须另起格式名(如timed); -
$request_time仅在log_format中可用,不可用于if判断或重写规则。
绑定格式并使配置生效
在 http 或具体 server 块中,将 access_log 指向你定义的格式名:
- 例如:
access_log /var/log/nginx/access.log timed;(Linux)或access_log logs/access.log timed;(Windows); - 保存后务必执行:
nginx -t校验语法 →nginx -s reload(Linux/macOS)或重启服务(Windows); - 发起一次请求后检查日志末尾是否出现类似
0.037的数值——这就是本次请求在 Nginx 内部的完整耗时(秒,三位小数即毫秒级)。
结合 upstream 时间字段做瓶颈归因
单看 $request_time 只能知道“总共花了多久”,无法判断慢在哪。必须搭配以下三个 upstream 时间变量并列记录:
-
$upstream_connect_time:Nginx 与后端建立 TCP 连接(含 TLS 握手)耗时; -
$upstream_header_time:从连接完成到收到响应首行的时间(含请求发出 + 后端处理 + header 返回); -
$upstream_response_time:从连接完成到收完全部响应体的时间(即后端完整响应耗时)。
通过差值快速定位问题层:
— 若 $request_time − $upstream_response_time > 0.2,说明延迟集中在 Nginx 本机(如 rewrite 复杂、SSL 开销大、日志写入慢);
— 若 $upstream_header_time − $upstream_connect_time 显著偏高,关注后端逻辑或 Nginx 代理参数(如 proxy_buffering);
— 若 $upstream_response_time 为空(显示为 -),需检查 proxy_pass 是否命中、后端是否可达、超时设置是否合理。
补充关键业务字段提升可观测性
为支撑 SLO 计算与链路追踪,建议在日志中一并记录:
-
$status和$upstream_status:区分是网关层错误(如 502/504)还是后端返回错误; -
$http_x_request_id或自定义$api_name(用map指令提取路径):实现按接口维度聚合分析; -
$msec:提供精确到毫秒的时间戳,便于与上下游日志对齐。
这些字段与 $request_time 共同构成可落地的轻量级监控基础,无需侵入应用代码,即可支撑 P95/P99 延迟统计、错误率告警等 SLO 场景。











