直接在 nginx log_format 中使用 $upstream_status 可精准记录后端真实状态码,需确保后端稳定响应、未启用 proxy_intercept_errors、正确透传响应头,并配合 $upstream_addr 和 $upstream_response_time 分析异常,通过 map 实现条件日志以聚焦 4xx/5xx 错误。

直接在 Nginx 的 log_format 中引用 $upstream_status,就能记录后端真实返回的状态码,而不是上游转发失败时的代理层状态(比如 502/503),这是实现精准监控的关键。
确认变量可用且后端响应已透传
$upstream_status 是 Nginx 内置变量,但它的值依赖于 upstream 模块是否成功收到后端响应。如果后端超时、拒绝连接或 Nginx 自身无法转发请求,该变量可能为空或为 000。因此需确保:
- 后端服务稳定可连,且明确返回 HTTP 状态码(如 200、404、500)
- 未启用
proxy_intercept_errors on—— 否则错误响应可能被 Nginx 拦截并替换为自定义页面,导致$upstream_status记录的是拦截前原始状态,但日志中 body 已非后端原样 - 使用
proxy_pass时,后端响应头未被显式清除(如未用proxy_hide_header屏蔽Status或其他影响状态判断的头)
在 log_format 中正确嵌入变量
推荐将 $upstream_status 与其他 upstream 相关变量组合使用,便于关联分析:
- 基础写法:
log_format main '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$upstream_addr" $upstream_status $upstream_response_time'; -
$upstream_addr显示实际处理请求的后端地址(含 IP:port 或 name),配合$upstream_status可定位具体节点异常 -
$upstream_response_time与$upstream_status并列,能区分是慢响应(如 200 但耗时 5s)还是错误响应(如 500 + 0.001s)
结合 access_log 条件输出,减少无效日志
并非所有状态都需要记录完整字段。可通过 map 构建条件日志,只对异常状态做详细记录:
- 先定义 map:
map $upstream_status $log_level { ~^[45] $upstream_status; default "-"; } - 再在 log_format 中引用:
"$log_level",这样正常 2xx/3xx 请求对应字段为 "-",而 4xx/5xx 则显示具体状态码 - 也可用
access_log ... if=$log_level;实现仅对非 "-" 的行写入独立日志文件,方便告警和归档
验证与常见陷阱
部署后务必验证变量是否真实生效:
- 手动触发后端返回 404 或 500(如调用一个不存在的接口),检查日志中
$upstream_status是否匹配,而非固定为 200 或空 - 若始终为 000:可能是 upstream 配置缺失、后端无响应、或请求根本没走到 proxy_pass(例如被 rewrite 或 return 提前终止)
- 注意区分
$upstream_status和$status:$status是 Nginx 发给客户端的状态,$upstream_status是后端返回给 Nginx 的状态——两者不一致时(如后端 500 被 Nginx error_page 处理成 200),正是需要监控的重点











