Nginx日志需采用规范JSON格式,统一小写下划线命名、字符串加双引号、数值不加引号;必含$time_iso8601时间戳、$remote_addr与$http_x_forwarded_for客户端标识、request_time与upstream_response_time性能指标、$host/$request_uri等路由字段及$status/$upstream_status状态归因,并按ES或Loki适配预埋service、label等字段。

关键在于让 Nginx 日志天然结构化、字段语义明确、时间可对齐,并与 Grafana 支持的数据源(如 Elasticsearch、Loki)无缝衔接。log_format 不是简单拼字段,而是定义监控维度的起点。
一、日志格式必须为 JSON 且字段命名规范
避免空格、特殊符号和歧义字段名,统一使用小写+下划线,所有字符串值加双引号,数值不加引号。例如:
-
✅ 推荐写法:
log_format grafana_json '{"@timestamp":"$time_iso8601","client_ip":"$remote_addr","method":"$request_method","path":"$request_uri","status":$status,"size":$body_bytes_sent,"rt":$request_time,"upstream_rt":"$upstream_response_time","upstream_addr":"$upstream_addr","host":"$host","user_agent":"$http_user_agent","referer":"$http_referer","xff":"$http_x_forwarded_for"}'; - ❌ 避免写法:混用单双引号、status 写成 "$status"(导致 ES 解析为字符串)、字段含空格如 "HTTP Status"、未转义嵌入引号导致 JSON 解析失败。
二、必含核心监控维度字段
这些字段直接支撑 Grafana 多维下钻与聚合分析:
-
时间戳:固定用
$time_iso8601,确保时区一致(UTC),Grafana 时间范围筛选才准确; -
客户端标识:同时保留
$remote_addr(真实直连 IP)和$http_x_forwarded_for(多层代理链),便于识别真实用户或封禁恶意节点; -
性能指标:显式分离
request_time(Nginx 处理总耗时)与upstream_response_time(后端响应耗时),两者差值即为 Nginx 自身开销; -
路由与上下文:
$host、$server_name、$request_uri、$scheme缺一不可,支撑按域名、路径前缀、协议类型做流量拆分; -
状态归因:
$status(原始状态码)、$upstream_status(上游返回状态),用于区分是网关拦截(4xx/5xx)还是后端异常。
三、适配不同后端数据源的增强技巧
根据你用的是 Elasticsearch 还是 Loki,微调 log_format 可省去大量 Logstash 或 Promtail 的解析工作:
-
对接 Elasticsearch:在 JSON 中预埋
"log_type": "nginx_gateway"和"service": "ai-gateway"字段,方便 Kibana/Grafana 按 service 聚合,也利于 index template 自动匹配 mapping; -
对接 Loki:Loki 不索引 JSON 全文,但支持 label 提取。可在 log_format 中用
{...} | service="ai-gateway" host="$host" status="$status"格式(需配合 Promtail pipeline 支持),把高频过滤字段作为 labels,大幅提升查询效率; -
预留扩展位:加入
"trace_id":"$http_x_request_id"或"span_id":"$http_x_b3_spanid",未来接入 OpenTelemetry 链路追踪时无需改日志格式。
四、验证与上线前检查项
格式写完不等于可用,务必逐项确认:
- 重启 Nginx 后执行
tail -f access.log | head -n 1,粘贴到 JSON 校验工具(如 jsonlint.com)看是否合法; - 在 Grafana 中用 Explore 模式查日志源,输入
{job="nginx"} | json(Loki)或log_format:grafana_json(ES),确认各字段可被自动提取为 label 或 field; - 测试高并发场景下日志是否丢行、RT 字段是否出现“-”或“0.000”,如有需在 log_format 中用
"rt":${request_time:-0}(Tengine 支持)或 Nginx 1.19+ 的$request_time默认行为兜底; - 敏感字段如
$http_authorization或$request_body切勿写入生产日志,既违反安全规范,也大幅增加存储与索引压力。

















