nginx中配置log_format记录代理耗时细分,需利用$upstream_connect_time、$upstream_header_time、$upstream_response_time等变量计算各阶段延迟,并通过json格式日志输出,确保proxy_pass生效且access_log正确引用该format。

在 Nginx 中配置 log_format 记录代理转发的耗时细分指标,核心是利用内置变量捕获各阶段时间戳,再通过差值计算关键延迟项。重点不是“记录时间”,而是“拆解时间”——比如 upstream 建连、请求发送、响应接收、整个代理过程等。
需要关注的关键内置时间变量
Nginx 提供了多个以 $upstream_*_time 和 $request_time 为主的变量,它们在 proxy_pass 场景下自动生效(需启用 upstream 模块):
-
$request_time:从接收到客户端第一个字节,到返回最后一个字节给客户端的总耗时(单位:秒,精度毫秒) -
$upstream_connect_time:与 upstream 建立 TCP 连接所用时间(含 DNS 解析、TCP 握手、SSL 握手) -
$upstream_header_time:从发起 upstream 请求,到接收到 upstream 返回的第一个字节的时间(即后端处理 + 网络传输首包时间) -
$upstream_response_time:从发起 upstream 请求,到接收完全部响应体的时间(含 header + body 传输) -
$upstream_cache_status:可辅助判断是否命中缓存(影响耗时解读)
定义带耗时细分的 log_format
推荐使用 JSON 格式便于日志采集和分析(如接入 ELK 或 Loki),同时保留可读性:
log_format upstream_detail escape=json
'{'
'"time_local":"$time_local",'
'"remote_addr":"$remote_addr",'
'"request":"$request",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_connect_time":"$upstream_connect_time",'
'"upstream_header_time":"$upstream_header_time",'
'"upstream_response_time":"$upstream_response_time",'
'"upstream_addr":"$upstream_addr",'
'"upstream_cache_status":"$upstream_cache_status"'
'}';
说明:
- 所有时间变量默认输出为秒,带三位小数(如
"0.024"),无需额外格式化 -
escape=json防止 URL 或 header 中的双引号/换行破坏 JSON 结构 -
$upstream_addr显示实际转发到的后端地址(支持多实例负载均衡时识别节点) - 若某阶段未发生(如复用连接无建连),对应变量值为 “-”,JSON 中会输出
"-"字符串
确保变量生效的前提条件
这些 upstream 时间变量仅在使用 proxy_pass(或 fastcgi_pass / grpc_pass 等)且成功触发 upstream 调用时才被填充。常见失效原因:
- 未配置
proxy_pass,或配置错误导致 fallback 到本地处理(如 404 页面由 Nginx 自己生成) - 使用了
proxy_cache_bypass或proxy_no_cache但未配缓存,可能跳过 upstream 流程 - upstream 定义中启用了
keepalive,但未在 location 中显式开启长连接(需加proxy_http_version 1.1; proxy_set_header Connection "";) - 日志写入位置错误:必须在
location或server块中用access_log ... upstream_detail;启用该 format
进阶:计算更细粒度延迟(如网络传输耗时)
原生变量不直接提供“请求发送耗时”或“响应体传输耗时”,但可通过组合推算:
- 后端纯处理耗时 ≈
$upstream_header_time - $upstream_connect_time(前提是连接已复用,否则含建连) - 响应体网络传输耗时 ≈
$upstream_response_time - $upstream_header_time - 客户端侧网络耗时 ≈
$request_time - $upstream_response_time(Nginx 发送响应给 client 的时间)
注意:这些是近似值,受 TCP 拥塞控制、缓冲区、Nginx 缓存策略等影响,不可用于精确链路追踪,但对容量评估和瓶颈定位足够有效。











