nginx 输出标准json日志可高效对接elk:需在http块定义escape=json的log_format,用$clientrealip获取真实ip,filebeat启用json.keys_under_root直解析,elasticsearch预置模板确保字段类型正确。

直接在 Nginx 中输出标准 JSON 格式日志,是对接 ELK 最简洁高效的方式。它把结构化工作提前到日志源头,省去 Logstash 里耗资源的 grok 解析,提升吞吐、降低延迟、减少解析失败风险。
定义带 escape=json 的 JSON 日志格式
在 /etc/nginx/nginx.conf 的 http 块内添加:
log_format json escape=json '{ "@timestamp":"$time_iso8601", "host":"$server_addr", "clientip":"$remote_addr", "url":"$request_uri", "status":$status, "method":"$request_method", "responsetime":$request_time, "size":$body_bytes_sent, "agent":"$http_user_agent" }';
- 必须加 escape=json:防止 $http_user_agent 或 $request_uri 中含双引号、换行符导致整行 JSON 损坏
- 字符串字段(如 status、url)值用 "$xxx" 包裹;数值字段(如 $status、$request_time)不加引号,Elasticsearch 才能自动识别为数字类型
- @timestamp 使用 $time_iso8601,Filebeat 或 Logstash 可直接映射为 Elasticsearch 的 @timestamp 字段
- 避免字段名与 Elasticsearch 内置字段冲突,比如不用 host 而用 server_host,不用 method 而用 http_method(可选但推荐)
启用日志并处理真实客户端 IP
若 Nginx 前有 CDN、负载均衡或反向代理,$remote_addr 会变成代理 IP。需先提取真实 IP:
在 http 块顶部添加:
map $http_x_forwarded_for $clientRealIp { "" $remote_addr; ~^(?P
然后将日志中的 "clientip":"$remote_addr" 替换为 "clientip":"$clientRealIp"。
再在 server 或 location 块中启用:
access_log /var/log/nginx/access.json json;
Filebeat 配置:零过滤直传
Filebeat 读取该 JSON 日志后,无需任何 grok 或 dissect,只需开启 JSON 解析即可:
在 filebeat.yml 的 inputs 下配置:
filebeat.inputs:
- type: filestream
paths:
- /var/log/nginx/access.json
json.keys_under_root: true
json.overwrite_keys: true
json.add_error_key: true
- json.keys_under_root: true 把 JSON 内字段提到根层级,Kibana 中可直接查 status、responsetime 等字段
- json.overwrite_keys: true 防止 Nginx 日志中同名字段(如 time_iso8601 和 @timestamp)互相覆盖
- Logstash 此时可简化为纯转发角色,甚至可跳过 Logstash,Filebeat 直连 Elasticsearch
ELK 后端适配要点
确保 Elasticsearch 接收日志后能正确索引和展示:
- 为 nginx 索引预置模板,指定 @timestamp 为 date 类型,status 为 integer,responsetime 为 float
- Kibana 中创建 index pattern,如 nginx-*,并确认 @timestamp 字段被识别为时间字段
- 首次导入后检查 Discover 页面,确认每条文档是合法 JSON,无 parse_error 或 _jsonparsefailure
- 建议在 Kibana 中新建一个 nginx 数据视图(Data View),明确设置时间字段为 @timestamp











