我在调试问题时遇到了困难,我认为它可能有两个方面——两个独立程序中的问题。
主要问题是我正在将 nginx 记录到 Ubuntu 14.04 上的 syslog 中,如下所示:
access_log syslog:server=unix:/dev/log,tag=nginx,facility=local7,severity=info combined
我希望能够过滤标记为 nginx 的消息,但是没有那么幸运。
filter nginx { facility(local7) and tags("nginx") }
将 and 改为 or 即可,或者直接删除 tags 部分,因为 facility 过滤器可以正常工作。但是 tags 过滤器不行。
所以,我想使用记录器进行测试并设置一个基本测试:
template nginx { template("timestamp=${ISODATE} host=${HOST} tags=${TAGS} msgheader=${MSGHDR} ${MSG}\n"); template-escape(no); };
filter nginx { tags("nginx"); };
destination nginx { file("/tmp/nginx.log" template(nginx)); };
log { source(s_net); filter(nginx); destination(nginx); };
--
$ logger -n localhost -P 10001 -t nginx -p local7.info -u /tmp/ignored testing 123
我有一个源 s_net,它监听端口 10001 上的 UDP 以进行此测试。使用记录器,我通过 UDP 记录到该端口,使用 local7 设施和信息严重性标记“nginx”,同样,过滤不起作用。删除过滤器约束可让消息传递到目的地,就像直接使用 nginx 一样。标签不起作用。
此外,标签不会出现在 $TAGS 宏中,而是出现在 $MSGHDR 宏中。
笔记:/tmp/ignored 是 logger < 2.0.2 中的一个解决方法,如果你不提供套接字,它根本不会写入 TCP/UDP 端口,因此提供一个虚拟标志可以让它工作
看来即使使用记录器,我也无法过滤传入的标签。
我对 syslog(尤其是 syslog-ng)还比较陌生,所以也许我遗漏了什么?文档似乎很少,但这看起来像是一个非常简单的用例。有人发现有什么特别错误吗?还是我误解了标签的用途?
答案1
nginx 配置参数引用的 RFC3164 中定义的 TAG 字段与 Syslog-ng 内部使用的标签过滤器存在差异。
您可以在 Nginx 中定义的 TAG 字段被解释为正在记录当前消息的程序或进程。它位于 syslog 数据包的 MSG 部分中,并以第一个非字母数字字符终止。此后的所有内容都将用作实际消息(RFC3164#section-4.1.3)。
当你使用 tcpdump 嗅探系统日志流量时,你会看到:
tcpdump -A -vvv -s0 -n -i venet0 port 514
这是一个来自 NGINX 的示例,其配置如下:
15:25:16.477717 IP (tos 0x0, ttl 63, id 22206, offset 0, flags [DF], proto UDP (17), length 454) loadbalancer.example.com.45470 > log.example.com.514: [udp sum ok] SYSLOG, length: 426
Facility local6 (22), Severity notice (5)
Msg: Mar 10 15:25:16 loadbalancer.example.com nginx_access: "[10/Mar/2017:15:25:16 +0100]" "NO-CACHE" "app.example.com:80" "0.032" "302" "331" "10.235.121.191" "sub.example.com" "GET /location/?parameter=value1 HTTP/1.1" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Win64; x64; Trident/7.0; .NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E; Tablet PC 2.0)"
我有时会使用 nginx 的 TAG 字段来区分不同的日志文件:
access_log /var/log/nginx/www.example.com.ssl_access_log proxy;
error_log /var/log/nginx/www.example.com.ssl_error_log warn;
access_log syslog:server=10.0.80.110,facility=local6,tag=nginx_access,severity=notice proxy;
error_log syslog:server=10.0.80.110,facility=local6,tag=nginx_error,severity=error warn;
然后,在接收 syslog-ng 服务器上,我可以对传入的消息进行排序,或者将它们转储到一个大文件中:
source s_net { udp(); };
filter f_prg_nginx_access{ program(nginx_access); };
filter f_prg_nginx_error{ program(nginx_error); };
destination d_lb_access { file("/var/log/lb_access.log" perm(0640));};
destination d_lb_error { file("/var/log/lb_error.log" perm(0640)); };
log { source(s_net); filter(f_prg_nginx_access); destination(d_lb_access); };
log { source(s_net); filter(f_prg_nginx_error); destination(d_lb_error); };
正如 Robert Fekete 所提到的,Syslog-ng 的标签过滤是另一种内部标记到达特定端口或匹配模式的消息的方法。此外,[2] 表示,标记是 syslog-ng 中对消息进行排序的最快方法,但标签仅在本地可用,不会通过网络发送。
[1]https://www.nginx.com/resources/admin-guide/logging-and-monitoring/ [2]https://www.balabit.com/sites/default/files/documents/syslog-ng-ose-3.6-guides/en/syslog-ng-ose-v3.6-guide-admin/html/tagging-messages.html
答案2
syslog-ng 中的标签是内部标签,您可以将其明确添加到消息中(例如,在源处),或从消息中解析。
我不知道记录器中的 nginx 标签或 access_log 配置如何影响消息本身,但我猜测 syslog-ng 不会解析它。
在没有看到示例消息的情况下,我可以建议针对该问题采取以下可能的解决方法:
- 如果设置了消息的 PROGRAM 字段,则可以根据该字段而不是标签进行过滤。
- 您提到标签出现在 MSGHDR 宏中。您还可以使用 match() 过滤器对其进行过滤,例如:filter demo_filter { match("nginx" value("MSGHDR")) };
- 将 nginx 消息发送到日志服务器的单独端口,并在日志服务器上配置源以仅在此端口上接收消息。 syslog-ng 将自动为从源收到的每条消息添加标签(请参阅http://www.balabit.com/sites/default/files/documents/syslog-ng-ose-3.6-guides/en/syslog-ng-ose-v3.6-guide-admin/html/tagging-messages.html)
高血压
问候,
罗伯特