ELK 筆記 – 2 – Logstash grok 淺嚐
前言
在前篇我們成功跑起了一個基本的 ELK 架構。
這裡我們要調整 pipeline config,運用 grok 來解析、處理不同格式的訊息。
原本傳過來的 log 資訊只是一個字串,ELK 最終也只是把他單純存在 Elasticsearch 資料的 message 欄位。
但可能這個字串裡面有一些進一步的細節,例如 時間、 Level、其他錯誤資訊等。
如果這個字串有固定的格式 pattern,那就可以把這個 pattern 寫在 grok 這邊, Logstash 可以按照 pattern 把這些細節解析出來,然後存到 Elasticserach 內。
參考資料
訊息格式
現在我們先假設從 Web 端發過來的日誌訊息格式以及範例如下
格式: [時間][Level][檔名][行數] 訊息文字 範例: [2020-01-01 12:34:56,789][ERROR][login.py][123] something error on login
grok 寫法
grok 預設已經寫好很多現成 pattern ,請參考 grok-patterns
可以看到現成的 pattern 對應的 REGEX 為何,有符合的,就直接用 %{Pattern 名稱},而實在沒有現成的,也可以用 REGEX 自己寫。
唯一需要注意的,就是在使用 WORD、NOTSPACE、DATA、GREEDYDATA、QUOTEDSTRING 這幾個 pattern 去解析字串時,應留意他們各自適用的範圍,實在不確定,就應參考正規式文件,或者乾脆貼到 regex 線上測試器 去試試看。
好比說 WORD 是 \b\w+\b,\w 應該是 數字、字母、底線,所以如果有中文恐怕就不行了,這時候說不定 NOTSPACE 的 \S+ 才是你要的解。 (當然,鼓勵你到 regex 線上測試器 實測一下,說不定我說錯了呢?)
此外,不要急著開始悶頭解析,也許你要解析的系統 log 已經有現成 pattern 了,例如 apache 、 redis 甚至部分 Aws 服務的 log,請參考 patterns 資料夾,點擊進去後就可以看到很多現有系統的 log ,看看有沒有你要的?
pattern 撰寫討論
以上面為例,第一項 [2020-01-01 12:34:56,789] 資訊,包含了 中括號 以及 2020-01-01 12:34:56,789
其中因為中括號( 也就是『[』、『]』 )在 REGEX 是有意義的,所以記得要用倒斜線跳脫,而 2020-01-01 12:34:56,789 屬於已有的時間格式,因此用現成 pattern %{TIMESTAMP_ISO8601:asctime} 即可。這裏冒號前半的 TIMESTAMP_ISO8601 是現成 pattern 名稱,冒號後的 asctime 則是要把此值轉換存到什麼欄位。
最後我們得到這樣的 pattern
\[%{TIMESTAMP_ISO8601:asctime}\]\[%{LOGLEVEL:levelname}\]\[%{NOTSPACE:filename}\]\[%{NUMBER:lineno}\]%{SPACE}%{GREEDYDATA:message_description}
語法測試
你可以把你的格式跟範例貼在這個 線上 grok 語法測試器,就知道你的語法是否正確。上面的範例,可以得到如下圖的解析結果。
Logstash pipeline 設定
綜上,調整 pipeline config 如下,中間新增了 filter 的部分,以及其內 grok pattern
input { tcp { port => 5055 codec => plain { charset => "UTF-8" } } } filter { grok { match => [ "message", "\[%{TIMESTAMP_ISO8601:asctime}\]\[%{LOGLEVEL:levelname}\]\[%{NOTSPACE:filename}\]\[%{NUMBER:lineno}\]%{SPACE}%{GREEDYDATA:message_description}" ] } } output { elasticsearch { hosts => "http://host.docker.internal:9200" } }
從 Kibana 查看解析結果
發送上面的範例訊息給 Logstash,之後到 Kibana 可以看到, 訊息已經被順利解析並儲存為不同欄位,如下圖範例
有黃色驚嘆號?
至於那個黃色驚嘆號,滑鼠移過去可以看到提示
大致就是因為出現新的欄位。只要按照提示,到 Management -> Index Pattern 內, Refresh 一次 field,就可以了,如下步驟
Leave a Reply