nginx通过map预计算$log_me布尔值,仅对非200状态码或不在静态白名单内的200请求记录日志,从源头减少日志写入;白名单覆盖/static/、/images/、/fonts/等高频静态路径,并用location兜底记录异常200。

直接用 map 拦截高频 200 静态请求、只记录异常状态码(如 4xx/5xx、非预期的 3xx、或突发的 200 异常路径),是 Nginx 日志瘦身最干净、零侵入的方式。关键不在“过滤日志”,而在“不生成日志”——从源头减少写入压力。
明确哪些静态路径属于“高频 200”白名单
先梳理真实流量中稳定返回 200 的静态资源路径,例如:
- /static/css/app.css
- /images/logo.png
- /fonts/icon.woff2
- 匹配模式如 /static/.*\.(js|css|png|jpg|gif|woff2)$
这些路径在健康状态下几乎只返回 200,且访问量巨大。只要它们没出错,就不该挤占日志空间。
用 map 构建“是否跳过日志”的布尔标记
在 http 块中定义一个 $log_me 变量,逻辑为:
✅ 记录:状态码非 200,或状态码是 200 但路径不在白名单中
❌ 跳过:状态码是 200 且 路径匹配白名单
示例配置:
map $status $log_me {
default 1; # 默认记录(含 4xx/5xx/3xx/非白名单 200)
~^[2]00$ 0; # 状态码以 "200" 开头时先设为不记录
}
<p>map $request_uri $log_me {
~^/static/.<em>.(js|css|png|jpg|gif|woff2)$ 0;
~^/images/.</em>.(png|jpg|webp)$ 0;
~^/fonts/.*.(woff|woff2|ttf)$ 0;
default $log_me; # 继承上一个 map 的值
}</p>注意:
- 两个 map 按顺序叠加,后一个会覆盖前一个的值
- 使用 ~^ 做前缀正则匹配,高效且避免误伤
- 所有白名单路径必须显式覆盖,未匹配的 200 请求仍会记录(比如新上线的 /assets/xxx.js 未加规则)
在 access_log 中用 if 条件启用日志写入
将 $log_me 作为 access_log 的条件参数:
access_log /var/log/nginx/app-access.log main if=$log_me;
这样只有 $log_me = 1 时才真正写日志行。Nginx 内部会跳过格式化与磁盘 I/O,性能开销极低。
⚠️ 注意:
- 不支持在 if 中使用复杂表达式,所以必须靠 map 预计算好布尔值
- 日志格式(main)保持不变,所有字段照常可用,只是行数大幅下降
保留突发异常的 200 —— 用 location 精准兜底
有些路径虽属静态目录,但偶尔因权限、后端代理、或临时重写返回异常 200(比如本该 404 却返回了空 200 页面)。这时需反向控制:
- 在对应 location 块中显式重置 $log_me,强制记录
示例:
location ~ ^/static/.*\.js$ {
# 正常情况不记日志,但若出现特定异常响应头,强制记录
if ($upstream_http_x_debug = "logme") {
set $log_me 1;
}
# 或:当文件不存在却返回 200(防空页面劫持)
try_files $uri @fallback_200;
}
<p>location @fallback_200 {
add_header X-Logged "abnormal-200";
set $log_me 1; # 强制记录该次请求
return 200 "";
}</p>这种兜底方式不破坏主干规则,只对真正可疑的“伪正常”响应留痕,兼顾精简与可观测性。











