Nginx 打印请求日志主要通过 access_log 指令实现,而日志的核心价值在于 日志格式(log_format) 的定义。通过自定义格式,你可以记录请求的全貌,包括客户端 IP、响应时间、请求头、甚至 POST 请求体。
1. 基础配置(HTTP 模块)
在 nginx.conf 的 http 块中定义日志格式,并在 server 或 location 块中引用。
http {
# 1. 定义日志格式(这里定义了最常用的 combined 增强版)
log_format main '$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"';
# 2. 配置访问日志
access_log /var/log/nginx/access.log main;
# 3. 错误日志(独立配置)
error_log /var/log/nginx/error.log warn;
server {
listen 80;
server_name example.com;
# 可以为特定虚拟主机单独指定日志
access_log /var/log/nginx/example_access.log main;
location /api/ {
# 可以为特定路径单独记录详细日志
access_log /var/log/nginx/api_access.log api_detail;
proxy_pass http://backend;
}
}
}
2. 常用日志变量详解
| 变量名 | 说明 | 示例值 |
|---|---|---|
$remote_addr |
客户端 IP 地址 | 192.168.1.100 |
$remote_user |
基本认证用户名(如果启用) | admin |
$time_local |
本地时间 | 26/Sep/2026:14:30:00 +0800 |
$request |
完整的请求行(方法 + URI + 协议) | GET /api/user?id=1 HTTP/1.1 |
$status |
HTTP 状态码 | 200 |
$body_bytes_sent |
响应体字节数(不含响应头) | 1024 |
$http_referer |
来源页面(防盗链分析) | https://google.com/ |
$http_user_agent |
客户端浏览器/工具标识 | Mozilla/5.0 ... |
$http_x_forwarded_for |
经过代理后的真实 IP(如果有 CDN) | 1.2.3.4, 5.6.7.8 |
$request_time |
请求总处理时间(秒)(性能关键指标) | 0.123 |
$upstream_response_time |
上游服务器响应时间(后端服务慢时排查用) | 0.100 |
$upstream_addr |
上游服务器的 IP:端口 | 127.0.0.1:8080 |
$request_body |
请求体(POST 数据,需要开启记录) | {"key":"value"} |
$http_authorization |
Authorization 请求头(打印 Token 用于调试) | Bearer xxxxx |
3. 高级配置:记录 POST 请求体(Payload)
默认 Nginx 不记录请求体,需要额外配置:
http {
# 自定义格式,增加 $request_body
log_format post_log '$remote_addr - $time_local "$request" $status '
'body="$request_body"';
server {
location /api/ {
# 关键配置:记录请求体,但限制大小防止日志膨胀
lua_need_request_body on; # 如果使用 OpenResty
# 或者使用 nginx 原生方式(仅对某些模块有效)
proxy_set_header X-Request-ID $request_id;
# 记录包含 body 的日志(注意:大文件上传不要开启)
access_log /var/log/nginx/post_access.log post_log;
proxy_pass http://backend;
}
}
}
警告:记录 $request_body 会导致:
- 日志文件急剧增大(POST JSON 可能几 MB)
- 可能泄露敏感信息(密码、Token),仅限调试环境使用。
4. 日志切割与轮转(防止磁盘爆满)
使用 logrotate 工具管理日志文件。
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
daily # 每天轮转
missingok # 日志不存在不报错
rotate 52 # 保留 52 个归档(约 1 年)
compress # 压缩旧日志(gzip)
delaycompress # 延迟压缩,保留最近一个未压缩
notifempty # 空文件不轮转
create 0640 nginx adm # 重新创建新日志文件
sharedscripts
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
endscript
}
5. 实时查看日志(调试利器)
# 实时查看访问日志
tail -f /var/log/nginx/access.log
# 过滤特定接口
tail -f /var/log/nginx/access.log | grep "/api/user"
# 查看响应时间超过 1 秒的请求(用 awk)
awk '$NF > 1' /var/log/nginx/access.log
# 统计 Top 10 访问 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
6. 调试场景:打印自定义请求头
如果你需要调试 X-User-ID 等自定义头:
http {
log_format debug '$remote_addr - $time_local "$request" '
'X-User-ID="$http_x_user_id" '
'X-Trace-ID="$http_x_trace_id"';
server {
access_log /var/log/nginx/debug.log debug;
}
}
7. 条件日志(跳过健康检查)
避免日志被健康检查刷屏:
location /health {
access_log off; # 关闭健康检查日志
return 200 "OK";
}
location /api/ {
# 只记录非 200 和 304 状态码的请求
access_log /var/log/nginx/api.log main if=$status != 200;
}
总结关键点
| 目的 | 配置核心 |
|---|---|
| 基础访问记录 | access_log + log_format |
| 性能分析 | 记录 $request_time 和 $upstream_response_time |
| 调试 POST | 记录 $request_body(仅限测试环境) |
| 避免磁盘爆满 | 配置 logrotate |
| 减少无用日志 | 使用 access_log off 或 if 条件 |
以上就是Nginx打印请求日志的代码实现的详细内容,更多关于Nginx打印请求日志的资料请关注其它相关文章!










