Risolviamo problemi pratici in Zabbix utilizzando JavaScript

Risolviamo problemi pratici in Zabbix utilizzando JavaScript
Tikhon Uskov, Ingegnere del team di integrazione di Zabbix

Zabbix è una piattaforma personalizzabile che viene utilizzata per monitorare qualsiasi tipo di dati. Fin dalle prime versioni di Zabbix, gli amministratori di monitoraggio hanno avuto la possibilità di eseguire vari script tramite Azioni per i controlli sui nodi di rete di destinazione. Allo stesso tempo, il lancio degli script ha portato a una serie di difficoltà, tra cui la necessità di supportare gli script, la loro consegna ai nodi di comunicazione e ai proxy, nonché il supporto per diverse versioni.

JavaScript per Zabbix

Nell'aprile 2019, Zabbix 4.2 è stato introdotto con la preelaborazione JavaScript. Molte persone si sono entusiasmate all'idea di abbandonare la scrittura di script che portano i dati da qualche parte, li digeriscono e li forniscono in un formato comprensibile a Zabbix, ed eseguono semplici controlli che riceveranno dati che non sono pronti per l'archiviazione e l'elaborazione da parte di Zabbix, e quindi elaborare questo flusso di dati utilizzando gli strumenti Zabbix e JavaScript. Insieme alla scoperta di basso livello e agli elementi dipendenti apparsi in Zabbix 3.4, abbiamo ottenuto un concetto abbastanza flessibile per l'ordinamento e la gestione dei dati ricevuti.

In Zabbix 4.4, come logica continuazione della pre-elaborazione in JavaScript, è apparso un nuovo metodo di notifica: Webhook, che può essere utilizzato per integrare facilmente le notifiche di Zabbix con applicazioni di terze parti.

JavaScript e Duktapes

Perché sono stati scelti JavaScript e Duktape? Sono state prese in considerazione varie opzioni per lingue e motori:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - Duktape
  • Javascript – Jerryscript
  • Python incorporato
  • Perla incorporata

I principali criteri di selezione sono stati la prevalenza, la facilità di integrazione del motore nel prodotto, il basso consumo di risorse e le prestazioni complessive del motore e la sicurezza dell'introduzione del codice in questo linguaggio nel monitoraggio. Sulla base della combinazione di indicatori, JavaScript ha vinto sul motore Duktape.

Risolviamo problemi pratici in Zabbix utilizzando JavaScript

Criteri di selezione e verifica delle prestazioni

Caratteristiche di Duktape:

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

  • Zabbix.log() - consente di scrivere messaggi con diversi livelli di dettaglio direttamente nel registro di Zabbix Server, che consente di correlare gli errori, ad esempio, in un Webhook, con lo stato del server.
  • CurlHttpRequest() - consente di effettuare richieste HTTP alla rete, su cui si basa l'utilizzo di Webhook.
  • atob() e btoa() - consente di codificare e decodificare stringhe in formato Base64.

NOTA. Duktape è conforme agli standard ACME. Zabbix utilizza la versione 2015 dello script. Le modifiche successive sono minori, quindi possono essere ignorate..

Magia Javascript

Tutta la magia di JavaScript risiede nella tipizzazione dinamica e nel casting dei tipi: stringa, numerico e booleano.

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

Nelle operazioni matematiche, i valori restituiti dagli operatori di funzione vengono convertiti in numeri. L'eccezione a tali operazioni è l'addizione, perché se almeno uno dei termini è una stringa, la conversione di stringa viene applicata a tutti i termini.

NOTA. I metodi responsabili di tali trasformazioni sono solitamente implementati nei prototipi padre dell'oggetto, valore di и accordare. valore di chiamato durante la conversione numerica e sempre prima del metodo accordare. Metodo valore di deve restituire valori primitivi, altrimenti il ​​suo risultato viene ignorato.

Un metodo viene chiamato su un oggetto valore di. Se non viene trovato o non restituisce un valore primitivo, viene chiamato il metodo accordare. Se il metodo accordare non trovato, ricerca valore di nel prototipo dell'oggetto e tutto viene ripetuto fino al completamento dell'elaborazione del valore e tutti i valori nell'espressione vengono convertiti nello stesso tipo. Se l'oggetto implementa un metodo accordare, che restituisce un valore primitivo, viene utilizzato per la conversione di stringhe. Tuttavia, il risultato dell'applicazione di questo metodo non è necessariamente una stringa.

Ad esempio, se for for oggetto 'obj' metodo è definito accordare,

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

