Nginx通过log_format支持全链路追踪的核心是将上游传递的trace-id/span-id等追踪头(如$ Blowhttp_trace_id、$http_x_b3_traceid)及本机生成ID注入日志,需配合map标准化多源trace-id、Lua生成span-id,并在access_log中启用该格式,确保每条日志携带可关联的完整上下文。

要在 Nginx 中通过 log_format 支持全链路追踪,核心是把上游传递的分布式追踪 ID(如 trace-id、span-id、parent-id)以及本机生成的 ID 注入到日志中,使每条访问日志携带可关联的追踪上下文。Nginx 本身不生成或传播 trace,需依赖上游(如网关、前端服务)注入头,并用 $http_* 变量提取,必要时用 map 或 set_by_lua 补充逻辑。
1. 定义支持 trace-id / span-id 的日志格式
在 http 块中定义日志格式,优先捕获标准追踪头(如 W3C Trace Context、B3、Jaeger):
log_format trace_log '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'trace_id="$http_trace_id" ' 'span_id="$http_span_id" ' 'parent_id="$http_parent_id" ' 'x_request_id="$http_x_request_id" ' 'upstream_addr="$upstream_addr" ' 'upstream_response_time=$upstream_response_time ';
说明:
-
$http_trace_id对应请求头trace-id(小写转驼峰:HTTP 头Trace-ID→ 变量$http_trace_id) - 同理支持
span-id、parent-id、X-Request-ID等常见字段 - 若使用 W3C 标准(
traceparent),需解析其 version-traceid-spanid-traceflags 字段,Nginx 原生不支持解析,需 Lua 或 map 预处理
2. 使用 map 模块标准化不同来源的 trace-id
不同系统可能用不同 header 名称传 trace-id(如 X-B3-TraceId、uber-trace-id、traceparent),可用 map 统一映射为 $trace_id:
map $http_x_b3_traceid $trace_id {
"" $http_trace_id;
~. $http_x_b3_traceid;
}
<p>map $http_uber_trace_id $trace_id {
"" $trace_id;
~. $http_uber_trace_id;
}</p><p>map $http_traceparent $trace_id {
"" $trace_id;
~^([0-9a-f]{2})-([0-9a-f]{32})-([0-9a-f]{16}) $2; # 提取 W3C trace-id(32 hex)
}</p>然后在 log_format 中使用 $trace_id 替代原始变量,确保日志中 trace-id 字段始终有值且格式统一。
3. 自动生成本机 span-id(可选,增强链路完整性)
Nginx 不内置 UUID 生成,但可通过第三方模块或 Lua 实现:
- 启用
ngx_http_lua_module后,在http块中添加:
lua_package_path "/path/to/lua-resty-random/lib/?.lua;;";
init_by_lua_block {
require "resty.random"
}
set_by_lua $span_id '
local random = require "resty.random"
local r, err = random.bytes(8)
if r then
ngx.var.span_id = string.gsub(r, "%W", function(c) return string.format("%02x", string.byte(c)) end)
else
ngx.var.span_id = "unknown"
end
';
再将 $span_id 加入 log_format。注意:该 span-id 仅标识当前 Nginx worker 的处理单元,不参与跨服务传播,适合做本地子链路标记。
4. 启用日志并验证字段是否生效
在 server 或 location 块中启用自定义日志:
access_log /var/log/nginx/access-trace.log trace_log;
测试方法:
- 用 curl 发送带 trace 头的请求:
curl -H "Trace-ID: abc123" -H "Span-ID: def456" http://your-nginx/ - 检查日志输出是否包含
trace_id="abc123" span_id="def456" - 若使用 map 或 Lua,确认 fallback 逻辑(如无
X-B3-TraceId时是否回退到Trace-ID)
注意:Nginx 日志是最终落盘环节,不参与 trace propagation;真正实现“全链路”,还需上游服务透传头、下游服务读取并续传,Nginx 日志只是可观测性的一环。


















