我們使用 JavaScript 解決 Zabbix 中的實際問題

我們使用 JavaScript 解決 Zabbix 中的實際問題
吉洪·烏斯科夫、Zabbix集成團隊工程師

Zabbix是一個可定制的平台,用於監控任何類型的數據。 從 Zabbix 的最早版本開始,監控管理員就能夠通過以下方式運行各種腳本: 動態 用於檢查目標網絡節點。 同時,腳本的推出也帶來了許多困難,包括需要支持腳本、將腳本交付到通信節點和代理、以及對不同版本的支持等。

用於 Zabbix 的 JavaScript

2019 年 4.2 月,Zabbix 3.4 推出,帶有 JavaScript 預處理功能。 許多人對放棄編寫腳本的想法感到興奮,這些腳本將數據帶到某處,消化它並以 Zabbix 理解的格式提供它,並執行簡單的檢查,以接收尚未準備好由 Zabbix 存儲和處理的數據,以及然後使用 Zabbix 和 JavaScript 工具處理該數據流。 結合 Zabbix XNUMX 中出現的低級發現和依賴項,我們得到了一個相當靈活的概念來排序和管理接收到的數據。

在Zabbix 4.4中,作為JavaScript中預處理的邏輯延續,出現了一種新的通知方法——Webhook,可以使用它輕鬆地將Zabbix通知與第三方應用程序集成。

JavaScript 和 Duktapes

為什麼選擇 JavaScript 和 Duktape? 考慮了語言和引擎的各種選項:

  • 盧阿 - 盧亞 5.1
  • Lua-LuaJIT
  • Javascript - Duktape
  • JavaScript——JerryScript
  • 嵌入式Python
  • 嵌入式Perl

主要選擇標準是流行性、引擎與產品集成的便捷性、引擎的低資源消耗和整體性能,以及將這種語言的代碼引入監控的安全性。 根據指標組合,JavaScript 在 Duktape 引擎上獲勝。

我們使用 JavaScript 解決 Zabbix 中的實際問題

選擇標準和性能測試

杜克膠帶的特點:

- 標準 ECMAScript E5/E5.1
— Duktape 的 Zabbix 模塊:

  • Zabbix.log() - 允許您將不同詳細級別的消息直接寫入 Zabbix Server 日誌中,這使得將 Webhook 中的錯誤與服務器狀態關聯起來成為可能。
  • CurlHttpRequest() - 允許您向網絡發出 HTTP 請求,Webhook 的使用就是基於此。
  • atob() 和 btoa() - 允許您以 Base64 格式對字符串進行編碼和解碼。

. Duktape 符合 ACME 標準。 Zabbix使用2015版本的腳本。 後續更改很小,因此可以忽略。.

JavaScript 魔法

JavaScript 的所有魔力都在於動態類型和類型轉換:字符串、數字和布爾值。

這意味著無需提前聲明變量應返回值的類型。

在數學運算中,函數運算符返回的值被轉換為數字。 此類操作的例外是加法,因為如果至少其中一個術語是字符串,則字符串轉換將應用於所有術語。

. 負責此類轉換的方法通常在對象的父原型中實現, 的價值 и 字符串. 的價值 在數值轉換期間調用,並且始終在方法之前調用 字符串. 方法 的價值 必須返回原始值,否則其結果將被忽略。

在對像上調用方法 的價值。 如果沒有找到或者沒有返回原始值,則調用該方法 字符串。 如果方法 字符串 沒有找到,正在尋找 的價值 在對象的原型中,重複一切,直到值的處理完成並且表達式中的所有值都轉換為相同類型. 如果對象實現了一個方法 字符串,它返回一個原始值,那麼它就是用於字符串轉換的。 但是,應用此方法的結果不一定是字符串。

例如,如果 for for 對象 'OBJ' 方法已定義 字符串,

`var obj = { toString() { return "200" }}` 

方法 字符串 準確返回一個字符串,當將字符串與數字相加時,我們得到一個粘合字符串:

