Risolvere compiti pratici in Zabbix utilizzando JavaScript

Risolvere compiti pratici in Zabbix utilizzando JavaScript
Tikhon Uskov, ingegnere del team di integrazione Zabbix

Zabbix è una piattaforma personalizzabile utilizzata per monitorare qualsiasi tipo di dati. Fin dalle prime versioni di Zabbix, gli amministratori di monitoraggio avevano la possibilità di eseguire vari script tramite Azioni per controlli sui nodi target della rete. Tuttavia, l'esecuzione degli script comportava una serie di difficoltà, tra cui la necessità di supportare gli script, la loro distribuzione ai nodi di comunicazione e proxy, così come la compatibilità con diverse versioni.

JavaScript per Zabbix

Nell'aprile 2019, è stato rilasciato Zabbix 4.2 con la funzione di pre-elaborazione in JavaScript. Molti si sono entusiasti dell'idea di rinunciare alla scrittura di script che prelevano dati, li elaborano e li forniscono in un formato comprensibile per Zabbix, per eseguire però controlli semplici che riceveranno dati non pronti per essere memorizzati e trattati da Zabbix e poi elaboreranno questo flusso di dati utilizzando gli strumenti di Zabbix e JavaScript. In combinazione con la rilevazione a basso livello e i dati dipendenti, introdotti in Zabbix 3.4, si è ottenuta una concettualizzazione abbastanza flessibile per la gestione e il controllo dei dati ottenuti.

In Zabbix 4.4, come logica continuazione del pre-elaborazione in JavaScript, è stato introdotto un nuovo modo di avvisare — il Webhook, che può essere utilizzato per una semplice integrazione delle notifiche di Zabbix con applicazioni di terze parti.

JavaScript e Duktape

Perché sono stati scelti JavaScript e Duktape? Sono state valutate varie opzioni di linguaggi e motori:

  • Lua – Lua 5.1
  • Lua – LuaJIT
  • Javascript – Duktape
  • Javascript – JerryScript
  • Embedded Python
  • Embedded Perl

I principali criteri di scelta erano la diffusione, la facilità di integrazione del motore nel prodotto, il basso consumo di risorse e le prestazioni generali del motore, nonché la sicurezza dell'inserimento del codice in questo linguaggio nel monitoraggio. In base a questa combinazione di fattori, ha prevalso JavaScript basato sul motore Duktape.

Risolvere compiti pratici in Zabbix utilizzando JavaScript

Criteri di scelta e performance testing

Caratteristiche di Duktape:

— Standard ECMAScript E5/E5.1
— Moduli Zabbix per Duktape:

  • Zabbix.log() — consente di scrivere direttamente nel log del Server Zabbix messaggi con vari livelli di dettaglio, permettendo di correlare errori, ad esempio, nel Webhook con lo stato del server.
  • CurlHttpRequest() — consente di effettuare richieste HTTP in rete, su cui si basa l'uso del Webhook.
  • atob() e btoa() — consentono di codificare e decodificare stringhe nel formato Base64.

NOTA. Duktape è conforme agli standard ACME. In Zabbix viene utilizzata la versione dello script del 2015. Le modifiche successive sono insignificanti e possono quindi essere ignorate..

La magia di JavaScript

Tutta la magia di JavaScript risiede nella tipizzazione dinamica e nella conversione dei tipi: stringhe, numeri e valori logici.

Ciò significa che non è necessario dichiarare in anticipo che tipo di variabile deve restituire un valore.

Durante le operazioni matematiche, i valori restituiti dagli operatori-funzioni vengono convertiti in numeri. L'eccezione a tali operazioni è l'addizione, poiché, se almeno uno degli addendi è una stringa, a tutti gli addendi viene applicata la conversione in stringa.

NOTA. I metodi responsabili di tali conversioni sono generalmente implementati nei prototipi genitori degli oggetti, valueOf e toString. valueOf viene chiamato durante la conversione numerica e sempre prima del metodo toString. Il metodo valueOf deve restituire valori primitivi, altrimenti il suo risultato verrà ignorato.

Per un oggetto viene chiamato il metodo valueOF. Se non viene trovato o non restituisce un valore primitivo, viene chiamato il metodo toString. Se il metodo toString non viene trovato, si cerca valueOf nel prototipo dell'oggetto, e tutto si ripete fino al completamento del processamento del valore e alla conversione di tutti i valori nell'espressione a un unico tipo.. Se per l'oggetto è implementato un metodo toString, che restituisce un valore primitivo, allora è proprio questo a essere utilizzato per la conversione in stringa. Il risultato di questo metodo non deve necessariamente essere una stringa.

