以前介紹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一整套組合拳的時區特性特別好用,可是在國內仍是統一時區吧。統一時區仍是再數據存儲前作調整,不然後期查詢會流淚的。