从部分日期时间字段创建新字段

Create new fields from parts of datetime field

我有一个 logstash 管道,它从 apache 日志条目中提取日期并将其保存在新字段中:

date {
  match => [ "timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
  target => "@apache_timestamp"
}

对于某些特定的报告,我还希望能够将此日期的部分内容提取到单独的字段中。

我尝试在日志中的新日期字段上使用 date 插件:

date {
  match => ["@apache_timestamp" , "dd/MMM/yyyy:HH:mm:ss Z" ]
  add_field => {"[hourOfDay]" => "%{+HH}"}
  add_field => {"[dayOfWeek]" => "%{+EEE}"}
  add_field => {"[weekOfYear]" => "%{+ww}"}
  add_field => {"[monthName]" => "%{+MMMM}"}
  add_field => {"[year]" => "%{+yyyy}"}
}

但它似乎没有添加任何新字段。

我也试过直接在消息上使用 grok 插件:

grok {
  match => { "message" => ["%{HTTPDATE}"] }
  add_field => {"[hourOfDay]" => "%{HOUR}"}
  add_field => {"[monthName]" => "%{MONTH}"}
  add_field => {"[year]" => "%{YEAR}"}
}

这会添加字段,但它们具有文字值 %{HOUR}%{MONTH} 等...

如何从 Apache 时间戳中提取 "Day of week" 和 "week of year" 等字段?

(我能够使用 Kibana 的脚本字段提取我需要的值,但它们看起来相当慢,而且 Kibana 无法查询脚本字段,因此这不是一个很好的解决方案。)

使用 Logstash 6.0

我不知道你的具体时间格式,所以我用 google 搜索了一个 apache 时间戳,发现了这个:

[Wed Oct 11 14:32:52 2000]

我去过这个地方:
http://grokconstructor.appspot.com/do/match#result
并使用了这个 grok 模式:

%{DAY:day} %{MONTH:month} %{NUMBER:year} %{NUMBER:hour}:%{NUMBER:minute}:%{NUMBER:second} %{NUMBER:millisecond}

使用 grok 匹配字段应该会在您的记录中生成新字段,因此不需要 add_field。请记住,grok 模式匹配在特殊字符周围可能会很棘手,这就是我试图将括号排除在外的原因,它对我有用。
也不要忘记,测试站点特别要求不要使用引号,但您仍然需要在配置文件中使用引号。

对于我得到的线条,我需要使用这个 grok 表达式:

grok {
  match => { "message" => ["^.*%{MONTHDAY:dayOfMonth}\/%{MONTH:monthName}\/%{YEAR:year}:(?!<[0-9])%{HOUR:hourOfDay}:%{MINUTE}(?::%{SECOND})(?![0-9]) %{INT:utcOffset}.*$"] }
}

使用此日志行:

192.168.0.1 - - [01/Jan/2017:00:00:00 -0500] "GET /some-image-file.png HTTP/1.1" 200 13281 "-" "MobileSafari/602.0 CFNetwork/808.2.13 Darwin/16.3.0" "-" "-"

我可以像这样提取字段:

monthName   Jan
year    2017
hourOfDay   00
dayOfMonth  1
utcOffset   -0500

我仍然无法获得 DayOfWeek 字段(星期日、星期一、星期二等...),但现在这可能已经足够了。


编辑

我能够获得星期几和一年中的星期几,但我需要在 Ruby 中完成:

ruby {
    code => 'event.set("dayOfWeek", Time.parse(event.get("@apache_timestamp").to_s).strftime("%A"))'
}
ruby {
    code => 'event.set("weekOfYear", Time.parse(event.get("@apache_timestamp").to_s).strftime("%W"))'
}

仅供参考:

语法如下:

add_field => {"[dayOfWeek]" => "%{+EEE}"}

似乎只能@timestamp上工作。我不认为有任何其他方法可以在其他日期时间字段(例如我的 @apache_timestamp)上使用该语法,因此丑陋的 Ruby 解决方案。