Ad esempio, se per l'oggetto ‘obj‘ è definito un metodo toString,

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

metodo toString restituisce proprio una stringa, e nella somma di una stringa con un numero otteniamo una stringa concatenata:

`obj + 1 // '2001'` 

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

Ma se riscriviamo toString, in modo che il metodo restituisca un numero, durante la somma dell'oggetto verrà eseguita l'operazione matematica con conversione numerica e si ottiene il risultato della somma matematica.

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

`obj + 1 // '2001'`

In questo caso, se eseguiamo l'addizione con una stringa, viene effettuata la conversione in stringa e otteniamo una stringa concatenata.

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

È proprio in questo che risiede il motivo di un gran numero di errori da parte degli utenti principianti di JavaScript.

Nel metodo toString si può inserire una funzione che aumenti il valore attuale dell'oggetto di 1.

Risolvere compiti pratici in Zabbix utilizzando JavaScript
L'esecuzione dello script a condizione che la variabile sia uguale a 3 e sia anche uguale a 4.

Rispetto al confronto dei tipi (==), viene eseguito un metodo ogni volta toString con la funzione di incremento del valore. Di conseguenza, ad ogni confronto successivo il valore aumenta. Questo può essere evitato utilizzando un confronto senza coercizione di tipo (===).

Risolvere compiti pratici in Zabbix utilizzando JavaScript
Confronto senza coercizione di tipo

NOTA. Non utilizzare il confronto con coercizione di tipo senza necessità.

Per script complessi, ad esempio, Webhook con logica complicata, in cui è necessario un confronto con coercizione di tipo, si raccomanda di scrivere in anticipo verifiche per i valori restituiti dalle variabili e gestire le discrepanze e gli errori.

Webhook Media

Alla fine del 2019 e all'inizio del 2020, il team di integrazione di Zabbix ha lavorato attivamente allo sviluppo di Webhook e integrazioni "pronte all'uso" fornite nel pacchetto di Zabbix.

Risolvere compiti pratici in Zabbix utilizzando JavaScript
Link a la documentazione

Preprocessing

  • L'introduzione della preelaborazione in JavaScript ha permesso di eliminare la maggior parte degli script esterni, e attualmente in Zabbix è possibile ottenere qualsiasi valore e convertirlo in un altro valore completamente diverso.
  • La preelaborazione in Zabbix è implementata tramite codice JavaScript, che, al momento della compilazione in bytecode, viene trasformato in una funzione che accetta un singolo valore come parametro value sotto forma di stringa (la stringa può contenere anche numeri).
  • Poiché in output si ottiene una funzione, alla fine dello script è obbligatorio return.
  • È possibile utilizzare macro personalizzate nel codice.
  • Le risorse possono essere limitate non solo a livello di sistema operativo, ma anche a livello di programmazione. Per il passaggio di preelaborazione si riservano al massimo 10 megabyte di memoria RAM e un limite di tempo di esecuzione di 10 secondi.

Risolvere compiti pratici in Zabbix utilizzando JavaScript

NOTA. I valori di timeout di 10 secondi sono più che sufficienti, poiché la raccolta di migliaia di elementi di dati in un secondo in uno scenario di preelaborazione piuttosto "pesante" potrebbe rallentare Zabbix. Pertanto, non si consiglia di utilizzare la preelaborazione per eseguire script completi in JavaScript tramite i cosiddetti elementi di dati dummy, che vengono eseguiti solo per effettuare la preelaborazione..

Il proprio codice può essere verificato tramite un test di preelaborazione o con l'ausilio dello strumento 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`

Attività pratiche

Compito 1

Sostituire l'elemento dati calcolato con una pre-elaborazione.

Condizione: otteniamo dal sensore la temperatura in gradi Fahrenheit da conservare in gradi Celsius.

In passato avremmo creato un elemento dati che raccoglieva la temperatura in gradi Fahrenheit. Successivamente, un altro elemento dati (calcolato) che, secondo una formula, avrebbe convertito i gradi Fahrenheit in gradi Celsius.

Problemi:

  • È necessario duplicare gli elementi dati e memorizzare tutti i valori nel database.
  • È necessario coordinare gli intervalli per l'elemento dati "genitore", che viene calcolato e utilizzato nella formula, e per l'elemento dati calcolato. In caso contrario, l'elemento dati calcolato potrebbe andare in uno stato non supportato o calcolare il valore precedente, il che influenzerebbe l'affidabilità dei risultati di monitoraggio.

Una delle soluzioni è stata quella di rinunciare agli intervalli di controllo flessibili a favore di intervalli fissi, per garantire il calcolo dell'elemento dati calcolato dopo l'elemento dati che riceve i dati (in questo caso, la temperatura in gradi Fahrenheit).