`obj + 1 // '2001'` 

`obj + 'a' // ‘200a'`

但如果你重寫 字符串,使得該方法返回一個數字,當對象相加時,會進行數值轉換的數學運算,得到數學相加的結果。

`var obj = { toString() { return 200 }}` 

`obj + 1 // '2001'`

在這種情況下,如果我們對字符串執行加法,則會執行字符串轉換,並得到一個粘合字符串。

`obj + 'a' // ‘200a'`

這就是 JavaScript 新手出現大量錯誤的原因。

方法 字符串 您可以編寫一個函數,將對象的當前值加 1。

我們使用 JavaScript 解決 Zabbix 中的實際問題
執行腳本,假設變量等於3,它也等於4。

與強制轉換(==)相比,該方法每次都會執行 字符串 具有增值功能。 因此,隨著每次後續比較,該值都會增加。 這可以通過使用非轉換比較 (===) 來避免。

我們使用 JavaScript 解決 Zabbix 中的實際問題
沒有類型轉換的比較

. 不必要時不要使用演員比較.

對於復雜的腳本,例如邏輯複雜的Webhooks,需要進行類型轉換的比較,建議預先編寫對返回變量的值的檢查並處理不一致和錯誤。

網絡鉤子媒體

在 2019 年底和 2020 年初,Zabbix 集成團隊一直在積極開發 Zabbix 發行版附帶的 Webhooks 和開箱即用集成。

我們使用 JavaScript 解決 Zabbix 中的實際問題
鏈接到 文件

前處理

  • JavaScript 中預處理的出現使得放棄大多數外部腳本成為可能,目前在 Zabbix 中您可以獲取任何值並將其轉換為完全不同的值。
  • Zabbix中的預處理是通過JavaScript代碼實現的,當編譯成字節碼時,它被轉換成一個以單個值作為參數的函數 作為字符串(字符串可以包含數字和數字)。
  • 由於輸出是一個函數,因此在腳本末尾需要 返回.
  • 可以在代碼中使用自定義宏。
  • 資源不僅可以在操作系統級別進行限制,還可以通過編程方式進行限制。 預處理步驟最多分配 10 MB RAM,運行時間限制為 10 秒。

我們使用 JavaScript 解決 Zabbix 中的實際問題

. 10 秒的超時值相當大,因為根據相當“重”的預處理場景,在 1 秒內收集條件數千個數據項可能會減慢 Zabbix 的速度。 因此,不建議使用預處理通過所謂的影子數據元素(虛擬項)執行完整的 JavaScript 腳本,這些元素僅運行來執行預處理.

您可以通過預處理測試或使用實用程序檢查您的代碼 zabbix_js:

`zabbix_js -s *script-file -p *input-param* [-l log-level] [-t timeout]`

`zabbix_js -s script-file -i input-file [-l log-level] [-t timeout]`

`zabbix_js -h`

`zabbix_js -V`

實際任務

任務 1

用預處理替換計算項。

健康)狀況:從傳感器獲取華氏溫度並以攝氏度存儲。

以前,我們將創建一個收集華氏溫度的項目。 之後,另一個數據項(計算)將使用公式將華氏溫度轉換為攝氏度。

問題:

  • 需要復制數據元素並將所有值存儲在數據庫中。
  • 您必須就公式中計算和使用的“父”數據項以及計算的數據項的間隔達成一致。 否則,計算項可能會進入不受支持的狀態或計算出先前的值,這將影響監測結果的可靠性。

一種解決方案是放棄靈活的檢查間隔,轉而採用固定間隔,以確保在接收數據的項目(在我們的示例中為華氏溫度)之後評估計算項目。

但例如,如果我們使用模板檢查大量設備,並且每30秒檢查一次,Zabbix“黑客”了29秒,並在最後一秒開始檢查和計算。 這會創建隊列並影響性能。 因此,建議僅在確實必要時才使用固定間隔。

