

从Nginx过滤打印user-agent为clb-healthcheck的日志聊聊Nginx的日志自定义打印
source link: https://wiki.eryajf.net/pages/5fce99/#%E6%89%A9%E5%B1%95
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

从Nginx过滤打印user-agent为clb-healthcheck的日志聊聊Nginx的日志自定义打印
# 缘起
通常我们的南北流量的链路是从云的 LB 到服务器的 Nginx 集群,为了利用好 lb 自动检测 Nginx 的功能,通常你会打开健康检查,此时,Nginx 的日志当中就会打印大量的健康检查日志,令人不胜其烦。
# 解决
此时,你可以通过如下配置方式,将健康检查的日志过滤掉,通常,健康检查的日志大概如下:
{
"remote_addr": "1.1.1.1",
"@timestamp": "2023-10-24T09:44:41+08:00",
"request_uri": "/webStatus",
"verb": "GET",
"httpversion": "HTTP/1.1",
"response": "200",
"body_bytes_sent": "0",
"referrer": "-",
"user_agent": "clb-healthcheck",
"http_x_forwarded_for": "-",
"server_name": "test.eryajf.net",
"request_time": "0.000",
"upstream_response_time": "-",
"upstream_addr": "-",
"realpath_root": "/usr/local/nginx/html",
"request_body": "-",
"nginx_version": "1.14.0",
"scheme": "http"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
可以观察到一个特征,所有健康检查的日志的 ua,都是 clb-healthcheck
,于是,我们可以在 Nginx 配置中增加如下配置:
map $http_user_agent $log_ua {
clb-healthcheck 0;
default 1;
}
access_log /data/log/tmp.log json if=$log_ua;
2
3
4
5
6
7
简单说明:此处通过一个 map 来声明一个规则,并通过 0 和 1 表示是否匹配,然后 access_log 中通过 if 判断来应用这个规则。此规则表示如果该条日志中 ua 包括 clb-healthcheck 则不进行记录,否则记录。

可以看到,第一条请求日志正常打印,应用如上规则之后,同样的 ua 的第二条请求则不再输出对应日志,而非此 ua 的第三条请求,日志正常输出打印。
# 扩展
事实上除了上边基于 ua 的方式之外,Nginx 所有的内置变量 (opens new window)都是支持这么定义的。里边变量比较多,我们常用的变量如下:
$host
:访问域名
$uri
:请求 uri
$status
:http 状态码
$request_method
:请求方法
$request_completion
:请求是否完成
$upstream_addr
:反向代理的 upstream
$upstream_status
:upstream 响应值
$scheme
:请求的协议
$http_referer
:referer 来源
$http_user_agent
:浏览器的 user agent
$http_cookie
: 本地所有 cookie,也可以打印指定 cookie,如打印 session: $http_session
$args 或$arg\_
: 请求时的参数
这里摘出几个简单做下示例。
基于域名的规则
map $host $log_host {
~nixops.me 1;
~nixops1.me 1;
default 0;
}
server {
[…]
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/nixops.me.log main if=$log_host;
}
2
3
4
5
6
7
8
9
10
11
这样 /var/log/nginx/nixops.me.log 里面就只有 nixops.me 和 nixops1.me 这两个域名的日志了。
基于http状态码的规则
map $status $log_status {
~^[50] 1;
404 1;
default 0;
}
server {
[…]
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/http_error.log main if=$log_status;
}
2
3
4
5
6
7
8
9
10
11
这样就输出 502、503、504、404 日志到 /var/log/nginx/http_error.log
。
基于指定uri的规则
map $uri $log_uri {
~*admin 1;
/api 1;
default 0;
}
server {
[…]
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/http_uri.log main if=$log_uri;
}
2
3
4
5
6
7
8
9
10
11
另一种写法:
server {
[…]
set $log_uri 0;
if ( $uri ~ ^/api ) {
set $log_uri 1;
}
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/http_uri.log main if=$log_uri;
}
2
3
4
5
6
7
8
9
这种不使用 map 的方式可以支持正则表达式。
多个条件
上边的例子都是单项的条件,事实上还可以基于多个条件进行过滤。
使用 map 的方式配置:
map $http_user_agent $log_ua {
~*Googlebot 1;
~*Baiduspider 1;
default 0;
}
map $http_cookie $log_cookie {
~PHPSESSION 1;
default "";
}
map “$log_ua:$log_cookie” $logging {
“1:1” 1;
default 0;
}
server {
[…]
access_log /var/log/nginx/access.log main;
access_log /var/log/nginx/http_multi_conditions.log main if=$logging;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
使用 if 的方式进行过滤:
server {
[…]
set $logging 0;
set $logtmp "$log_ua$log_cookie"
if ( $logtmp = "11" ) {
set $logging 1;
}
access_log /var/log/nginx/access.log main if=$logging;
}
2
3
4
5
6
7
8
9
10
11
12
13
</div
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK