預設 Elasticsearch 本身 @timestamp 是以收到 event 的時間而定,而圖表呈現的時間又是以 @timestamp 為主,所以通常跟實際 Log 的時間會有差異,這時候就必須透過 Logstash 處理這一段的 timestamp。
一般來說沒處理過的會長這樣:
{
"_index": "logstash-2019.07.04",
"_type": "doc",
"_id": "aiq2vWsBcSH-g8aKx3Hv",
"_version": 1,
"_score": null,
"_source": {
"httpversion": "1.1",
"@timestamp": "2019-07-04T15:59:59.892Z",
"timestamp": "04/Jul/2019:23:59:58 +0800"
}
}
- @timestamp 是 elasticsearch / logstash 收到 log 的時間 (並非實際 log 的時間)
- timestamp 是用 gork 切出來的 log date filed。
實際上應該要以 timestamp 為主才對 (實際 log 時間),所以必須透過寫 Logstash filter 把 @timestamp 換掉。
拿 Apache / Nginx 的 access.log 為範例,用 date 這個 plugin 來達成:
filter {
grok {
match => { "message" => "^%{NGINX_ACCESSLOG_COMBINED}$" }
}
date {
locale => "en"
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
remove_field => ["timestamp"]
}
}
- locale 是用來判斷時區,實際上與系統的時區有關 (ex. LANG=en_US.UTF-8)
- match 判斷 timestamp 這個 filed 的來源格式為 “dd/MMM/yyyy:HH:mm:ss Z” (ex. 04/Jul/2019:23:59:58 +0800)
- remove_field 取代 @timestamp 之後當然要移除原本的 timestamp filed。
處理完後就會變這樣:
{
"_index": "logstash-2019.07.04",
"_type": "doc",
"_id": "aiq2vWsBcSH-g8aKx3Hv",
"_version": 1,
"_score": null,
"_source": {
"httpversion": "1.1",
"@timestamp": "2019-07-04T23:59:58.892Z"
}
}
最後呈現的 timestamp 就會是真實 log time。