日志收集时的时间戳处理
Logstash在处理数据的时候,会自动生成一个字段@timestamp,默认该字段存储的是Logstash收到消息/事件(event)的时间。很多时候我们用ELK是处理日志的,日志里面一般都是有时间的。而且很多时候我们只关注日志里面的时间,而不关注Logstash收到这条日志的时间。这个时候,一种方法是再增加一个字段,用来存储日志里面的时间,这种很简单;另一种方法是使用日志中的时间替换掉@timestamp字段默认的时间。本文介绍第二种方法并总结一些关键知识点。
一、Nginx配置$time_local
以Logstash采集Nginx日志为例,格式如下:
log_format main '$remote_addr - [$time_local] "$request_method $uri $query_string" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time';
175.167.136.165 - [19/May/2020:17:44:03 +0800] "POST /upload -" 200 65 "https://static.cam.com/2020/comicfood/v3/index.html" "Mozilla/5.0 (Linux; Android 10; WLZ-AL10 Build/HUAWEIWLZ-AL10; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.64 Mobile Safari/537.36 androidapp.foodle" 0.487 0.224
@timestamp字段是内置的,和之前说的一样,时间是Logstash收到消息的时间,而且注意使用的是UTC时间
timestamp字段是我们解析规则里面定义的字段(字段名随便起,不能有特殊符号,比如@),该字段存储的是从日志里面解析出来的时间,注意这个时间格式完全是日志里面时间的格式。要注意我们使用的timestamp和系统内置的@timestamp不是同一个字段。
1、ISO8601形式以及时间戳转换覆盖
如上的日志格式时时在grok中可以这么写:
grok { match => { "message", "%{HTTPDATE:timestamp}"
}
2、时间转存覆盖@timestamp有两种写法可以供使用
date { match => ["timestamp", "dd/MMM/yyyy:HH:mm:ss Z"]
#timezone => "UTC" target => "@timestamp" }
上述配置的含义是,将time_field字段按照"dd/MMM/yyyy:HH:mm:ss Z"格式解析后存到target指定的字段end_time字段去。time_field必须是已经定义的字段,最常见的就是在grok里面解析出来的某个时间字段。时间格式可查看Date插件的文档。如果没有指定target,默认就是@timestamp字段,这就是为什么我们可以使用该插件来修改@timestamp字段值的原因。
或者是
date {
match => ["timestamp", "ISO8601"]
}
都可以实现ISO8601时间的匹配格式。
另外,timezone字段在某些场景下也非常重要,如果从时间的值里面解析不出来时区,而且我们也没有指定时区的话,程序就会认为我们的时间字段的时区就是系统所处时区。比如上面从timestamp转到@timestamp的时候,时间值里面没有时区,所以使用了系统的时区东八区。当然,我们可以使用该字段指定时区。
二、Nginx配置$time_iso8601 (新加字段方式)
log_format json '{"@timestamp":"$time_iso8601",' '"@version":"1",' '"host":"$clientRealIp",' '"size":$body_bytes_sent,' '"reponsetime":$request_time,' '"domain":"$host",' '"url":"$uri",' '"status":"$status"}';
获取到的日志通常为
{"@timestamp":"2018-06-26T15:39:56+08:00","@version":"1","host":"192.168.29.7","size":0,"reponsetime":0.000,"domain":"www.logstashtest.com","url":"/images/logo3.png","status":"304"}
时间格式:2018-06-26T15:39:56+08:00
此时logstash配置如下:
input { file { path => "/home/nginx/logs/logstash_iso_test_access.log" } } filter { json { source => "message" } grok { match => ["message","%{TIMESTAMP_ISO8601:isotime}"] } date { locale => "en" match => ["isotime", "ISO8601"] } # mutate { # remove_field => ["@timestamp"] # } } output { stdout { codec => "rubydebug" } }
此时访问nginx日志为:
{"@timestamp":"2018-06-26T15:45:43+08:00","@version":"1","host":"192.168.29.7","size":0,"reponsetime":0.000,"domain":"www.logstashtest.com","url":"/images/logo3.png","status":"304"}
logstash输出:
{
"@version" => "1",
"host" => "Sandos1",
"@timestamp" => 2018-06-26T07:45:43.000Z,
"message" => "192.168.29.7 - - [26/Jun/2018:15:45:43 +0800] \"GET /images/logo3.png HTTP/1.1\" 304 0 \"-\" \"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0\" \"-\" \"192.168.29.7\" \"0.000\"",
"request_time" => "26/Jun/2018:15:45:43 +0800",
"path" => "/home/nginx/logs/main_logstashtest_access.log"
}
附:时间匹配规则表