I'm reading events from an API that contains a field 'Timestamp' with a timestamp in the following format. The milliseconds are not always present or occur in 1, 2 or 3 digit resolution:
They have to be converted to epoch in microseconds. Therefore, I use this filter in Logstash:
# extract the year, month, day and time including optional microseconds from the field Timestamp
grok {
match => [ "Timestamp", "%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day}T%{TIME:time}" ]
}
# create a temporary field with a consistent formatted datetime
mutate {
add_field => {
"[@metadata][timestamp_temp1]" => "%{year}-%{month}-%{day} %{time}"
}
}
# create a date object that we can parse later with a ruby filter
date {
locale => "en"
timezone => "UTC"
match => ["[@metadata][timestamp_temp1]", "ISO8601", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S", "yyyy-MM-dd HH:mm:ss.SS", "yyyy-MM-dd HH:mm:ss.SSS"]
target => "[@metadata][timestamp_temp2]"
remove_field => ["timestamp", "year", "month", "day", "time"]
}
# convert the dateobject to an epoch in microseconds
ruby {
code => "event.set('[@metadata][epoch_micro]', (1000000*event.get('[@metadata][timestamp_temp2]').to_f).round(0))"
}
Although the solution works, it took me a while to figure it out, and it feels a bit complicated. Is this the proper way to deal with dates or is there a more minimalistic solution?
Thanks Rohan. I took the TIMESTAMP_ISO8601 of your solution and was able to minimize my config.
Note that a timestamp in MICROseconds epoch cannot be done by casting to int as you did, you have to cast to float and round the result, or you will loose some precision.
The final solution is now:
# from the Timestamp field, extract the date into mydate
grok {
match => {"Timestamp"=>"%{TIMESTAMP_ISO8601:mydate}"}
}
# from the mydate field, contruct a date and store it in [@metadata][timestamp_temp]
date {
locale => "en"
timezone => "UTC"
match => ["mydate", "ISO8601", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S", "yyyy-MM-dd HH:mm:ss.SS", "yyyy-MM-dd HH:mm:ss.SSS"]
target => "[@metadata][timestamp_temp]"
}
# calculate the micro second epoch from the timestamp_temp field and store it in [@metadata][epoch_event]
ruby {
code => "event.set('[@metadata][epoch_event]', (1000000*event.get('[@metadata][timestamp_temp]').to_f).round(0))"
}
Apache, Apache Lucene, Apache Hadoop, Hadoop, HDFS and the yellow elephant
logo are trademarks of the
Apache Software Foundation
in the United States and/or other countries.