可通过map预分类状态码并结合多条access_log指令与if=条件实现按状态码分流日志:2xx写normal.log,429/503/504写abnormal.log,支持熔断监控与精准排障。

直接用 access_log 指令无法根据状态码动态切换日志文件,但通过 map 预分类 + 多条 access_log 指令 + if= 条件控制,就能把正常请求(如 2xx)和异常熔断类响应(如 429、503、504)分别写入不同日志文件,无需外部工具。
定义状态码分组映射
在 http{} 块中,用 map 把常见状态码归类为布尔标记变量。注意:每个 map 的值必须是字符串,且非空即为真(if= 判定时生效):
-
map $status $log_normal { default ""; ~^[2] "1"; }—— 匹配所有 2xx 状态码 -
map $status $log_abnormal { default ""; ~^(429|503|504)$ "1"; }—— 精准匹配熔断/服务不可用状态码 -
map $status $log_4xx { default ""; ~^[4] "1"; }—— 可选:额外捕获全部 4xx(不含 429)用于调试
配置差异化日志格式
为不同用途的日志定义清晰可读的格式,便于后续分析或告警对接:
log_format normal '$remote_addr [$time_local] "$request" $status $body_bytes_sent';-
log_format abnormal '$remote_addr [$time_local] "$request" $status $upstream_status $request_time $upstream_response_time "$http_user_agent"';—— 加入上游状态和耗时,定位是 Nginx 本身限流还是后端超时
在 server 或 location 中启用条件日志
把每类日志单独声明,并绑定对应 if= 变量。Nginx 1.7.0+ 均支持该语法,且只在变量非空/非零时写入:
access_log /var/log/nginx/normal.log normal if=$log_normal;access_log /var/log/nginx/abnormal.log abnormal if=$log_abnormal;- 可保留一条默认日志用于兜底:
access_log /var/log/nginx/access.log combined if=$log_4xx;
配合熔断行为做日志强化
如果使用了限流(limit_req)或主动返回 503,建议在对应 location 中显式设置变量,确保日志可追溯:
- 在触发限流的 location 内加:
set $log_abnormal "1"; - 或用
error_page 429 = @log_429;+location @log_429 { ... set $log_abnormal "1"; ... },让自定义错误页也进入异常日志流











