iT邦幫忙

2021 iThome 鐵人賽

DAY 28
1
Software Development

系統與服務雜談系列 第 28

Log Agent - Fluent Bit Parser元件

  • 分享至 

  • xImage
  •  

Fluent bit回顧
Log Agent - Fluent Bit 簡介
Log Agent - Fluent Bit 安裝與常見架構模式
Log Agent - Fluent Bit Service配置與內建 API
Log Agent - Fluent Bit Input元件 與 Tail淺談

Parsers

Parser主要功能就是把從Input收到的非結構化資料轉換成Structured Log

主要的Parser類型有

  • JSON
  • Regular Expression
  • Logfmt
  • Decorders
  • LTSV
[PARSER]
    Name parser自定義名稱
    Format parser類型名稱
    Time_Key    time的欄位名稱, 會將這欄位的值轉成log的時間戳記
    Time_Format 使用strptime格式

JSON Parser

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 Parser

Logfmt format 其實就是之前提過的KVP
一樣本來就是Structured

logTime=2021-10-12 18:31:01 message=ithome
[PARSER]    
    Name        demologfmt    
    Format      logfmt

Regular Expression Parser

這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
      • (?[^ ]) 把[^] 匹配到的字串都賦值給remote
    • [^ ]*這regex pattern就是一直匹配不是空格的字元
      • [^ ] ^在[]內表示except後面的字, 後面接的是space
  • \[(?<time>[^\]]*)\]
    • \[\]只是因為[]是特殊符號, 但這裡要表示就是[]這字, 就要透過\做Escaping轉義
  • (?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?
    • 拆兩段(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?
      • (?\S+)的\S也是用來表示任意的非空白字元, 跟上面的[^ ]*一樣
        • 用來捕捉到GET
      • (?: +(?[^"]?)(?: +\S)?)?
        • 先講解(?: +) , 這代表non-capturing groups, 就表示(?: )這裡面的字元不會被捕捉出來, 這裡面其實是 +, 就是至少一個空格space
          • 用來比對 /?p=1這裡/之前的那空格
        • 再來(?<path>[^\"]*?), 這就一直匹配不是"的字元, 並捕捉賦值給path
          • 用來捕捉到/?p=1
        • 最後是(?: +\S*)?
          • ()? 表示前面匹配到的字元出現0-1次
          • (?: +\S*)
            • 跟之前一樣有non-capturing groups匹配空格,然後持續匹配任意個非空格字元

https://ithelp.ithome.com.tw/upload/images/20211012/20104930uDM6TnZss4.png
後面字串的剖析方式大同小異

另一個範例, 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

IIS Log Parser

rubular
Regex key的命名規則

[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
https://ithelp.ithome.com.tw/upload/images/20220311/20104930bgI0NkiaZH.png


上一篇
Log Agent - Fluent Bit Input元件 與 Tail淺談
下一篇
Log Agent - Fluent Bit Multiline Parsing
系列文
系統與服務雜談33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
json_liang
iT邦研究生 4 級 ‧ 2021-10-13 12:34:22

感謝分享 實用好工具

我要留言

立即登入留言