Nginx日志格式定制:如何记录更有价值的访问信息?

Nginx日志格式定制:如何记录更有价值的访问信息?

你的Nginx日志长这样:192.168.1.1 - - [27/Jul/2026:14:30:25 +0800] "GET /index.html HTTP/1.1" 200 15234。这是默认的combined格式,记录了IP、时间、请求方法、状态码、响应大小。看起来够用了。直到你想知道“这个请求到底花了多长时间”,或者“用户真实IP是什么”。默认日志回答不了这些问题

你需要的字段不在里面。默认日志解决的是“谁访问了”,定制日志解决的是“访问过程怎么样”。

默认格式缺什么

Nginx默认的combined格式只记录请求的开始时间、HTTP方法、状态码、响应体大小。它不记录请求的处理时长,也不记录上游服务器的响应时间。当用户说“网站慢”时,你无法从默认日志中确认慢在哪一环——是Nginx处理慢,还是PHP-FPM执行慢,还是数据库响应慢。你只能凭猜测去排查

默认格式记录的客户端IP可能是CDN节点或负载均衡器的IP,而不是真实用户的IP。如果你的网站使用了CDN或七层负载均衡,日志中的$remote_addr记录的是最后一跳的IP,而不是访问者的真实IP

这两个缺失的信息,在故障排查和运营分析中恰恰是最需要的。

定制日志格式:log_format

Nginx通过log_format指令定义日志格式。将以下配置添加到http块中

nginx

http {
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    access_log /var/log/nginx/access.log main;
}

main是格式名称,在access_log指令中引用。$remote_addr记录直接连接的客户端IP。$remote_user记录基本认证用户名。$time_local记录请求时间。$request记录完整请求行(方法+路径+协议)。$status记录响应状态码。$body_bytes_sent记录响应体大小。$http_referer记录来源页面。$http_user_agent记录客户端标识。$http_x_forwarded_for记录原始客户端IP(需代理传递)

添加响应时间字段

响应时间是排查性能问题的关键字段。Nginx提供多个变量来记录时间

$request_time:从接收客户端第一个字节到发送完最后一个字节的总耗时,包括接收请求、处理请求、发送响应三个环节。单位秒,精度到毫秒。

$upstream_response_time:Nginx转发请求到上游服务器(如PHP-FPM、Tomcat)后,等待并接收完整响应所花费的时间。不包括Nginx自身的处理时间

$upstream_connect_time:与上游服务器建立连接所花费的时间。

$upstream_header_time:从连接到上游服务器到收到响应头第一字节的时间

在日志格式中添加这些字段:

nginx

log_format timing '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" '
                  'rt=$request_time uct=$upstream_connect_time '
                  'uht=$upstream_header_time urt=$upstream_response_time';

rt标记总响应时间,urt标记上游响应时间。当rt接近urt时,说明Nginx本身处理快,慢在上游服务。当rt远大于urt时,说明慢在Nginx层(可能是网络传输慢,也可能是客户端网络慢)

记录真实客户端IP

当网站使用CDN或七层负载均衡时,$remote_addr记录的是CDN节点或负载均衡的IP,而不是访问者的真实IP。CDN和负载均衡器通常会在HTTP头中传递原始客户端IP。对于通用CDN或代理,使用$http_x_forwarded_for

http块中添加以下配置,让Nginx从正确的位置获取客户端IP:

nginx

http {
    set_real_ip_from 10.0.0.0/8;
    set_real_ip_from 192.168.0.0/16;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
}

不同场景的日志格式推荐

场景推荐字段用途
运维排查$remote_addr$request$status$request_time$upstream_response_time定位性能瓶颈
安全分析$remote_addr$request$status$http_user_agent$http_x_forwarded_for识别异常请求
数据分析$request$status$http_referer$http_user_agent用户行为分析

一个真实案例

某电商平台在促销活动中发现部分用户打开商品页很慢。Nginx默认日志只显示状态码200和响应大小,看不出耗时。添加$request_time$upstream_response_time后,发现$upstream_response_time平均8秒,而$request_time平均8.5秒——慢在PHP-FPM处理环节,而不是网络或Nginx。针对商品详情接口优化代码和缓存后,$upstream_response_time降到0.2秒。

最后一句

Nginx默认日志只能告诉你“有人访问了”,定制日志能告诉你“访问过程怎么样”。默认日志记录的是谁来了,定制日志告诉你他等待了多久、慢在哪个环节。响应时间和真实IP这两个字段,在故障排查和运营分析中比默认字段更有价值。

去检查你的Nginx日志格式,把$request_time$upstream_response_time加进去,下次用户说“网站慢”时,你的日志里已经有答案了。

知识库

为什么我的服务器总在半夜重启?常见原因排查

2026-7-27 18:16:35

知识库

云服务器快照策略设计:多久打一次?保留多久?

2026-7-28 17:53:13