輕松測試 logstash 的配置文件


配置文件本身非常脆弱!所以修改配置文件自然會引入部署失敗的風險。如果能夠對配置文件進行自動化測試將會極大的降低這種風險。本文將介紹一個可以自動化測試 logstash 配置文件的工具,讓大家可以像寫單元測試用例一樣為 logstash 配置文件創建測試 case,並以快速迭代的方式變更 logstash 配置文件。

噩夢

在很多真實環境中,變更 logstash 的配置文件幾乎是個噩夢。日志不是結構化的格式(甚至是亂七八糟!),導致我們幾乎必須一個一個地處理日志,並對解析什么和不解析什么做出邏輯判定。這會導致我們在 logstash 的配置文件中寫出復雜的日志處理邏輯。更加悲催的是,我們編寫的僅僅是一個配置文件,大多數時候你找不到像 VisualStudio 那樣豪華的帶有拼寫檢查和語法檢查的編輯工具。所以我們迫切的需要一個可以對 logstash 的配置文件做單元測試的工具,讓我們更好的控制變更、執行迭代。

logstash-test-runner

logstash-test-runner 就是這樣一個可以讓我們應用 DevOps 原則來解決這個問題的工具。它具有下面幾個特點:

  • 它是一個測試框架
  • 非常容易寫測試用例
  • 不用學習一個新的 DSL(Domain-Specific-Language)
  • 能夠快速的獲得反饋

logstash-test-runner 的作者應該是飽受 logstash 的配置文件蹂躪之后創建的這個工具,所以這是一個寫給自己用的工具,在使用的時候你能夠切身體會到它的便利!

前提條件

運行 logstash-test-runner 依賴於下面三個條件:

  • Docker
  • NodeJS > v8
  • Bash > v4

其中 logstash 的測試用例是在 docker 容器中運行的,默認使用的鏡像中 logstash 的版本為 5.5.1,我們可以通過第二個命令行參數指定其它的版本。

NodeJS 程序用來對比實際運行的輸出結果與期望的輸出結果。

logstash-test-runner 其實就是一個 Bash 腳本,把上面的工具組織起來完成任務。

在運行 logstash-test-runner 前請確保你的環境滿足上述條件。然后從這里克隆 logstash-test-runner。如果你確定你要運行的 logstash 的版本,最好是提前先把對應的容器鏡像拉下來,比如筆者最常用的是 logstash 6.2.4:

$ docker pull docker.elastic.co/logstash/logstash:6.2.4

運行下內置的 demo

准備就緒,讓我們先運行下 logstash-test-runner 內置的 demo 體驗一下。進入到 logstash-test-runner 目錄下,執行下面的命令:

$ npm install
$ ./test.sh __tests__

test.sh 腳本的第一個參數是保存測試用例的根目錄,第二個參數是 logstash 的 docker 鏡像。也可以不指定 logstash 鏡像,默認使用的鏡像中的 logstash 版本為 5.5.1。該命令執行的結果如下:

__tests__ 目錄的結構如下:

每個子目錄代表一個測試用例,demo 中有三個測試用例,分別是 clustering、crawlers 和 mongo。每個測試用例下有三個文件,分別是 input.log、logstash.conf 和 output.log,他們的名稱是固定的。input.log 模擬日志文件,保存的是日志記錄;logstash.conf 則是待測的 logstash 配置文件;output.log 中是需要我們寫入的期望結果(這就是 logstash 版的單元測試呀!)。

添加自己的測試用例

下面我們添加自己的測試用例來測試 multiline 功能(把應用程序中的異常堆棧合並到一條日志記錄中)。先創建目錄 __nick__/mlines,然后在 __nick__/mlines 目錄中創建文件 input.log、logstash.conf 和 output.log。input.log 文件的內容如下:

2019-1
hello
world
2019-2
aa
2019-3
  bb
2019-4

模擬的日志記錄以日期開頭,非數字開頭的記錄則是異常堆棧。

logstash.conf 文件的內容如下:

input {
  stdin {
    codec => multiline {
      pattern => "^\d"
      negate => "true"
      what => "previous"
    }
  }
}
filter {
  mutate {
    replace => {
      "host" => "testing_host"
    }
  }
}

filter 中設置 host 主要目的是讓測試用例忽略真正的 host 值(在容器中運行這個值是隨機的字符串,無法執行比較操作,所以總是讓他輸出 testing_host)。

output.log 文件的內容如下:

{"tags":["multiline"],"host":"testing_host","message":"2019-1\nhello\nworld","@version":"1","@timestamp":"2019-03-05T09:30:26.820Z"}
{"tags":["multiline"],"host":"testing_host","message":"2019-2\naa","@version":"1","@timestamp":"2019-03-05T09:30:26.823Z"}
{"tags":["multiline"],"host":"testing_host","message":"2019-3\n  bb","@version":"1","@timestamp":"2019-03-05T09:30:26.824Z"}

這是我們期望 logstash 輸出的 JSON 格式的日志記錄。當然,在默認情況下 logstash-test-runner 會忽略 @timestamp。

接下來執行下面的命令運行測試:

$ ./test.sh __nick__ docker.elastic.co/logstash/logstash:6.2.4

該命令中筆者指定了 logstash 鏡像,所以測試用例都是由 logstash 6.2.4 執行的,結果如下:

上圖顯示測試用例都通過了。如果有測試用例失敗,就會輸出詳細的失敗信息,非常有助於排除問題。

難點在於寫 output.log

logstash-test-runner 非常簡單易用,其實在整個使用過程中,筆者覺得寫 output.log 是最困難的。因為你很難根據日志記錄和 logstash 的配置文件直接推導出 logstash 輸出的記錄應該是什么樣子的。logstash-test-runner 直接把 logstash 輸出的日志記錄輸出到了 console 中:

這樣我們就可以輕松的根據 console 中的輸出來調整 output.log 文件了!

總結

使用者為自己編寫的工具往往是直擊痛點,logstash-test-runner 就是這樣的工具。它讓我們可以快速迭代 logstash 的配置變更。我們還可以自動化的執行 logstash-test-runner,作為 CI/CD 的一部分,從而確保每個配置變更都通過了測試。
對 logstash 之類的基礎設施工具進行測試符合 DevOps(構建→測試→發布→運行)的實踐。我想測試基礎設施配置的實踐會越來越普遍,並且在提高基礎設施可靠性和交付方面體現出巨大的價值。

參考:
Dealing with Tight-Coupling
agolo/logstash-test-runner


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM