使用转义的“[”,“(”和“)”字符的Grok正则表达式问题

3
新手弹性搜索 - 使用新的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 debugger和https://grokdebug.herokuapp.com/都适用于这个模式。

当我将这个正则表达式放入logstash中时,它无法识别行中的msgnum (451)部分,因为在msgnum字段周围有转义的圆括号\( 和 \),结果无法将该行识别为合法字符串。

我是否转义了某些内容?这是一个bug吗?

更新于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设置,现在正则表达式匹配传入的日志流,这正是我想要的。谢谢!
1个回答

4

细节决定成败,错误并不是一开始就显现出来的。Grok调试工具失败的原因是因为您使用了DATE模式。这个模式的解析方式如下:

DATE_US %{MONTHNUM}[/-]%{MONTHDAY}[/-]%{YEAR}
DATE_EU %{MONTHDAY}[./-]%{MONTHNUM}[./-]%{YEAR}
MONTHNUM<\/code>和MONTHDAY<\/code>都是两位数字模式,实际上它们匹配的是年份中的15。这就是为什么该模式不起作用的原因,因为\[%{DATE}<\/code>实际上没有匹配(缺少了20)。为什么模式.%{DATE}<\/code>还能工作呢?因为你并没有用点来匹配[<\/code>,而是用点来匹配年份中的0<\/code>。

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

\[(?<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}

这将返回以下输出:
{
  "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"
}

2
绝对史诗级的捕捉! - Tim Kuehn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接