Nginx 日志完全指南:access_log/error_log 配置、JSON 结构化与条件记录
Nginx 访问日志和错误日志在哪、怎么配?本文详解 log_format 自定义格式、escape=json 输出结构化日志、按状态码的条件日志、error_log 级别控制与 Docker 环境下的日志采集,并给出接入观测云实现集中检索与告警的落地路径。
Nginx 日志(Nginx Logging)由访问日志(access log)与错误日志(error log)组成:访问日志逐条记录客户端请求的处理结果,错误日志记录请求处理及服务运行中的异常事件。 作为使用率最高的 Web 服务器与反向代理之一,把 Nginx 日志配置好、结构化好,是 Web 可观测的第一步。
核心要点速览
- 默认位置
/var/log/nginx/access.log与error.log;Docker 官方镜像把二者软链到 stdout/stderr; - 访问日志默认 combined 格式,用
log_format可自定义,加escape=json可直接输出 JSON; - 高流量下用
map+if=做条件日志,只记 4xx/5xx 或按采样记录,显著降噪降本; error_log第二参数控制级别(默认 error,Docker 镜像默认 notice);- 观测云落地:DataKit 采集 → Pipeline 切割 time/status → 查看器聚类分析 → 监控器按状态码告警。
日志文件在哪里?
Linux 直装场景默认在 /var/log/nginx/ 目录。找不到时用 sudo nginx -t 定位配置文件,再查其中的 error_log 与 access_log 指令。
Docker 场景:官方镜像将 /var/log/nginx/access.log 软链到 /dev/stdout、error.log 软链到 /dev/stderr,所以直接用 docker logs -f <容器> 查看;只看访问日志加 2>/dev/null,只看错误日志加 1>/dev/null。
访问日志:默认格式解读
默认 combined 格式:
'$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"'
对应一条日志逐字段解读:
| 字段 | 示例 | 含义 |
|---|---|---|
$remote_addr |
172.17.0.1 | 客户端 IP |
$time_local |
[27/May/2026:16:37:59 +0000] | 本地时间 |
$request |
"GET / HTTP/1.1" | 方法、URI、协议 |
$status |
200 | 响应状态码 |
$body_bytes_sent |
615 | 响应体字节数 |
$http_referer |
"-" | 来源页 |
$http_user_agent |
Mozilla/5.0 ... | 客户端 UA |
$http_x_forwarded_for |
"-" | 经过代理时的原始客户端 IP |
自定义格式与 JSON 结构化
在 http 块中用 log_format 定义、在 access_log 中按名启用。例如加上 $host 记录域名:
log_format with_host '$remote_addr - [$time_local] "$host" "$request" $status $body_bytes_sent "$http_user_agent"';
access_log /var/log/nginx/access.log with_host;
更进一步,直接输出 JSON——这是接入日志平台的最佳姿势:
log_format json_access escape=json '{'
'"time":"$time_iso8601",'
'"remote_ip":"$remote_addr",'
'"method":"$request_method",'
'"uri":"$request_uri",'
'"status":$status,'
'"bytes_sent":$bytes_sent,'
'"duration_sec":$request_time,'
'"user_agent":"$http_user_agent",'
'"trace_id":"$http_x_request_id"'
'}';
access_log /var/log/nginx/access.log json_access;
escape=json 会自动转义 UA 中的引号等非法字符,保证 JSON 永远合法。把 traceparent/X-Request-Id 等链路头写进日志,后续可在观测云中实现日志与 APM 链路的双向跳转 。
高流量降噪:条件日志
通过 map 定义"是否记录"的开关,跳过 2xx/3xx 只留异常:
map $status $loggable {
~^[23] 0;
default 1;
}
access_log /var/log/nginx/access.log combined if=$loggable;
典型用法:只记 4xx/5xx、排除已知爬虫 UA、只对特定路径记录。若应用层已记录完整请求日志,也可用 access_log off; 彻底关闭 Nginx 访问日志。
错误日志:级别与多文件
error_log /var/log/nginx/error.log warn;
级别从低到高:debug → info → notice → warn → error → crit → alert → emerg。未配置时默认记录 error 及以上(官方 Docker 镜像默认为 notice)。错误日志格式固定为"时间 [级别] pid#tid: *cid 消息, client/ server/ request 上下文",不支持自定义格式,但支持多文件分级输出:
error_log /var/log/nginx/error.log info;
error_log /var/log/nginx/emerg.log emerg;
接入观测云:从采集到告警
观测云落地:直装场景用 DataKit 磁盘文件采集 logging.conf 指向 /var/log/nginx/*.log;容器场景直接采集容器 stdout,无需挂载日志目录 。JSON 格式日志会被自动解析;传统 combined 格式用 Pipeline grok 切割,并提取标准字段 time 与 status(可按状态码区间映射:4xx→warning、5xx→error),切割后在查看器中按级别着色筛选 。随后:在日志查看器用聚类分析归并海量错误日志(自动提取 pattern,1 万条内快速发现新异常);在**监控器(日志检测)**配置"5xx 数量 5 分钟内超过阈值即告警",告警策略绑定钉钉/企业微信/飞书通知对象 ;常用统计(QPS、状态码分布、TOP URI)可从查看器一键导出到仪表板长期跟踪。
总结
Nginx 日志配置的三板斧:access 侧用 log_format + escape=json 走向结构化,用 map 条件日志控制体量;error 侧用级别控制详略。落到平台侧,DataKit + 观测云负责把这些日志变成可检索、可聚类、可告警的数据资产。
常见问题(FAQ)
Q:access.log 里的 $request_time 和 $upstream_response_time 有什么区别?
$request_time 是 Nginx 处理请求的完整耗时(含读写客户端);$upstream_response_time 只是上游后端响应的耗时。反向代理场景下二者差值大,通常说明慢在客户端网络或 Nginx 缓冲。
Q:为什么配置了 log_format 却不生效?
log_format 只是"定义",必须在 access_log 指令中按名字引用才生效;另外自定义格式只能写在 http 块中,写到 server 块会报语法错误。
Q:Docker 里想把 Nginx 日志同时落盘怎么办?
可在 nginx.conf 中额外添加一条指向挂载目录的 access_log /var/log/nginx/file_access.log;(Nginx 支持多目标同时输出),或将宿主机目录挂载进容器再按文件采集。
Q:观测云能直接解析 combined 文本格式吗?
可以。在 DataKit 或中心 Pipeline 中用内置的 nginx 日志 grok 模式即可切割出 IP、方法、URI、状态码等字段,无需应用侧改造;但源头输出 JSON 仍是性能与准确性的最优解。
系列阅读:Apache 日志详解 | 微服务日志最佳实践