2021年7月8日 星期四

Splunk 小基礎

覺得好久沒有寫部落格了 XD。今年工作上遇到許多意外,比原本預期的還要忙上許多;而且有不少想寫成文章的主題,其實都得思考到底能不能寫 XD;不過最重要的原因大概是因為開始在用 Notion 來做紀錄了吧。本來寫部落格的用意,就是用來紀錄遇到過的經驗,避免自己忘記了就消失了。不過在開始用 Notion 以後,總想說先把摘要紀錄在 Notion 上,之後再整理成文章,然後就....就沒有然後了,那些東西就一直維持摘要的樣子存在 Notion 上了 😂。

因為今天學到了一點關於 Splunk 的蠢事,所以來寫篇小文章,順便讓部落格添添火 (?

剛進公司的時候,第一次開始使用 Splunk,不過那時時程很趕,沒什麼時間好好研讀 Splunk 的文件,大概都是去參考其他同事們過去的大作,然後搬過來做點調整,會跑出想看到的東西就好了(亦即 Stackoverflow 工程師 😆)。因為沒有讀過文件,所以對於那些 query 背後行為的想像方式錯了,導致結果就是寫出來的 query 雖然是會動,但效能很差要跑很久 😓。只不過因為 Splunk 上的東西也都是我們自己看而已,而且那時也沒有什麼比較對象,就也沒發現那個速度並不是正常現象。

以這個 query 作為例子:

index="prod" source="ApplicationLog.aaa.bbb.ccc.api" "org.zalando.logbook.Logbook"
  | spath input=log 
  | rex field=message " uri=(?<url>.*?) " 
  | search url="*/api/xyz/v1/*"
  | eval count=1 
  | timechart span=5m per_second(count)

這個 query 的目的就是想找出由 xyz 這個 API 專案輸出的 access log。因為我們的 API access log 是讓 Logbook 輸出,所以會篩選 "org.zalando.logbook.Logbook"。本來我自己想像的是說,把 filter 放在第一個步驟時,Splunk 應該也是要做一樣的事情:要分析出句子裡哪裡有 "*/api/xyz/v1/*",所以應該也一樣會做字串拆解,不過它拆解完應該會需要每個拆出來的 key 都找一遍,而我直接告訴它我要找的字串會落在 message 這個 key 裡,應該比它每個 key 都翻一遍來得快。於是我就一直都是這麼寫的,然後就...到現在才發現原來這個思考邏輯完全是錯的 😓。

最重要的問題是在於,其實 Splunk 是一個 index engine,它不會用這麼原始的方式在搜尋字串,它會去做 segment。做了 segment 之後,句子會被拆解掉才被 index,所以其實搜尋時它並不會即時拆解字串,反而是刻意要求它去執行字串拆解會浪費更多無意義的時間...。比較好的方式是盡可能在最開始就把所有的 filter 都放進去,讓 Splunk 可以透過 segment 篩掉更多的 log,以讓後續的步驟處理的 log 量越少越好。

以上面的例子來說 ,要達到同樣的結果,其實換成下面這樣,執行速度最起碼提昇 10 倍以上吧。

index="prod" source="ApplicationLog.aaa.bbb.ccc.api" "org.zalando.logbook.Logbook" "*/api/xyz/v1/*"
  | eval count=1 
  | timechart span=5m per_second(count)

是個傻傻地耍蠢的故事。(汗)

不過另外一個題外話,其實這寫法也不太好,因為 Splunk 的文件有建議應該避免寫出以 wildcard 作為 prefix 的搜尋,這個部份可以參考一下 Splunk 官方的文件 [1]。

參考資料

  1. Wildcards

沒有留言: