要让nginx日志真正服务于监控、排障和业务分析,必须通过log_format定义字段并用内置变量提取业务参数;log_format需置于http块,配合access_log启用;推荐json格式、按天切分及埋点专用日志。

要让 Nginx 日志真正服务于监控、排障和业务分析,光靠默认格式远远不够。核心在于两件事:一是用 log_format 精确控制每条日志的字段组成;二是通过内置变量把关键业务参数(比如埋点 ID、用户标识、活动来源)直接提取进日志,省去后续解析成本。
基础配置必须放在 http 块里
log_format 指令只能定义在 nginx.conf 的 http 块中,不能写在 server 或 location 里。它只是“定义模板”,不生效;真正启用要靠 access_log 指令。
- 每个 log_format 必须起一个唯一名称,例如 main_detail 或 json_trace
- 字段之间用空格或引号分隔,支持换行提高可读性(Nginx 会自动合并)
- 定义后,在 server 块里加一行 access_log /path/to/log.log main_detail; 就能启用
- 多个 server 可以引用同一个格式,也可以各自指定不同格式,互不影响
常用自定义字段与对应变量
选对变量是定制价值的关键。不是所有字段都随时可用,要注意它们所处的处理阶段:
- $request_time:整个请求从读取首字节到发送完响应的总耗时(秒,精度毫秒),用于识别慢请求
- $upstream_response_time:Nginx 转发给后端并收到响应的时间,多个 upstream 会以逗号分隔,直指后端瓶颈
- $http_x_forwarded_for:代理链中的原始客户端 IP,但需配合 set_real_ip_from 和 real_ip_header 才可靠
- $arg_XXX:提取 URL 查询参数,如 $arg_uid 可捕获 ?uid=abc123 中的值,适合前端埋点上报
- $request_id:Nginx 自动生成的唯一请求 ID(1.11.0+ 默认支持),是全链路追踪的基础字段
- $scheme $server_name $request_uri:补全协议、域名、完整路径,便于按站点/路径聚合分析
JSON 格式日志更适配现代分析栈
如果后续要用 Filebeat + Elasticsearch 或 Loki 做日志采集与查询,原生 JSON 格式比空格分隔的日志更友好,字段自动可索引。
- 用双引号包裹整个 JSON 字符串,内部字段名和字符串值也用双引号
- 时间建议用 $time_iso8601(如 2026-07-07T08:29:15+08:00),比 $time_local 更易被日志系统识别
- 可嵌入业务参数,例如 "campaign_id": "$arg_cid",前端带 ?cid=newyear2026 就自动记录
- 加上 buffer=32k 参数可减少磁盘 I/O,提升高并发写入稳定性
按天切分与埋点专用日志实践
高频埋点请求(如打点 GIF、上报接口)不适合混在主访问日志里,建议单独隔离并按天归档。
- 用 map 指令提取日期: map $time_iso8601 $logdate { ~^(?
\d{4}-\d{2}-\d{2}) $ymd; default 'unknown'; } - 定义专用格式,只保留埋点需要的字段,例如:log_format track '{"ts":"$time_iso8601","uid":"$arg_uid","evt":"$arg_evt","ip":"$remote_addr"}';
- 在 location 块中单独配置:access_log /var/log/nginx/track_$logdate.log track;
- 搭配 empty_gif 或快速返回,确保埋点不影响用户体验











