我无法解析以下 nginx 错误日志消息grok 调试器。我感觉我应该用一个愚蠢的技巧,但却不知道它是什么。
2015/03/20 23:35:52 [错误] 8#0:*10241823 测试“/www”存在性失败(2:没有此文件或目录)同时记录请求,客户端:201.45.203.78,服务器:$domain,请求:“GET /ritikapuri_”
以下是我目前的 Grok 模式:
(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER}: %{GREEDYDATA:errormessage} client: %{IP:client}
这种模式让我进入“服务器”部分,但我似乎无法解析其余部分,而且我也不清楚为什么。
如果我使用另一个 %{GREEDYDATA} 模式来获取日志的末尾,它有时不会解析与上述不匹配的日志并给我一个 _grokparsefailure。
最好的方法是使用 if 语句来捕获 nginx 中日志消息的不同变化吗?
我遵循的方法包括这个但无法让它们工作。
答案1
我使用@dr01的答案来使用通知格式改进nginx中错误日志的配方1.15
——这个答案将分离出HTTP版本和HTTP方法和请求。
(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER:threadid}\: \*%{NUMBER:connectionid} %{GREEDYDATA:message}, client: %{IP:client}, server: %{GREEDYDATA:server}, request: "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion}))", host: %{GREEDYDATA:host}
示例字符串
2015/03/20 23:35:52 [error] 8#0: *10241823 testing "/www" existence failed (2: No such file or directory) while logging request, client: 201.45.203.78, server: $domain, request: "GET /dsfadsfe HTTP/1.1", host: "localhost:8080"
输出自grok 调试器
{
"timestamp": [
[
"2015/03/20 23:35:52"
]
],
"severity": [
[
"error"
]
],
"pid": [
[
"8"
]
],
"threadid": [
[
"0"
]
],
"connectionid": [
[
"10241823"
]
],
"message": [
[
"testing "/www" existence failed (2: No such file or directory) while logging request"
]
],
"client": [
[
"201.45.203.78"
]
],
"server": [
[
"$domain"
]
],
"verb": [
[
"GET"
]
],
"request": [
[
"/dsfadsfe"
]
],
"httpversion": [
[
"1.1"
]
],
"host": [
[
""localhost:8080""
]
]
}
答案2
由于没有看到您尝试的模式不起作用,我无法评论它们为什么不起作用。正如您所说,您提供的模式与服务器匹配,我稍微修改了您的陈述,并在末尾添加了一些内容以捕捉其余部分:
(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER}: %{GREEDYDATA:errormessage},\ client: %{IP:client}, server: \$domain, request: \"%{WORD:method} %{URIPATH:path}\"
请注意,我在 GREEDYDATA 后面添加了一个逗号,因为您可能不希望在捕获的数据中出现逗号,并且我假设逗号将始终用在消息的客户端部分之前。我怀疑您在匹配 $domain 时遇到了问题,因为您需要在 $ 前面添加 \ 来转义它。
请注意,虽然这在 grok 调试器中有效,但我怀疑它在 logstash 中不起作用,您还需要转义所有空格,以便 logstash 能够很好地适应该模式(即将每个实例“ ”更改为“\ ”)
回复:最好的方法是使用 if 语句来捕获 nginx 中日志消息的不同变化吗?
我不太清楚你在问什么,但你可以在过滤器周围或过滤器的某些部分放置 if 语句,就像这样回答。如果您能找到标记标签的方法,也可以使用标签做同样的事情。从每行的处理能力来看,这两个选项可能是“最佳”的,因为我相信所涉及的工作量会比这样的工作量少回答因为每个事件都需要根据每个模式进行检查。您也可以编写一个非常复杂的模式,可以匹配每种不同的情况,但我认为这并不理想,因为模式会扩展到有如此多不同的潜在匹配,每次检查都需要很大的功率。
我希望这能有所帮助!
答案3
无论字段的值是什么,这个 grok 配方也有效server
:
(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER:threadid}\: \*%{NUMBER:connectionid} %{GREEDYDATA:errormessage}, client: %{IP:client}, server: %{GREEDYDATA:server}, request: %{GREEDYDATA:request}
答案4
Grok 错误模式,增加了可选上游和引荐来源字段。测试nginx:1.17.3
(?<timestamp>%{YEAR}[./]%{MONTHNUM}[./]%{MONTHDAY} %{TIME}) \[%{LOGLEVEL:severity}\] %{POSINT:pid}#%{NUMBER:threadid}\: \*%{NUMBER:connectionid} %{GREEDYDATA:message}, client: %{IP:client}, server: %{GREEDYDATA:server}, request: "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion}))"(, upstream: "%{GREEDYDATA:upstream}")?, host: "%{DATA:host}"(, referrer: "%{GREEDYDATA:referrer}")?