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"
}
附:時間匹配規則表