對於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的生態圈有Zap與Logrus提供了Structured Log的輸出
明日繼續從Metrics與Tracing來介紹.
---參考資料
JSON & KVP
Introducing Structured Logs
logfmt
你的意思是 output format 改为 json?
文章太短了,有点遗憾
也為必要改成json, KVP也能
只要有key:value這樣的結構就可