iT邦幫忙

2021 iThome 鐵人賽

DAY 21
2
Software Development

系統與服務雜談系列 第 21

分布式可觀測性 Structured Log

  • 分享至 

  • xImage
  •  

對於Log, 以往很多老專案, 傳產等等的軟體系統產出的Log, 很像下圖

Dec 14 06:41:08 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting!
    at com.myproject.module.MyProject.badMethod(MyProject.java:22)
    at com.myproject.module.MyProject.oneMoreMethod(MyProject.java:18)
    at com.myproject.module.MyProject.anotherMethod(MyProject.java:14)
    at com.myproject.module.MyProject.someMethod(MyProject.java:10)
    at com.myproject.module.MyProject.main(MyProject.java:6)

Dec 14 06:41:09 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting!
Dec 14 06:41:10 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting!
Dec 14 06:41:11 Exception in thread "main" java.lang.RuntimeException: Something has gone wrong, aborting!
    at com.myproject.module.MyProject.badMethod(MyProject.java:22)
    at com.myproject.module.MyProject.oneMoreMethod(MyProject.java:18)
    at com.myproject.module.MyProject.anotherMethod(MyProject.java:14)
    at com.myproject.module.MyProject.someMethod(MyProject.java:10)
    at com.myproject.module.MyProject.main(MyProject.java:6)

對於人類是很好閱讀, 但對於程式來收集並解析卻很不方便, 因為不知道每一行每一欄"固定"代表什麼.
也不能斷言收集到那一行就做一個完整的record.

因此在Log採集服務, 希望是採取Structured Log的結構來輸出.
常見的結構有JSON和KVP, 兩者對於人類閱讀性是很高的.
對於日誌解析與搜尋更是方便,
相對於format string來輸出成flat log來說, 後者還得費心的寫Regex來parsing.

# flat log, 通常都透過format把值塞進去
%d{yyyy-MM-dd HH:mm:ss.SSS} %level ${application_name} trace=%X{X-B3-TraceId},span=%X{X-B3-SpanId} <%t> %c{40} - %msg%n

這種格式用ELK的話, 就是透過Logstash的grok寫regex來解析, 轉換成structured log, 再送到Elasticsearch.
然後維護grok的regex是髒活, 又累又沒效率又沒產出價值.
不做regex轉換? 上一篇提到如果沒有透過解析出來的filed做索引, 而直接全文檢索,
恭喜你, 出事情找Log時應該慢到想罵人.
甚至也沒辦法透過Log中的時間來查找, 因為連時間都是要Regex來解析轉換的
用前幾篇的awk? 更會寫到想死吧!

JSON格式的Log就沒什麼好展示的, Kibana上看到的都是這類.
JSON格式基本上, 存的時候都是扁平的一行, 只是展示時會Pretty.

KVP則是通常長這樣Key=Value Key2=Value2, 也沒一定要用=或用space做銜接就是
通用格式則是Key Separator Value KVDelimiter
Separator可以是=:
KVDelimiter可以是space,,, \t之類的
Key限制上就是至少一個非數字字元, 允許_.$@
Value基本就是只要value中有Separator就要用" "包住

早期用Flat log是為了省空間, 因為JSON和KVP格式會大量重複出現Key, 以前量不大且是單機.
大多與Application在同一台機器上.
現在這點可以透過Compress壓縮來解決,
因此在現在的時空背景, 查詢與寫入效能反而是我們在意的點.

令一個缺點大概是, 用OS提供的像是tail,less,cat
大概就看到眼花了吧, 都擠成一行XD

但優點真的太多, 光是一整行就能方便用grep或awk來搜尋到完整的Log內容,
也方便從內容裡直接解析出一個時間值,
Key值本身就具備索引的屬性, 便於查詢跟分析,
其實也增加了事件描述語意的能力.

Go的生態圈有ZapLogrus提供了Structured Log的輸出

明日繼續從Metrics與Tracing來介紹.

---參考資料
JSON & KVP
Introducing Structured Logs
logfmt


上一篇
分布式可觀測性 Logging 淺談
下一篇
分布式可觀測性 Metrics 淺談
系列文
系統與服務雜談33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
wajika
iT邦新手 5 級 ‧ 2021-12-29 14:02:11

你的意思是 output format 改为 json?

wajika iT邦新手 5 級 ‧ 2021-12-29 14:02:35 檢舉

文章太短了,有点遗憾

雷N iT邦研究生 1 級 ‧ 2021-12-29 21:24:49 檢舉

也為必要改成json, KVP也能
只要有key:value這樣的結構就可

我要留言

立即登入留言