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 -106. 调试场景:打印自定义请求头
如果你需要调试 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打印请求日志的资料请关注代码网其它相关文章!
发表评论