nginx access log 的 if 参数不支持直接抽样,但可通过 $msec 时间模运算或 $request_id 哈希实现约1%概率抽样,推荐后者以保证跨实例一致性。

Access log 的 if 参数本身并不直接支持“抽样”(sampling)逻辑,它只接受布尔表达式,用于决定某条请求是否记录到该日志段。但你可以结合 Nginx 内置变量(如 $request_id、$msec 或自定义 map)构造概率性条件,实现有选择性的抽样记录。
用 $msec 做简单时间模抽样
$msec 是毫秒级时间戳(带小数),取整后对某个数取模,可近似实现固定比例抽样。例如保留约 1% 的请求:
log_format sample_log '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_time';
<p>access_log /var/log/nginx/sample.log sample_log if=$sample_flag;</p><h1>每 100 毫秒中大约选 1 个(即 ~1% 概率)</h1><p>map $msec $sample_flag {
~^(\d+).(\d{3})$ $((10#$1 % 100 == 0 && 10#$2 </p>说明:提取整秒部分模 100,再限制毫秒前缀小于 10,综合接近 1% 触发。注意 map 中不能直接写复杂算术,需借助正则提取 + 条件判断,且仅适用于较新 Nginx(≥1.19.2 支持 map 中的算术)。
用 $request_id 的哈希值做稳定抽样
更推荐的方式是基于请求唯一标识做哈希,保证同一请求在不同机器/重启后抽样结果一致,适合调试和追踪:
对设计或页面进行 WCAG 2.1 AA 无障碍审计。触发关键词:“audit accessibility”、 “check a11y”、 “is this accessible?” 或在审查设计时使用。
map $request_id $sample_hash {
default 0;
}
<h1>将 request_id 前 8 字符转为十六进制整数,再模 100</h1><h1>(需配合第三方模块如 ngx_http_js_module,或用 Lua)</h1><h1>简化替代:用内置 $connection_requests(不稳定)或借助 split_clients</h1>实际中,纯 OpenResty/Nginx + Lua 更灵活:
set_by_lua_block $sample_flag {
local hash = ngx.crc32_short(ngx.var.request_id or ngx.var.remote_addr)
return (hash % 100) 用 split_clients 实现分桶式抽样(无依赖)
如果不想引入 Lua,可用 split_clients 预先划分请求桶,再用 map 映射为布尔标志:
split_clients "$remote_addr$remote_port$request_uri" $sample_bucket {
5% "1";
* "0";
}
<p>map $sample_bucket $sample_flag {
"1" 1;
"0" 0;
}</p><p>access_log /var/log/nginx/sample.log sample_log if=$sample_flag;</p>说明:基于客户端地址+端口+URI 哈希分桶,5% 的请求命中 "1",从而被记录。这种方式无需额外模块,稳定性好,但抽样键不可控(不适用于需按用户 ID 抽样的场景)。
注意事项与建议
- 抽样比例不宜过低(如
- 避免在
if中使用耗时变量(如$upstream_http_*),它们可能延迟日志判断时机 - 若需按业务维度抽样(如只记录特定 user_id 或 trace_id),应在 upstream 返回头中注入标识,并用
map提取后判断 - 抽样日志建议单独配置
buffer和flush参数,减少 I/O 频次