在這個問題中,最佳解決方案是一行 JavaScript 預處理,將華氏度轉換為攝氏度:

`return (value - 32) * 5 / 9;`

它快速而簡單,您不需要創建不必要的數據項並保留它們的歷史記錄,並且您還可以使用靈活的時間間隔進行檢查。

我們使用 JavaScript 解決 Zabbix 中的實際問題

`return (parseInt(value) + parseInt("{$EXAMPLE.MACRO}"));`

但是,如果在假設的情況下需要添加接收到的數據元素,例如,使用宏中定義的任何常量,則必須考慮到參數 展開為字符串。 在字符串加法運算中,兩個字符串簡單地合併為一個。

我們使用 JavaScript 解決 Zabbix 中的實際問題

`return (value + "{$EXAMPLE.MACRO}");`

要獲得數學運算的結果,需要將獲得的值的類型轉換為數值格式。 為此,您可以使用該功能 解析整數(),它產生一個整數,一個函數 解析浮點(),它產生一個小數,或一個函數 ,它返回一個整數或小數。

任務 2

獲取證書結束前的時間(以秒為單位)。

健康)狀況:服務以“Feb 12 12:33:56 2022 GMT”格式頒發證書到期日期。

在 ECMAScript5 中 Date.parse() 接受 ISO 8601 格式 (YYYY-MM-DDTHH:mm:ss.sssZ) 的日期。 必須以 MMM DD YYYY HH:mm:ss ZZ 格式將字符串轉換為它

問題:月份值以文本形式表示,而不是數字。 Duktape 不接受這種格式的數據。

解決方案示例:

  • 首先,聲明一個帶有值的變量(整個腳本是用逗號分隔列出的變量的聲明)。

  • 在第一行我們獲取參數中的日期 並使用以下方法用空格分隔 分裂。 因此,我們得到一個數組,其中數組的每個元素(從索引 0 開始)對應於空格前後的一個日期元素。 分割(0) - 月, 分割(1) - 數字, 分割(2) - 帶有時間等的字符串。之後,可以通過數組中的索引來訪問日期的每個元素。

`var split = value.split(' '),`

  • 每個月(按時間順序)對應於其在數組中的位置索引(從 0 到 11)。 要將文本值轉換為數值,請將月份索引加一(因為月份從 1 開始編號)。 在這種情況下,加一的表達式放在括號中,因為否則將獲得字符串,而不是數字。 最後我們做 片() - 從末尾剪切數組,只留下兩個字符(這對於具有兩位數的月份很重要)。

`MONTHS_LIST = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],`

`month_index = ('0' + (MONTHS_LIST.indexOf(split[0]) + 1)).slice(-2),`

  • 我們通過按適當的順序添加字符串,從獲得的值形成 ISO 格式的字符串。

`ISOdate = split[3] + '-' + month_index + '-' + split[1] + 'T' + split[2],`

生成的格式中的數據是從 1970 年到未來某個時間點的秒數。 在觸發器中使用接收到的格式的數據幾乎是不可能的,因為Zabbix只允許你用宏來操作 {日期} и {時間},以用戶友好的格式返回日期和時間。

  • 然後,我們可以獲取 JavaScript 中 Unix 時間戳格式的當前日期,並從生成的證書到期日期中減去它,以獲得從現在到證書到期的毫秒數。

`now = Date.now();`

  • 在 Zabbix 中,我們將接收到的值除以千來得到秒數。

`return parseInt((Date.parse(ISOdate) - now) / 1000);`

在觸發器中,您可以指定表達式 '最後的' 後跟一組數字,對應於您要響應的時間段內的秒數,例如以周為單位。 因此,觸發器將通知證書將在一周後到期。

. 注意使用 解析整數() 在功能上 返回將毫秒除法得到的小數轉換為整數。 您還可以使用 解析浮點() 並存儲小數數據.

觀看報導

來源: www.habr.com

添加評論