吉洪·烏斯科夫、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 引擎上獲勝。
選擇標準和性能測試
杜克膠帶的特點:
- 標準
— 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。
執行腳本,假設變量等於3,它也等於4。
與強制轉換(==)相比,該方法每次都會執行 字符串 具有增值功能。 因此,隨著每次後續比較,該值都會增加。 這可以通過使用非轉換比較 (===) 來避免。
沒有類型轉換的比較
注. 不必要時不要使用演員比較.
對於復雜的腳本,例如邏輯複雜的Webhooks,需要進行類型轉換的比較,建議預先編寫對返回變量的值的檢查並處理不一致和錯誤。
網絡鉤子媒體
在 2019 年底和 2020 年初,Zabbix 集成團隊一直在積極開發 Zabbix 發行版附帶的 Webhooks 和開箱即用集成。
鏈接到
前處理
- JavaScript 中預處理的出現使得放棄大多數外部腳本成為可能,目前在 Zabbix 中您可以獲取任何值並將其轉換為完全不同的值。
- Zabbix中的預處理是通過JavaScript代碼實現的,當編譯成字節碼時,它被轉換成一個以單個值作為參數的函數 值 作為字符串(字符串可以包含數字和數字)。
- 由於輸出是一個函數,因此在腳本末尾需要 返回.
- 可以在代碼中使用自定義宏。
- 資源不僅可以在操作系統級別進行限制,還可以通過編程方式進行限制。 預處理步驟最多分配 10 MB RAM,運行時間限制為 10 秒。
注. 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;`
它快速而簡單,您不需要創建不必要的數據項並保留它們的歷史記錄,並且您還可以使用靈活的時間間隔進行檢查。
`return (parseInt(value) + parseInt("{$EXAMPLE.MACRO}"));`
但是,如果在假設的情況下需要添加接收到的數據元素,例如,使用宏中定義的任何常量,則必須考慮到參數 值 展開為字符串。 在字符串加法運算中,兩個字符串簡單地合併為一個。
`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