必须在http块内定义log_format并加escape=json参数,确保每行日志为合法JSON;变量值自动转义,键名和固定字符串不处理;字段需符合JSON语法,数值不加引号;末尾须加分号,名称需与access_log指令一致。

直接在 http 块内定义带 escape=json 的 log_format,并确保每行日志是一个合法、可解析的 JSON 对象。
必须加 escape=json 参数
Nginx 1.11.8+ 支持该参数,它会自动对变量值(如 $http_user_agent、$http_referer)做 JSON 字符串转义:换行变 \n,双引号变 \",控制字符被安全处理。不加这个,日志极易因 UA 或 Referer 中的特殊字符而结构损坏,导致下游解析失败。
- 只作用于变量值,键名和固定字符串不处理
- 不能靠手动替换双引号代替 —— 手动无法覆盖所有非法字符(如 \r、\t、未闭合引号)
- 格式定义中必须写成
log_format name escape=json '{...}';
字段写法要符合 JSON 语法规范
字符串字段(如 "remote_addr"、"uri")必须用双引号包裹;数值字段(如 status、body_bytes_sent、request_time)不加引号,方便日志系统后续做聚合统计。
- 错误示例:
"status":"$status"→ 导致 status 变成字符串,无法数值分析 - 正确示例:
"status":$status→ 输出"status":200 - 注意
$upstream_response_time可能为空或多值,建议仍用"$upstream_response_time"保持字符串类型,交由日志系统清洗
记得加分号,且名称要与 access_log 对应
log_format 指令末尾的分号 ; 容易遗漏。缺分号时 nginx -t 可能不报错,但日志格式实际不生效。
- 定义名称如
json_log,则对应 server 或 http 块中的access_log /var/log/nginx/access.log json_log; - 名称是引用标识,可自定义,不强制叫
main或json - 若某个
server块单独写了access_log,需显式指定该名称,否则沿用上级默认
推荐基础配置示例
以下为兼顾兼容性与可解析性的最小可靠模板:
log_format json_log escape=json '{"time":"$time_iso8601","remote_addr":"$remote_addr","host":"$host","uri":"$uri","status":$status,"body_bytes_sent":$body_bytes_sent,"http_referer":"$http_referer","http_user_agent":"$http_user_agent","request_time":$request_time}';
然后启用:access_log /var/log/nginx/access.log json_log;


















