Nginx 日志完全指南:access_log/error_log 配置、JSON 结构化与条件记录

Nginx 访问日志和错误日志在哪、怎么配?本文详解 log_format 自定义格式、escape=json 输出结构化日志、按状态码的条件日志、error_log 级别控制与 Docker 环境下的日志采集,并给出接入观测云实现集中检索与告警的落地路径。

最佳实践
Nginx 日志完全指南:access_log/error_log 配置、JSON 结构化与条件记录技术指南封面

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);
  • 集中采集后,先检查时间、HTTP 状态码与日志级别字段,再按服务和状态码建立查询。

日志文件在哪里?

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 会转义变量值中的引号等字符,整体 JSON 结构仍取决于 log_format 的写法。要在观测云关联日志与链路,日志中的 trace_id 必须与探针生成的链路标识一致;普通 X-Request-Id 不能直接当作这个标识,需按日志关联配置完成注入。

高流量降噪:条件日志

通过 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 的 Nginx 采集器中,将日志配置的 files 指向访问日志和错误日志路径,并指定 nginx.p 解析脚本。官方示例分别说明了两类日志的提取字段,其中 status_code 表示 HTTP 状态码,status 表示日志级别 。

容器使用 stdout/stderr 输出时,按容器运行时的日志路径配置采集。自定义 JSON 格式则需要匹配的 Pipeline 脚本;先用样例检查 time、状态码和 URI,再统计 5xx 数量,设置检测窗口、阈值与通知对象 。

总结

Nginx 日志配置的三板斧:access 侧用 log_format + escape=json 走向结构化,用 map 条件日志控制体量;error 侧用级别控制详略。集中采集后,保留原始日志与解析字段,方便从状态码统计回到具体请求。

常见问题(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 文本格式吗?
可以使用 Nginx 采集器提供的 Pipeline 示例解析常见访问日志。自定义字段或格式与示例不同时,需要调整脚本并用样例验证;JSON 输出也需要正确配置字段提取。


系列阅读:Apache 日志详解 | 微服务日志最佳实践

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台