Ma se, ad esempio, utilizziamo il template per verificare un gran numero di dispositivi e il controllo avviene ogni 30 secondi, per 29 secondi Zabbix è inattivo, e nell'ultimo secondo inizia i controlli e i calcoli. Questo porta a creare una coda e influisce sulle prestazioni. Pertanto, si consiglia di utilizzare intervalli fissi solo se è davvero necessario.

In questo caso, la soluzione ottimale è una pre-elaborazione con una sola riga in JavaScript, che converte i gradi Fahrenheit in gradi Celsius:

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

È veloce e semplice, non è necessario creare ulteriori elementi dati e memorizzare la loro cronologia, e può essere utilizzato per controlli con intervalli flessibili.

Risolvere compiti pratici in Zabbix utilizzando JavaScript

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

Ma, se in una situazione ipotetica è necessario sommare l'elemento dati ottenuto, ad esempio con una costante definita in un macro, è necessario considerare che il parametro value viene espanso in una stringa. Durante l'operazione di somma tra stringhe, le due stringhe si uniscono in una sola.

Risolvere compiti pratici in Zabbix utilizzando JavaScript

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

Per ottenere il risultato di un'operazione matematica, è necessario convertire i tipi di valori ottenuti in formato numerico. A tal fine, si può utilizzare la funzione parseInt(), che restituisce un numero intero, la funzione parseFloat(), che restituisce un numero decimale, oppure la funzione number, che restituisce un numero intero o decimale.

Compito 2

Ottenere il tempo in secondi fino alla scadenza del certificato.

Condizione: un certo servizio restituisce la data di scadenza del certificato nel formato "Feb 12 12:33:56 2022 GMT".

In ECMAScript5 ora supporta formati di data aggiuntivi: accetta una data nel formato ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ). È necessario convertire questa stringa nel formato MMM DD YYYY HH:mm:ss ZZ

Problema: il valore del mese è espresso in lettere, anziché in numeri. Dati in questo formato non sono accettati da Duktape.

Esempio di soluzione:

  • Per prima cosa viene dichiarata una variabile che acquisisce valore (l'intero script è una dichiarazione di variabili, elencate tramite virgole).

  • Nella prima riga otteniamo la data nel parametro value e la dividiamo con spazi utilizzando il metodo split. In questo modo, otteniamo un array, in cui ogni elemento dell'array, a partire dall'indice 0, corrisponde a un elemento della data prima e dopo lo spazio. split(0) — mese, split(1) — giorno, split(2) — stringa con l'ora, ecc. Dopo, si può accedere a ciascun elemento della data per indice nell'array.

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

  • Ad ogni mese (in ordine cronologico) corrisponde un indice nella sua posizione nell'array (da 0 a 11). Per convertire il valore testuale in numerico, si aggiunge uno all'indice del mese (poiché la numerazione dei mesi inizia da 1). L'espressione con l'aggiunta di uno è racchiusa tra parentesi, poiché altrimenti si otterrebbe una stringa, anziché un numero. Alla fine, eseguiamo slice() — un taglio dell'array dalla fine, per mantenere solo due caratteri (importante per i mesi con numero a due cifre).

`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),`

  • Formiamo dalla stringa ottenuta una data nel formato ISO tramite una semplice concatenazione delle stringhe nell'ordine appropriato.

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

I dati nel formato ottenuto rappresentano il numero di secondi dal 1970 fino a un certo momento nel futuro. Utilizzare i dati nel formato ottenuto nei trigger è praticamente impossibile, poiché Zabbix consente di operare solo con i macro {Date} e {Time}, che restituiscono data e ora in un formato comprensibile per l'utente.

  • Dopo di che possiamo ottenere in JavaScript la data attuale nel formato Unix Timestamp e sottrarla dal valore ottenuto della data di scadenza del certificato per ottenere il numero di millisecondi dal momento attuale fino alla scadenza del certificato.

`now = Date.now();`

  • Dividiamo il valore ottenuto per mille, per ottenere i secondi in Zabbix.

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

Nel trigger possiamo specificare l'espressione ‘last<‘ e un insieme di cifre che corrisponde al numero di secondi nel periodo a cui bisogna reagire, ad esempio, in settimane. In questo modo, il trigger notificherà che la scadenza del certificato è tra una settimana.

NOTA. Si prega di notare l'uso di parseInt() nella funzione return, per convertire un numero decimale ottenuto dal risultato della divisione dei millisecondi in un numero intero. È anche possibile utilizzare parseFloat() e memorizzare dati decimali.

Guarda la relazione

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster