nginx 默认不将后端返回的5xx等异常http状态码记入error_log,主渠道是access_log;可通过自定义log_format记录$upstream_status到access_log,或用map+log_by_lua将异常状态码以warn/err级别写入error_log,或结合proxy_intercept_errors与error_page间接捕获。

在 Nginx 中,后端(如上游服务器)返回的异常状态码(例如 500、502、503、504)默认不会直接记入 error_log,除非触发了 Nginx 自身的错误处理逻辑(比如连接失败、超时、上游不可达)。要主动捕获并记录这些 HTTP 状态码,需结合 log_format、access_log 和条件日志,或利用 error_log 的特定级别与模块能力。但需明确:Nginx 的 error_log 主要记录服务自身错误(配置、IO、proxy 失败等),而非标准 HTTP 响应码;真正记录响应状态码的主渠道是 access_log。若坚持写入 error_log,可通过以下方式间接实现。
使用 $upstream_http_* 和 $upstream_status 记录到 access_log(推荐)
这是最常用、最可靠的方式。通过自定义日志格式,将上游响应状态码、响应头、耗时等关键信息输出到访问日志中,便于后续分析和告警。
- 在
http块中定义日志格式,包含$upstream_status(上游实际返回的状态码)和$status(Nginx 返回给客户端的状态码):
- 在
location或server块中启用该日志:
- 这样,当后端返回 502 时,日志中会明确出现
status=502,可配合日志收集工具(如 Filebeat + ELK)做状态码聚合与告警。
用 map 指令对异常状态码触发 error_log 输出
Nginx 本身不支持直接把 $status 写进 error_log,但可通过 map 构建条件变量,再结合 error_log 的 notice 或 warn 级别(需开启调试日志或自定义模块),或更实用的方式:用 log_by_lua(需启用 ngx_lua 模块)实现精准控制。
- 基础 map 示例(仅用于标记,不直接写 error_log):
~^[5-9][0-9][0-9]$ "1";
default "0";
}
- 该变量可用于后续判断,例如在
log_format中输出标记,或配合 Lua 脚本:
if ngx.var.is_upstream_error == "1" then
ngx.log(ngx.WARN, "Upstream error: ", ngx.var.upstream_status,
" for ", ngx.var.uri);
end
}
- 此方式会将异常请求以
WARN级别写入error_log,内容清晰可检索,且不影响性能(log_by_lua 执行在请求结束阶段)。
利用 proxy_intercept_errors + error_page 实现显式错误捕获
当启用 proxy_intercept_errors on 后,Nginx 会截获 300–599 的上游响应,并交由 error_page 处理。此时可在 error_page 对应的 location 中,通过变量(如 $upstream_status)记录或重定向,但注意:error_page 中的 log_format 变量仍可用,而 error_log 不会自动记录该状态码 —— 需配合 return 或 echo + Lua 实现日志落盘。
- 典型配置片段:
error_page 500 502 503 504 /error_handler;
location = /error_handler {
internal;
# 可在此处调用 log_by_lua 记录详细信息
log_by_lua_block {
ngx.log(ngx.ERR, "Intercepted upstream error: ", ngx.var.upstream_status);
}
return 502;
}
注意事项与限制
-
$upstream_status仅在 proxy_pass 场景下有效,且依赖于成功建立连接并收到响应;连接拒绝、超时等情况该变量为空或为 “000”。 - 原生 Nginx 不支持将任意响应码直接写入
error_log,error_log的内容由核心模块或第三方模块(如 lua-nginx-module)控制。 - 避免过度使用
log_by_lua记录高频请求,建议按需设置阈值(如仅记录 5xx 且非健康检查请求)。 - 确保
error_log级别不低于所用日志等级(如ngx.WARN要求error_log ... warn)。











