Fluent bit回顧
Log Agent - Fluent Bit 簡介
Log Agent - Fluent Bit 安裝與常見架構模式
Log Agent - Fluent Bit Service配置與內建 API
Log Agent - Fluent Bit Input元件 與 Tail淺談
Parser主要功能就是把從Input收到的非結構化資料轉換成Structured Log
主要的Parser類型有
[PARSER]
Name parser自定義名稱
Format parser類型名稱
Time_Key time的欄位名稱, 會將這欄位的值轉成log的時間戳記
Time_Format 使用strptime格式
JSON格是最簡單了, 本來就是Structured, Object的話都依訂有key,
如果有必要, 有欄位就是代表log time時, 需要特別指定Time_Key跟Time_Format
"{"logTime":"2021-10-12 18:31:01","message":"ithome"}"
Parser示範
[PARSER]
Name demoJson
Format json
Time_Key logTime
Time_Format %Y-%m-%d %H:%M:%S
Logfmt format 其實就是之前提過的KVP
一樣本來就是Structured
logTime=2021-10-12 18:31:01 message=ithome
[PARSER]
Name demologfmt
Format logfmt
這Regex Parser才是重點中的重點, 太多Log資料並非是Structured, 而是Flat Log.
我們需要用Regex來捕捉哪些內容是屬於哪些key/label
input元件讀進這一行, 給了parser
47.29.201.179 - - [28/Feb/2019:13:17:10 +0000] "GET /?p=1 HTTP/2.0" 200 5316 "https://domain1.com/?p=1" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36"
定義Regex如下
/^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")/
剖析結果
{
"remote": "47.29.201.179",
"host": "-",
"user": "-",
"method": "GET",
"path": "/?p=1",
"code": "200",
"size": "5316",
"referer": "https://domain1.com/?p=1",
"agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36"
}
我來慢慢說明那Regex
/
/ regexx /
來包裹regex(?<remote>[^ ]*)
(?<Name> regex pattern)
用pattern來捕捉內容塞給對應命名的key
[^ ]*
這regex pattern就是一直匹配不是空格的字元
[^ ]
^在[]內表示except後面的字, 後面接的是space\[(?<time>[^\]]*)\]
\[
跟\]
只是因為[]是特殊符號, 但這裡要表示就是[]這字, 就要透過\
做Escaping轉義(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?
(?<method>\S+)
和(?: +(?<path>[^\"]*?)(?: +\S*)?)?
\S
也是用來表示任意的非空白字元, 跟上面的[^ ]*一樣
(?: +)
, 這代表non-capturing groups, 就表示(?: )這裡面的字元不會被捕捉出來, 這裡面其實是 +
, 就是至少一個空格space
/?p=1
這裡/之前的那空格(?<path>[^\"]*?)
, 這就一直匹配不是"的字元, 並捕捉賦值給path
後面字串的剖析方式大同小異
另一個範例, Apache HTTP Server log
192.168.2.20 - - [29/Jul/2015:10:27:10 -0300] "GET /cgi-bin/try/ HTTP/1.0" 200 3395
[PARSER]
Name apache
Format regex
Regex ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z
Types code:integer size:integer
結果如下,
時間段29/Jul/2015:10:27:10 -0300
被Time_Format給解析成時間
以timestamp1438176430
呈現
Oct 12 23:55:23 nathan td-agent-bit[256618]: [0] demo: [1438176430.000000000, {"host"=>"192.168.2.20", "user"=>"-", "method"=>"GET", "path"=>"/cgi-bin/try/", "code"=>"200", "size"=>"3395"}]
成功的透過Regex Parser將flat log轉成Structured Log
官網其實還有提供LTSV, 但我沒用過,
還有提供一些Decorder, 這些日後有機會在分享
但Regex在Parser這裡真的非常非常非常地重要
---參考文件
strptime參考
Non-Capturing Groups
Fluentd - regexp
Rubular - Ruby regex editor
Calyptia - Regex
---新增自定義parser
[PARSER]
Name iislog
Format regex
Regex ^(?<time>[^ ]+ [^ ]+) (?<s_ip>[^ ]+) (?<cs_method>[^ ]+) (?<cs_uri_stem>[^ ]+) (?<cs_uri_query>[^ ]+) (?<s_port>[^ ]+) (?<cs_username>[^ ]+) (?<c_ip>[^ ]+) (?<user_agent>[^ ]+) (?<sc_status>[^ ]+) (?<sc_substatus>[^ ]+) (?<sc_win32_status>[^ ]+) (?<sc_bytes>[^ ]+) (?<cs_bytes>[^ ]+) (?<time_taken>[^ ]+)$
Time_Key time
Time_Format %Y-%m-%d %H:%M:%S
順便也新增一組filter, 用上modify功能, 動態加上一組key_value
[FILTER]
Name modify
match IIS_*
Add server serverid_1
看看結果, 這就是我要的XD