metodo accordare restituisce esattamente una stringa e quando aggiungiamo una stringa con un numero, otteniamo una stringa incollata:

`obj + 1 // '2001'` 

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

Ma se riscrivi accordare, in modo che il metodo restituisca un numero, quando l'oggetto viene aggiunto, verrà eseguita un'operazione matematica con una conversione numerica e si otterrà il risultato dell'addizione matematica.

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

`obj + 1 // '2001'`

In questo caso, se eseguiamo l'addizione con una stringa, viene eseguita una conversione di stringa e otteniamo una stringa incollata.

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

Questo è il motivo di un gran numero di errori da parte degli utenti JavaScript inesperti.

Il metodo accordare puoi scrivere una funzione che aumenterà il valore corrente dell'oggetto di 1.

Risolviamo problemi pratici in Zabbix utilizzando JavaScript
Esecuzione dello script, a condizione che la variabile sia uguale a 3, ed è anche uguale a 4.

Se confrontato con un cast (==), il metodo viene eseguito ogni volta accordare con funzione di aumento del valore. Di conseguenza, ad ogni confronto successivo, il valore aumenta. Ciò può essere evitato utilizzando il confronto senza cast (===).

Risolviamo problemi pratici in Zabbix utilizzando JavaScript
Confronto senza casting di tipo

NOTA. Non usare il confronto del cast inutilmente.

Per script complessi, come Webhook con logica complessa, che richiedono il confronto con il casting di tipo, si consiglia di pre-scrivere controlli per i valori che restituiscono variabili e gestiscono incongruenze ed errori.

Media webhook

Alla fine del 2019 e all'inizio del 2020, il team di integrazione di Zabbix ha sviluppato attivamente webhook e integrazioni pronte all'uso fornite con la distribuzione di Zabbix.

Risolviamo problemi pratici in Zabbix utilizzando JavaScript
Link a documentazione

Pre-elaborazione

  • L'avvento della preelaborazione in JavaScript ha permesso di abbandonare la maggior parte degli script esterni e attualmente in Zabbix è possibile ottenere qualsiasi valore e convertirlo in un valore completamente diverso.
  • La preelaborazione in Zabbix è implementata dal codice JavaScript, che, una volta compilato in bytecode, viene convertito in una funzione che accetta un singolo valore come parametro APPREZZIAMO come stringa (una stringa può contenere sia una cifra che un numero).
  • Poiché l'output è una funzione, alla fine dello script è richiesto ritorno.
  • È possibile utilizzare macro personalizzate nel codice.
  • Le risorse possono essere limitate non solo a livello di sistema operativo, ma anche a livello di programmazione. Alla fase di preelaborazione vengono allocati un massimo di 10 megabyte di RAM e un limite di tempo di esecuzione di 10 secondi.

Risolviamo problemi pratici in Zabbix utilizzando JavaScript

NOTA. Il valore di timeout di 10 secondi è parecchio, perché la raccolta condizionale di migliaia di elementi di dati in 1 secondo secondo uno scenario di preelaborazione piuttosto "pesante" può rallentare Zabbix. Pertanto, non è consigliabile utilizzare la preelaborazione per eseguire script JavaScript completi tramite i cosiddetti elementi di dati ombra (elementi fittizi), che vengono eseguiti solo per eseguire la preelaborazione.

Puoi controllare il tuo codice tramite il test di pre-elaborazione o utilizzando l'utilità 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`

Compiti pratici

Compito 1

Sostituisci l'elemento calcolato con la pre-elaborazione.

condizione: Ottieni la temperatura in Fahrenheit dal sensore per memorizzarla in Celsius.

In precedenza, avremmo creato un elemento che raccoglie la temperatura in gradi Fahrenheit. Successivamente, un altro elemento di dati (calcolato) che convertirà Fahrenheit in Celsius utilizzando una formula.

Problematica:

  • È necessario duplicare gli elementi di dati e memorizzare tutti i valori nel database.
  • È necessario concordare gli intervalli per l'elemento di dati "padre" calcolato e utilizzato nella formula e per l'elemento di dati calcolato. In caso contrario, l'elemento calcolato potrebbe entrare in uno stato non supportato o calcolare un valore precedente, che influirà sull'affidabilità dei risultati del monitoraggio.

Una soluzione consisteva nell'allontanarsi da intervalli di controllo flessibili a favore di intervalli fissi per garantire che l'elemento calcolato venga valutato dopo l'elemento che riceve i dati (nel nostro caso, la temperatura in gradi Fahrenheit).

