nginx 的 error_log info 级别不支持动态变量插值,仅输出固定格式内部事件;深度追踪变量必须使用 access_log + 自定义 log_format,或启用 debug 编译版配合 error_log debug。

info 级别 error_log 本身不记录请求变量变化
直接启用 error_log ... info 不会自动打印 $uri、$args、$upstream_addr 这类变量的值——Nginx 的 error_log 在 info 及以下级别(notice、warn)只输出固定格式的内部事件(如“upstream timed out”),不支持动态插值。想“深度追踪变量”,必须配合 log_format + access_log,或用 ngx_http_log_module 的 log_subrequest 配合调试模块。
真正能打变量的方案:access_log + 自定义 log_format
把变量输出到日志的可靠路径是 access_log,它支持完整变量展开。你需要:
- 定义含多阶段变量的
log_format,例如包含$time_iso8601、$request_length、$upstream_http_x_trace_id、$upstream_connect_time - 在需要观测的 location 或 server 块中启用该 format 的
access_log,路径建议独立(如/var/log/nginx/trace.log),避免污染主访问日志 - 若需 subrequest(如 internal redirect、auth_request)中的变量,加
log_subrequest on,否则子请求默认不记 - 注意:
access_log的写入发生在请求结束时,无法看到中间阶段(如 rewrite 后、proxy_pass 前)的瞬时值
要抓 rewrite / proxy_pass 前后的变量?用 nginx-debug 或 echo 模块
原生 Nginx 不提供“每阶段打点”能力。可行替代方案有:
- 编译安装带
--with-debug的 Nginx,然后设置error_log /path/debug.log debug;—— 它会输出大量内部状态,包括http script value: "$uri"、rewrite phase: 0等,但日志量极大、无结构、难过滤 - 使用第三方
echo-nginx-module:在关键位置插入echo "uri=$uri args=$args";或echo_location触发子请求并打日志,需搭配access_log捕获其输出 - 用
map构造调试标记变量(如map $uri $debug_marker { ~^/api/ "in-api"; }),再把它塞进log_format,实现轻量级阶段标记
info 日志里唯一有用的变量线索:$pid 和 $connection
虽然 error_log ... info 不展开变量,但部分内置 info 级日志行会隐式携带上下文标识:
-
connect() failed (111: Connection refused) while connecting to upstream, client: 10.0.1.2, server: api.example.com, request: "GET /v1/users HTTP/1.1", upstream: "http://127.0.0.1:8000/v1/users", host: "api.example.com"—— 这里的request和upstream字段实际就是运行时拼接结果,可反推$request和$upstream_http_host值 - 所有 info 行都带
pid和connection,可用于关联同一请求在不同日志行(access_log / error_log / debug_log)中的轨迹 - 务必开启
daemon off;和master_process off;调试时,避免 worker 进程切换导致$pid失效
真要逐阶段看变量,别指望 error_log info —— 它不是为此设计的。要么切到 access_log 做终态快照,要么上 debug 编译版做全链路埋点,二者之间没有平滑过渡。











