具有转义“[”、“(”和“)”字符问题的 Grok 正则表达式

Grok regex with escaped “[“, “(“, and “)” chars problems

这里是 Elastic 新手 - 使用新的 5.5 安装。我的日志行如下所示:

[2015/10/01@19:48:22.785-0400] P-4780 T-2208 I DBUTIL : (451) prostrct create session begin for timk519 on CON:.

我有以下正则表达式:

\[%{DATE:date}@%{TIME:time}-(?<gmtoffset>\d{4})\]\s*(?<procid>P-[0-9]+)\s*(?<threadid>T-[0-9]+)\s*(?<msgtype>[ifIF])\s*(?<processtype>[a-zA-Z]+)\s*(?<usernumber>[0-9]+|[:])\s*\((?<msgnum>[0-9]+|[\-]+)\)\s*%{GREEDYDATA:message}

当我在 kibana grok 调试器中尝试它时,它不起作用并且出现以下错误:

GrokDebugger: [parse_exception] [pattern_definitions] property isn't a map, but of type [java.lang.String], with { header={ processor_type="grok" & property_name="pattern_definitions" } }

这似乎是由于行首的 \[。如果我用句点“.”替换前导 \[我明白了

.%{DATE:date}@%{TIME:time}-(?<gmtoffset>\d{4})\]\s*(?<procid>P-[0-9]+)\s*(?<threadid>T-[0-9]+)\s*(?<msgtype>[ifIF])\s*(?<processtype>[a-zA-Z]+)\s*(?<usernumber>[0-9]+|[:])\s*\((?<msgnum>[0-9]+|[\-]+)\)\s*%{GREEDYDATA:message}

grok 调试器和 https://grokdebug.herokuapp.com/ 非常适合这种模式。

当我将此正则表达式放入 logstash 时,它无法识别该行的 msgnum (451) 部分,因为转义了 parens \( 和 \)在 msgnum 字段周围,因此无法将该行识别为合法字符串。

我是不是转义不正确?这是一个错误吗?

更新 2017-07-21

我通过将 ( 和 ) 放在 [(] 和 [)] 中来解决转义问题。我还没有找到解决匹配前导 [ 的方法。

更新 2017-07-24

下面的答案是一个史诗般的收获,我用它来创建以下自定义模式:

DBTIME %{TIME}[-+]\d{4}
DBTIMESTAMP %{YEAR}/%{MONTHNUM}/%{MONTHDAY}@%{DBTIME}

我已经在我的 grok 语句中实现了,如下所示:

\[%{DBTIMESTAMP:dbdatetime}\]\s*%{PROCESSID:processid}\s*%{DBTHREADID:threadid}\s*%{DBMSGTYPE:msgtype}\s*%{PROCESSTYPE:processtype}?\s*%{USERNUMBER:usernumber}?\s*:\s*[(]%{MSGNUMBER:msgnumber}[)].\s*%{GREEDYDATA:eventmessage}\s*\r

然后我使用日期过滤器将 dbdatetime 转换为 @timestamp 设置,现在正则表达式匹配传入的日志流,这正是我想要的。谢谢!

细节决定成败,错误一开始并不明显。 Grok 调试器失败的原因是因为您使用了 DATE 模式。此模式解析如下:

DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}
DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}

MONTHNUMMONTHDAY 都是 2 位数字模式,这实际上意味着它们与您所在年份的 15 匹配。这就是模式不起作用的原因,因为 \[%{DATE} 实际上不匹配(它缺少 20)。为什么模式 .%{DATE} 很难工作?因为您没有将 [ 与点匹配,所以您匹配的是年份的 0

如何解决这个问题?使用自定义模式来匹配日期。像这样的东西有效:

\[(?<date>%{YEAR}/%{MONTHNUM}/%{MONTHDAY})@%{TIME:time}-(?<gmtoffset>\d{4})\]\s*(?<procid>P-[0-9]+)\s*(?<threadid>T-[0-9]+)\s*(?<msgtype>[ifIF])\s*(?<processtype>[a-zA-Z]+)\s*(?<usernumber>[0-9]+|[:])\s*\((?<msgnum>[0-9]+|[\-]+)\)\s*%{GREEDYDATA:message}

这将return以下输出:

{
  "date": "2015/10/01",
  "msgnum": "451",
  "procid": "P-4780",
  "processtype": "DBUTIL",
  "message": "prostrct create session begin for timk519 on CON:.",
  "threadid": "T-2208",
  "usernumber": ":",
  "gmtoffset": "0400",
  "time": "19:48:22.785",
  "msgtype": "I"
}