nginx自定义日志变量需先用set或map声明再在log_format中引用:set适用于server/location内静态或参数提取,map用于http块顶层条件映射;变量仅在其作用域及子块有效,log_format须在access_log前定义。

Nginx 日志中使用自定义变量,核心在于两步:先声明变量值,再在 log_format 中引用。它不依赖模块开发,普通配置即可实现,但必须注意作用域和声明顺序。
变量声明:用 set 或 map 定义值
普通业务场景推荐用 set 指令,在 server 或 location 块内直接赋值:
-
set $log_env "prod";—— 静态字符串,适合固定环境标识 -
set $log_user_id $arg_uid;—— 把 URL 参数uid=123提取为变量 -
set $log_trace_id $http_x_request_id;—— 从请求头提取追踪 ID
若需条件映射(比如按 Cookie 切分环境),必须用 map,且只能写在 http 块顶层:
map $cookie_env $log_backend { default "prod"; "staging" "staging"; }- 之后所有
server和location都能直接用$log_backend
日志格式:把变量嵌入 log_format
在 http 块中定义日志模板,把自定义变量像内置变量一样写进去:
log_format custom '$remote_addr [$time_local] "$request" $status $body_bytes_sent $log_env $log_user_id';- 变量名前加
$,位置随意,支持空格、引号、连字符等分隔符 - 若变量可能为空(如未传
uid),日志中对应位置会显示空字符串,不影响格式对齐
启用日志:绑定格式与文件路径
在需要记录的 server 或 location 中指定日志输出:
-
access_log /var/log/nginx/app.log custom;—— 使用刚才定义的custom格式 - 可为不同服务配置不同日志文件和格式,互不干扰
- 确保
log_format在access_log引用前已定义,否则 reload 失败
注意事项:避免常见陷阱
自定义变量不是全局共享的,作用域规则很关键:
-
set变量只在当前块及子块生效,location内set的变量无法被同级另一个location读取 -
map是唯一跨server复用的方式,但源变量必须存在(不能是未定义的$my_var) - 不能在
if块里用set赋值后再用于log_format—— 因为log_format在日志写入时才求值,而if的执行时机不保证 - 记录 POST body 等敏感内容需额外处理(如用 Lua),原生 Nginx 不支持直接记
$request_body











