Risolvemu prublemi pratichi in Zabbix usendu JavaScript
Tikhon Uskov, ingegnere di squadra di integrazione Zabbix
Zabbix hè una piattaforma persunalizabile chì hè aduprata per monitorà ogni tipu di dati. Dapoi e prime versioni di Zabbix, l'amministratori di monitoraghju anu avutu a capacità di eseguisce diversi script via Actions per i cuntrolli nantu à i nodi di rete di destinazione. À u listessu tempu, u lanciu di script hà purtatu à una quantità di difficultà, cum'è cum'è a necessità di supportà scripts, a so consegna à i nodi di cumunicazione è i proxy, è ancu u supportu per e diverse versioni.
JavaScript per Zabbix
In April 2019, Zabbix 4.2 hè statu introduttu cù preprocessing JavaScript. Parechje persone anu entusiasmu cù l'idea di abbandunà i script di scrittura chì piglianu dati in qualchì locu, digeriscenu è furnisce in un formatu chì Zabbix capisce, è eseguisce cuntrolli simplici chì riceveranu dati chì ùn sò micca pronti per u almacenamentu è u processu da Zabbix, è poi processà stu flussu di dati cù l'arnesi Zabbix è JavaScript. In cunghjunzione cù scuperta di livellu bassu è elementi dipendente chì apparsu in Zabbix 3.4, avemu un cuncettu abbastanza flexible per sorte è gestione di e dati ricevuti.
In Zabbix 4.4, cum'è una continuazione logica di pre-processamentu in JavaScript, hè apparsu un novu metudu di notificazione - Webhook, chì pò esse usatu per integrà facilmente e notificazioni Zabbix cù applicazioni di terzu.
JavaScript è Duktapes
Perchè sò stati scelti JavaScript è Duktape? Diverse opzioni per lingue è motori sò state cunsiderate:
Lua - Lua 5.1
Lua - LuaJIT
Javascript - Duktape
Javascript - JerryScript
Python integratu
Perl integratu
I criterii principali di selezzione eranu prevalenza, facilità d'integrazione di u mutore in u produttu, u cunsumu di risorse bassu è u rendiment generale di u mutore, è a sicurità di introduzzione di codice in questa lingua in u monitoraghju. Basatu nantu à a cumminazzioni di indicatori, JavaScript hà vintu nantu à u mutore Duktape.
Zabbix.log () - permette di scrive missaghji cù diversi livelli di ditagli direttamente in u logu di u servitore Zabbix, chì permette di correlate l'errori, per esempiu, in un Webhook, cù u statu di u servitore.
CurlHttpRequest () - permette di fà dumande HTTP à a reta, nantu à quale l'usu di Webhook hè basatu.
atob () è btoa () - permette di codificà è decodificà stringhe in u formatu Base64.
NOTA. Duktape hè conforme à i standard ACME. Zabbix usa a versione 2015 di u script. I cambiamenti successivi sò minori, cusì ponu esse ignorati..
Magia JavaScript
Tutta a magia di JavaScript si trova in a tipografia dinamica è a casting di tipu: stringa, numerica è booleana.
Questu significa chì ùn hè micca necessariu di dichjarà in anticipu chì tippu a variàbile deve rinvià un valore.
In l'operazioni matematiche, i valori restituiti da l'operatori di funzione sò cunvertiti in numeri. L'eccezzioni à tali operazioni hè l'aghjunzione, perchè se almenu unu di i termini hè una stringa, a cunversione di stringa hè appiicata à tutti i termini.
NOTA. I metudi rispunsevuli di tali trasfurmazioni sò generalmente implementati in i prototipi parentali di l'ughjettu, valoreOf и àString. valoreOf chjamatu durante a cunversione numerica è sempre prima di u metudu àString. Metudu valoreOf deve rinvià i valori primitivi, altrimenti u so risultatu hè ignoratu.
Un metudu hè chjamatu nantu à un oggettu valore di. Se ùn hè micca truvatu o ùn torna micca un valore primitivu, u metudu hè chjamatu àString. Se u metudu àString micca trovu, cerca valoreOf in u prototipu di l'ughjettu, è tuttu hè ripetutu finu à chì u processu di u valore hè cumpletu è tutti i valori in l'espressione sò cast à u listessu tipu.. Se l'ughjettu implementa un metudu àString, chì torna un valore primitivu, allora hè quellu chì hè utilizatu per a cunversione di stringa.Tuttavia, u risultatu d'applicà stu metudu ùn hè micca necessariamente una stringa.
Per esempiu, se per l'ughjettu 'ughjettu"U metudu hè definitu àString,
`var obj = { toString() { return "200" }}`
Metu àString torna esattamente una stringa, è quandu aghjunghje una stringa cù un numeru, avemu una stringa incollata:
`obj + 1 // '2001'`
`obj + 'a' // ‘200a'`
Ma si riscrive àString, cusì chì u metudu torna un numeru, quandu l'ughjettu hè aghjuntu, una operazione matematica cù una cunversione numerica serà realizatu è u risultatu di l'aghjuntu matematicu serà ottenutu.
In questu casu, se facemu l'aghjunzione cù una stringa, una cunversione di stringa hè realizata, è avemu una stringa incollata.
`obj + 'a' // ‘200a'`
Questu hè u mutivu di un gran numaru di sbagli da l'utilizatori novi JavaScript.
U metudu àString pudete scrive una funzione chì aumenterà u valore attuale di l'ughjettu da 1.
Esecuzione di u script, basta chì a variabile hè uguale à 3, è hè ancu uguale à 4.
Comparatu cù un cast (==), u metudu hè eseguitu ogni volta àString cù a funzione di crescita di valore. Per quessa, cù ogni paraguni sussegwente, u valore aumenta. Questu pò esse evitata usendu paraguni non-cast (===).
Paragone senza tippu casting
NOTA. Ùn aduprate micca u Cast Comparaison Inutilmente.
Per i scripti cumplessi, cum'è Webhooks cù logica cumplessa, chì necessitanu paraguni cù u casting di tipu, hè cunsigliatu di pre-scrive cuntrolli per i valori chì tornanu variabili è trattanu inconsistenze è errori.
Webhook Media
À a fine di u 2019 è à l'iniziu di u 2020, a squadra di integrazione Zabbix hà sviluppatu attivamente Webhooks è integrazioni out-of-the-box chì venenu cù a distribuzione Zabbix.
L'avventu di preprocessing in JavaScript hà permessu di abbandunà a maiò parte di i script esterni, è attualmente in Zabbix pudete ottene qualsiasi valore è cunvertisce in un valore completamente diversu.
A preprocessazione in Zabbix hè implementata da u codice JavaScript, chì, quandu compilatu in bytecode, hè cunvertitu in una funzione chì piglia un valore unicu cum'è paràmetru. valore cum'è una stringa (una stringa pò cuntene un cifru è un numeru).
Siccomu l'output hè una funzione, à a fine di u script hè necessariu ritornu.
Hè pussibule aduprà macros persunalizati in u codice.
I risorsi ponu esse limitati micca solu à u nivellu di u sistema operatore, ma ancu programmaticu. U passu di preprocessing hè attribuitu un massimu di 10 megabytes di RAM è un limitu di runtime di 10 seconde.
NOTA. U valore di timeout di 10 seconde hè assai assai, perchè a cullizzioni di millaie di dati cundiziunali in 1 secondu secondu un scenariu di preprocessazione piuttostu "pesante" pò rallentà Zabbix. Per quessa, ùn hè micca cunsigliatu di utilizà a preprocessazione per eseguisce scripts JavaScript cumpletu attraversu l'elementi di dati ombra chjamati (elementi fittizi), chì sò eseguiti solu per eseguisce preprocessing..
Pudete cuntrollà u vostru còdice attraversu a prova di preprocessing o usendu l'utilità zabbix_js:
Cundizione: Ottene a temperatura in Fahrenheit da u sensor per almacenà in Celsius.
Nanzu, avemu da creà un articulu chì recullà a temperatura in gradi Fahrenheit. Dopu quì, un altru articulu di dati (calculatu) chì cunvertisce Fahrenheit à Celsius cù una formula.
Problemi:
Hè necessariu duplicà elementi di dati è almacenà tutti i valori in a basa di dati.
Avete bisognu di l'intervalli per l'elementu di dati "parent" chì hè calculatu è utilizatu in a formula, è per l'elementu di dati calculatu. Altrimenti, l'elementu calculatu pò andà in un statu micca supportatu o calculà un valore precedente, chì affettarà l'affidabilità di i risultati di u monitoraghju.
Una solu suluzione era di alluntanassi da intervalli di cuntrollu flessibili in favore di intervalli fissi per assicurà chì l'articulu calculatu hè evaluatu dopu à l'articulu chì riceve i dati (in u nostru casu, a temperatura in gradi Fahrenheit).
Ma s'è, per esempiu, avemu aduprà u mudellu à verificà un gran numaru di dispusitivi, è u cuntrollu hè realizatu una volta ogni 30 seconde, Zabbix "hacks" per 29 seconde, è à l 'ultimu secondu principia à verificà è calculà. Questu crea una fila è affetta u rendiment. Dunque, hè cunsigliatu di utilizà intervalli fissi solu s'ellu hè veramente necessariu.
In questu prublema, a suluzione ottima hè un preprocessing JavaScript in una linea chì cunverte gradi Fahrenheit à gradi Celsius:
`return (value - 32) * 5 / 9;`
Hè veloce è faciule, ùn avete micca bisognu di creà elementi di dati innecessarii è mantene una storia nantu à elli, è pudete ancu aduprà intervalli flessibili per i cuntrolli.
Ma, se in una situazione ipotetica hè necessariu aghjunghje l'elementu di dati ricivutu, per esempiu, cù qualsiasi constante definita in a macro, deve esse cunsideratu chì u paràmetru. valore si dilata in una corda. In una operazione di addizione di corde, duie corde sò simpliciamente cumminate in una sola.
`return (value + "{$EXAMPLE.MACRO}");`
Per ottene u risultatu di una operazione matematica, hè necessariu di cunvertisce i tipi di i valori ottenuti in un furmatu numericu. Per questu pudete aduprà a funzione parseInt(), chì pruduce un interu, una funzione parseFloat(), chì pruduce un decimale, o una funzione nùmeru, chì restituisce un interu o decimale.
Task 2
Ottene u tempu in seconde finu à a fine di u certificatu.
Cundizione: un serviziu emette una data di scadenza di certificatu in u formatu "Feb 12 12:33:56 2022 GMT".
In ECMAScript5 data.parse() accetta una data in u furmatu ISO 8601 (AAAA-MM-GGTHH:mm:ss.sssZ). Hè necessariu di cascà una stringa in u furmatu MMM DD AAAA HH:mm:ss ZZ
prublemu: U valore di u mese hè spressu cum'è testu, micca cum'è un numeru. I dati in stu formatu ùn sò micca accettati da Duktape.
Esempiu di suluzione:
Prima di tuttu, una variàbile hè dichjarata chì piglia un valore (u scrittu sanu hè una dichjarazione di variàbili chì sò listati separati da virgule).
In a prima linea avemu a data in u paràmetru valore è separà cù spazii cù u metudu Split. Cusì, avemu un array, induve ogni elementu di l'array, cuminciendu à l'indice 0, currisponde à un elementu di data prima è dopu un spaziu. split (0) - mese, split (1) - numeru, split (2) - una stringa cù u tempu, etc. Dopu à quessa, ogni elementu di a data pò esse accessu per index in u array.
`var split = value.split(' '),`
Ogni mese (in ordine cronologicu) currisponde à l'indici di a so pusizioni in l'array (da 0 à 11). Per cunvertisce un valore di testu à un valore numericu, unu hè aghjuntu à l'indici di u mese (perchè i mesi sò numerati da 1). In questu casu, l'espressione cù l'aghjunzione di unu hè presa in parentesi, perchè altrimenti una stringa serà ottenuta, micca un numeru. À a fine facemu fetta () - cut the array from the end to leave only two characters (chì hè impurtante per mesi cù un numeru di dui cifre).
I dati in u formatu risultatu hè u numeru di seconde da 1970 à qualchì puntu in u futuru. Hè quasi impussibile di utilizà dati in u formatu ricevutu in triggers, perchè Zabbix vi permette di operà solu cù macros. {Data} и {Time}, chì torna a data è l'ora in un formatu amichevule.
Pudemu allora ottene a data attuale in JavaScript in u formatu Unix Timestamp è sottrallu da a data di scadenza di u certificatu risultatu per ottene u numeru di millisecondi da avà finu à chì u certificatu scade.
`now = Date.now();`
Dividemu u valore ricevutu per mille per ottene seconde in Zabbix.
In u trigger, pudete specificà l'espressione 'ultimu' seguita da un inseme di cifre chì currisponde à u numeru di seconde in u periodu à quale vulete risponde, per esempiu, in settimane. Cusì, u trigger avvisarà chì u certificatu scade in una settimana.
NOTA. Attenti à l'usu parseInt() in funzione ritornuper cunvertisce u numeru fraccionariu risultatu da a divisione di millisecondi à un entero. Pudete ancu aduprà parseFloat() è almacenà dati fraccionari.