Nginx 通过 $request_length 变量精确记录完整请求报文大小(含请求行、Headers 和 Body),需在 log_format 中显式输出并经日志解析/Exporter 转换为 Prometheus 可采集的直方图指标,推荐结合 vts 模块或 textfile_collector 实现分布统计。

Nginx 本身不直接暴露“请求报文头大小”或“完整请求报文大小”的原生指标,但可通过组合日志变量 + 后处理方式,间接统计请求报文(含请求行、所有 Header 和 Body)的大小分布。Prometheus 并不直接采集这类原始日志字段,需借助日志解析 + Exporter 或自定义指标暴露逻辑来实现。核心思路是:用 $request_length 作为请求报文总大小代理,再通过日志管道加工后交由 Prometheus 监控系统消费。
请求报文大小靠 $request_length 记录
$request_length 是 Nginx 内置变量,表示从客户端接收到的完整请求数据长度(单位:字节),它严格等于:
- 请求行(如
GET /api/v1/users HTTP/1.1) - 所有请求头(Headers)
- 请求体(Body,若有)
这个值在每次请求结束时确定,稳定可靠,是统计请求报文大小的唯一可信依据。
要让 Prometheus 获取该分布,必须先落地到可观测数据源:
- ✅ 在
log_format中显式包含$request_length - ✅ 将 access 日志写入文件或转发至日志收集系统(如 Loki、Filebeat)
- ❌ Prometheus 不能直接读取 Nginx 日志文件,需额外组件桥接
示例日志格式配置(加在 http{} 块中):
log_format reqsize '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'$request_length $content_length '
'"$http_user_agent"';
access_log /var/log/nginx/access.log reqsize;用日志 + 脚本做分布统计(离线/准实时)
Prometheus 原生不支持对日志字段做直方图聚合,所以常用做法是:
- 定期用
awk/goaccess/jq(配合 vts JSON 接口)扫描日志 - 按区间(如
, <code>512–1024B,1024–2048B,≥2048B)计数 - 将结果写入文本文件或 Pushgateway,供 Prometheus 抓取
简单 awk 统计脚本示例(统计最近 1 小时日志):
zcat /var/log/nginx/access.log.*.gz 2>/dev/null | \
awk '$10 > 0 {
len = $10;
if (len < 512) a++;
else if (len < 1024) b++;
else if (len < 2048) c++;
else d++
}
END {
print "nginx_req_size_bucket{le=\"512\"}", a+0;
print "nginx_req_size_bucket{le=\"1024\"}", b+0;
print "nginx_req_size_bucket{le=\"2048\"}", c+0;
print "nginx_req_size_bucket{le=\"+Inf\"}", d+0
}' > /tmp/nginx_req_size.prom然后用 Node Exporter 的 textfile_collector 加载该文件,Prometheus 即可抓取 nginx_req_size_bucket 指标,配合 histogram_quantile() 计算 P90/P99 等。
更推荐:用 nginx-module-vts + Prometheus 直接暴露直方图
若你已启用 nginx-module-vts(生产环境推荐方案),它原生支持按虚拟主机、路径、状态码等多维分组,并提供 vts_filter_by_set_key 配合 vhost_traffic_status_zone 实现请求大小的近似直方图指标。虽然不直接暴露 request_length,但可通过以下方式增强:
- 在 vts 配置中开启详细统计:
http_vhost_traffic_status_zone; vhost_traffic_status_filter_by_set_key $request_length $server_name; # 注意:vts 不原生支持此用法,需 patch 或改用自定义 Lua 模块
- 实际更可行的是:用 vts 的
/status/format/json接口 + 自定义 Exporter 提取并重采样request_length分布,作为补充指标暴露。
注意事项
-
$request_length包含换行符(CRLF),但不影响总量统计 - 若启用了
gzip或chunked编码,不影响$request_length,它始终反映接收端原始字节数 - 不要依赖
$http_content_length做减法估算头大小用于 Prometheus 直接采集——该字段可能缺失、被篡改或不适用于流式请求 - 对于高吞吐场景(>1k QPS),避免在日志中记录
$request_body,会显著拖慢性能
不复杂但容易忽略


















