跳到主要內容
節省工具箱Jason Tools
經驗分享

Graylog Pipeline 改寫 source 欄位

Jason Cheng 發布 瀏覽 1 次
Graylog Pipeline 改寫 source 欄位
本文目錄
  1. 情境
  2. Pipeline Rule
  3. 設定步驟
  4. 處理順序
  5. 其他做法
  6. 比較
  7. 結論
  8. 參考資料

收記錄時常遇到一種狀況:某套應用程式送進 Graylog 的 syslog,source 欄位全部都是 localhost.localdomain。原因通常是那台主機的主機名稱沒設定好,或應用程式自己組 syslog 時寫死了主機名稱。

結果就是在 Graylog 裡完全分不出是誰送的,依 source 做的串流規則、看板、告警也都對不上。這篇用 Pipeline Rule 依訊息內容改寫 source,順便整理幾種其他的處理方式。

情境

以某套應用程式為例(以下用 MyApp 代稱),它的記錄長這樣:

<134>Mar 25 10:15:32 localhost.localdomain MyApp[2381]: user login success, uid=1001

訊息裡有 MyApp[ 這段程式名稱與 PID,但 source 被設成 localhost.localdomain。目標是:只要訊息裡出現 MyApp[,就把 source 改成 MyApp。

Pipeline Rule

基本寫法

rule "Set source to MyApp"
when
  contains(to_string($message.message), "MyApp[", true)
then
  set_field("source", "MyApp");
end
  • contains(值, 要找的字串, 忽略大小寫)
    第三個參數 true 是不分大小寫
  • to_string()
    確保欄位是字串再比對,欄位不存在時也不會出錯
  • set_field()
    直接覆寫 source

較嚴謹的寫法

只在 source 真的是 localhost.localdomain 時才改,避免影響其他已經正確的記錄(例如另一台主機名稱設對的同一套程式),同時把原本的值留下來:

rule "Set source to MyApp"
when
  contains(to_string($message.message), "MyApp[", true)
  && to_string($message.source) == "localhost.localdomain"
then
  set_field("original_source", $message.source);
  set_field("source", "MyApp");
end

保留 original_source 的好處是日後追查時,還看得出這筆原本是怎麼送進來的。

同一台主機有多套程式時

如果同一個 source 底下有好幾套程式,可以改用正規表示式把程式名稱抓出來,一條規則處理全部:

rule "Set source from app name"
when
  to_string($message.source) == "localhost.localdomain"
  && regex("^(MyApp|OtherApp)\\[", to_string($message.message)).matches == true
then
  let m = regex("^(MyApp|OtherApp)\\[", to_string($message.message));
  set_field("original_source", $message.source);
  set_field("source", m["0"]);
end

regex() 的群組從 "0" 開始編號。這裡比對訊息開頭,所以前提是 message 欄位已經拿掉 syslog 的表頭(Graylog 的 Syslog input 解析成功時就是如此)。

注意:contains() 比 regex() 省資源,能用 contains() 就不要用 regex()。Pipeline 會對每一筆進來的訊息執行,記錄量大的環境差異很明顯。

設定步驟

  1. 建立規則
    「System → Pipelines」→「Manage rules」→「Create Rule」,貼上規則內容並儲存
  2. 建立 Pipeline
    「Manage pipelines」→「Add new pipeline」,在 Stage 0 加入剛才的規則
  3. 連結串流
    在 Pipeline 的「Edit connections」連結到這些記錄會進入的串流(不確定的話先連 Default Stream)
  4. 模擬測試
    Pipeline 頁面有「Simulate processing」,貼一筆原始訊息就能看到規則套用後的結果,上線前先測過

處理順序

Pipeline 有沒有在正確的時機執行,要看「System → Configurations → Message Processors」的順序。預設是:

  1. Message Filter Chain(extractor、串流規則)
  2. Pipeline Processor

這代表串流規則判斷時,source 還沒被 Pipeline 改掉。如果有依 source 分流的串流規則,要嘛把串流規則改成依訊息內容判斷,要嘛在 Pipeline 裡用 route_to_stream() 直接分流:

rule "Set source to MyApp and route"
when
  contains(to_string($message.message), "MyApp[", true)
then
  set_field("source", "MyApp");
  route_to_stream(name: "MyApp Logs");
end

其他做法

從來源修正

最根本的做法還是讓送記錄的那一端送對:

  • 設好主機名稱(hostnamectl set-hostname app01.example.com),並確認 /etc/hosts 一致
  • 如果記錄是透過 rsyslog 轉送,可以在 rsyslog 的範本裡指定主機名稱
  • 應用程式本身有 syslog 設定的話,看有沒有可以填主機名稱的欄位

能從來源改就從來源改,Graylog 端的規則是在沒辦法動來源(例如廠商設備、封閉的商用軟體)時才用。

Input 的 Override source

Syslog input 的設定裡有 Override source 欄位,填了之後這個 input 收到的所有訊息 source 都會被改成那個值。適合專門給一台設備使用的 input,例如開一個 UDP 1515 的 input 只收這套程式的記錄。

缺點是要多開 input、多開防火牆,而且整個 input 的訊息都會被改,沒辦法依內容判斷。

比較

做法優點缺點
從來源修正最根本,Graylog 不用額外處理不一定改得到
Input 的 Override source設定簡單,不耗效能要專用 input,無法依內容判斷
Pipeline Rule最有彈性,可依內容判斷、保留原值每筆訊息都要執行,規則要寫得精簡

結論

source 是 Graylog 裡最常用來篩選的欄位之一,它錯了,後面的串流、看板、告警都會跟著錯。我的建議是:能從來源改就從來源改,改不了再用 Pipeline Rule,而且規則要加上條件只處理需要的那幾筆,並把原值留下來。

參考資料

Jason Cheng

Jason Cheng

企業開源技術顧問,專注架構規劃與實務導入

關於作者 →

延伸閱讀