Ma se, ad esempio, utilizziamo il modello per controllare un numero elevato di dispositivi e il controllo viene eseguito una volta ogni 30 secondi, Zabbix "hackera" per 29 secondi e all'ultimo secondo inizia a controllare e calcolare. Questo crea una coda e influisce sulle prestazioni. Pertanto, si consiglia di utilizzare intervalli fissi solo se realmente necessario.

In questo problema, la soluzione ottimale è una preelaborazione JavaScript di una riga che converte i gradi Fahrenheit in gradi Celsius:

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

È semplice e veloce, non è necessario creare elementi di dati non necessari e conservarne una cronologia e puoi anche utilizzare intervalli flessibili per i controlli.

Risolviamo problemi pratici in Zabbix utilizzando JavaScript

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

Ma, se in una situazione ipotetica è necessario aggiungere il dato ricevuto, ad esempio, con una qualsiasi costante definita nella macro, si deve tener conto che il parametro APPREZZIAMO si espande in una stringa. In un'operazione di addizione di stringhe, due stringhe vengono semplicemente combinate in una sola.

Risolviamo problemi pratici in Zabbix utilizzando JavaScript

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

Per ottenere il risultato di un'operazione matematica, è necessario convertire i tipi dei valori ottenuti in un formato numerico. Per questo puoi usare la funzione parseInt (), che produce un numero intero, una funzione analizzareFloat(), che produce un decimale o una funzione numero, che restituisce un numero intero o un decimale.

Attività 2

Ottieni il tempo in secondi fino alla fine del certificato.

condizione: un servizio emette una data di scadenza del certificato nel formato "Feb 12 12:33:56 2022 GMT".

In ECMAScript5 Date.parse () accetta una data in formato ISO 8601 (AAAA-MM-GGTHH:mm:ss.sssZ). È necessario eseguire il cast di una stringa nel formato MMM GG AAAA HH:mm:ss ZZ

Problema: Il valore del mese è espresso come testo, non come numero. I dati in questo formato non sono accettati da Duktape.

Esempio di soluzione:

  • Prima di tutto viene dichiarata una variabile che assume un valore (l'intero script è una dichiarazione di variabili che sono elencate separate da virgole).

  • Nella prima riga otteniamo la data nel parametro APPREZZIAMO e separalo con spazi usando il metodo dividere. Pertanto, otteniamo un array, in cui ogni elemento dell'array, a partire dall'indice 0, corrisponde a un elemento data prima e dopo uno spazio. diviso(0) - mese, diviso(1) - numero, diviso(2) - una stringa con l'ora, ecc. Successivamente, è possibile accedere a ciascun elemento della data tramite l'indice nell'array.

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

  • Ogni mese (in ordine cronologico) corrisponde all'indice della sua posizione nell'array (da 0 a 11). Per convertire un valore di testo in un valore numerico, viene aggiunto uno all'indice del mese (poiché i mesi sono numerati a partire da 1). In questo caso l'espressione con l'aggiunta di uno viene presa tra parentesi, perché altrimenti si otterrà una stringa, non un numero. Alla fine lo facciamo fetta() - tagliare l'array dalla fine in modo da lasciare solo due caratteri (che è importante per i mesi con un 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 una stringa in formato ISO dai valori ottenuti mediante la consueta aggiunta di stringhe nell'ordine appropriato.

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

I dati nel formato risultante sono il numero di secondi dal 1970 a un certo punto nel futuro. È quasi impossibile utilizzare i dati nel formato ricevuto nei trigger, perché Zabbix consente di operare solo con le macro {Data} и {Tempo}, che restituiscono la data e l'ora in un formato intuitivo.

  • Possiamo quindi ottenere la data corrente in JavaScript nel formato Unix Timestamp e sottrarla dalla data di scadenza del certificato risultante per ottenere il numero di millisecondi da ora fino alla scadenza del certificato.

`now = Date.now();`

  • Dividiamo il valore ricevuto per mille per ottenere secondi in Zabbix.

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

Nel trigger puoi specificare l'espressione 'scorso' seguito da un insieme di cifre che corrisponde al numero di secondi nel periodo a cui si desidera rispondere, ad esempio in settimane. Pertanto, il trigger avviserà che il certificato scade in una settimana.

NOTA. Attenzione all'uso parseInt () in funzione ritornoper convertire il numero frazionario risultante dalla divisione di millisecondi in un numero intero. Puoi anche usare analizzareFloat() e memorizzare dati frazionari.

Guarda il rapporto

Fonte: habr.com

Aggiungi un commento