以前介绍filter date插件时就谈到时区问题,可是没有说明白。最近在使用range查询时间范围内的数据时出现了数据量不一致的状况。特意了解了下ELK Stack中关于时区的问题。html
使用kibana discovery界面搜索时,数据量一致。使用curl 搜索时少了数据。node
再说时间问题前,简单了解下UTC:nginx
UTC(Universal Time Coordinated) 叫作世界统一时间,中国大陆和 UTC 的时差是 + 8 ,也就是 UTC+8。
UTC时区参考文档ruby
ELK Stack集群各服务对时间处理的介绍:
logstash :根据所在机器的时区并对date类型数据进行处理,整理成UTC时间
elastic :全部date类型数据都存储为GMT(毫秒级)
kibana :根据kibana配置的时区,从elastic取出的timestamp时间转换为相应时区的时间。curl
logstash处理后以UTC时间存储进elastic,kibana取出来后,在恢复成相应时区的时间。由于我机器都是CST的时间,因此使用kibana搜索没有问题,可是curl命令不会对所取出来的时间进行时区转换,因此就少了8小时数据。测试
logstash 过滤字段信息时,删除或分开匹配时间和时区信息,timestamp
只匹配具体时间,timezone
则匹配+0800
这样的时区信息,并同时定义timezone为UTC,这样从根本上就获得原始的时间。url
UTC时间的示例:插件
$ bin/logstash -f text.conf [26/Mar/2019:00:00:08 +0800] #这里以nginx日志中的时间为例 { "timestamp" => "26/Mar/2019:00:00:08", "message" => "[26/Mar/2019:00:00:08 +0800]", "@timestamp" => 2019-03-26T00:00:08.000Z, #@timestamp的时间和输入的时间一致 "@version" => "1", "timezone" => "+0800", "host" => "node2007" } $ cat text.conf input { stdin {} } filter { grok { match => { "message" => "\[%{NOTSPACE:timestamp} %{INT:timezone}\]" } } date { match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss" ] timezone => "UTC" #没法从timestamp中提取时区。设置时区为UTC时间,忽略系统时区,若是date插件中的match匹配到了时区,则此处的时区不生效。因此在grok插件中将timezone和timestamp分隔开 } } output { stdout{ codec => rubydebug } }
正常时间处理:debug
$ bin/logstash -f text.conf [26/Mar/2019:00:00:08 +0800] { "@version" => "1", "@timestamp" => 2019-03-25T16:00:08.000Z, #转换成UTC时间,减小8小时, "message" => "[26/Mar/2019:00:00:08 +0800]", "host" => "node2007", "timestamp" => "26/Mar/2019:00:00:08 +0800" } $ cat text.conf input { stdin {} } filter { grok { match => { "message" => "\[%{HTTPDATE:timestamp}\]" } } date { match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ] timezone => "UTC" } } output { stdout{ codec => rubydebug } }
系统日志中不带有时区信息,则能够直接在配置文件中指定timezone => "UTC"
便可。无须要作匹配工做。日志
匹配到时区时间没有关系,能够在过滤时,在把时间补回来。
... date { match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ] target => "time" } ruby { code => "event.set('timestamp', event.get('time').time.localtime + 8*60*60)" #处理时将logstash自动减小的时间在给加回来 } ruby { code => "event.set('@timestamp',event.get('timestamp'))" } ...
以上代码通过我测试,能够正常使用。这里使用ruby插件,我不懂,time -> timestamp -> @timestamp须要经由两个变量才能最后赋值给@timestamp,为何不能直接使用@timestamp处理并赋值,若是有懂得的人,还请留言告知。
对时间进行处理后,咱们可使用curl命令随意进行查询啦,可是使用kibana时,还须要设置一下默认的时区: Management -> kibana(高级设置) -> Timezone for date formatting 并选择UTC时间展现。
总结:
ELK Stack一整套组合拳的时区特性特别好用,可是在国内仍是统一时区吧。统一时区仍是再数据存储前作调整,不然后期查询会流泪的。