Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript
Tikhon Ouskov, ingénieur de l'équipe d'intégration Zabbix

Zabbix est une plate-forme personnalisable utilisée pour surveiller tout type de données. Depuis les premières versions de Zabbix, les administrateurs de surveillance ont la possibilité d'exécuter divers scripts via Actions pour les vérifications sur les nœuds de réseau cibles. Dans le même temps, le lancement de scripts a entraîné un certain nombre de difficultés, notamment la nécessité de prendre en charge les scripts, leur livraison aux nœuds de communication et aux proxys, ainsi que la prise en charge de différentes versions.

JavaScript pour Zabbix

En avril 2019, Zabbix 4.2 a été introduit avec le prétraitement JavaScript. Beaucoup de gens se sont enthousiasmés à l'idée d'abandonner l'écriture de scripts qui prennent des données quelque part, les digèrent et les fournissent dans un format que Zabbix comprend, et effectuent des vérifications simples qui recevront des données qui ne sont pas prêtes pour le stockage et le traitement par Zabbix, et traitez ensuite ce flux de données à l'aide des outils Zabbix et JavaScript. En conjonction avec la découverte de bas niveau et les éléments dépendants apparus dans Zabbix 3.4, nous avons obtenu un concept assez flexible pour trier et gérer les données reçues.

Dans Zabbix 4.4, suite logique du prétraitement en JavaScript, une nouvelle méthode de notification est apparue - Webhook, qui peut être utilisée pour intégrer facilement les notifications Zabbix à des applications tierces.

JavaScript et Duktapes

Pourquoi JavaScript et Duktape ont-ils été choisis ? Différentes options de langages et de moteurs ont été envisagées :

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - Duktape
  • Javascript-JerryScript
  • Python intégré
  • Perl intégré

Les principaux critères de sélection étaient la prévalence, la facilité d'intégration du moteur dans le produit, la faible consommation de ressources et les performances globales du moteur, et la sécurité d'introduire du code dans ce langage dans le monitoring. Basé sur la combinaison d'indicateurs, JavaScript a gagné sur le moteur Duktape.

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript

Critères de sélection et tests de performance

Caractéristiques de Duktape :

- Standard ECMAScript E5/E5.1
— Modules Zabbix pour Duktape :

  • Zabbix.log() - vous permet d'écrire des messages avec différents niveaux de détail directement dans le journal du serveur Zabbix, ce qui permet de corréler les erreurs, par exemple, dans un Webhook avec l'état du serveur.
  • CurlHttpRequest() - vous permet de faire des requêtes HTTP au réseau, sur lequel l'utilisation de Webhook est basée.
  • atob() et btoa() - vous permettent d'encoder et de décoder des chaînes au format Base64.

NOTE. Duktape est conforme aux normes ACME. Zabbix utilise la version 2015 du script. Les modifications ultérieures sont mineures, elles peuvent donc être ignorées..

Magie JavaScript

Toute la magie de JavaScript réside dans le typage dynamique et la conversion des types : chaîne, numérique et booléen.

Cela signifie qu'il n'est pas nécessaire de déclarer à l'avance de quel type la variable doit renvoyer une valeur.

Dans les opérations mathématiques, les valeurs renvoyées par les opérateurs de fonction sont converties en nombres. L'exception à ces opérations est l'addition, car si au moins un des termes est une chaîne, la conversion de chaîne est appliquée à tous les termes.

NOTE. Les méthodes responsables de ces conversions sont généralement implémentées dans les prototypes parents de l'objet, valeur de и versChaîne. valeur de appelée lors de la conversion numérique et toujours avant la méthode versChaîne. Méthode valeur de doit renvoyer des valeurs primitives, sinon son résultat est ignoré.

Une méthode est appelée sur un objet valeur de. S'il n'est pas trouvé ou ne renvoie pas de valeur primitive, la méthode est appelée versChaîne. Si la méthode versChaîne introuvable, recherche valeur de dans le prototype de l'objet, et tout est répété jusqu'à ce que le traitement de la valeur soit terminé et que toutes les valeurs de l'expression soient converties dans le même type. Si l'objet implémente une méthode versChaîne, qui renvoie une valeur primitive, alors c'est elle qui est utilisée pour la conversion de chaîne. Cependant, le résultat de l'application de cette méthode n'est pas nécessairement une chaîne.

Par exemple, si pour l'objet 'obj' la méthode est définie versChaîne,

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

метод versChaîne renvoie exactement une chaîne, et lors de l'ajout d'une chaîne avec un nombre, nous obtenons une chaîne collée :

`obj + 1 // '2001'` 

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

Mais si vous réécrivez versChaîne, de sorte que la méthode renvoie un nombre, lorsque l'objet est ajouté, une opération mathématique avec une conversion numérique sera effectuée et le résultat de l'addition mathématique sera obtenu.

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

`obj + 1 // '2001'`

Dans ce cas, si nous effectuons une addition avec une chaîne, une conversion de chaîne est effectuée et nous obtenons une chaîne collée.

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

C'est la raison d'un grand nombre d'erreurs commises par les utilisateurs novices de JavaScript.

La méthode versChaîne vous pouvez écrire une fonction qui augmentera la valeur actuelle de l'objet de 1.

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript
Exécution du script, à condition que la variable soit égale à 3, et qu'elle soit aussi égale à 4.

Par rapport à un cast (==), la méthode est exécutée à chaque fois versChaîne avec fonction d'augmentation de valeur. En conséquence, à chaque comparaison ultérieure, la valeur augmente. Cela peut être évité en utilisant une comparaison non cast (===).

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript
Comparaison sans coulée de type

NOTE. N'utilisez pas inutilement la comparaison des acteurs.

Pour les scripts complexes, tels que les Webhooks avec une logique complexe, qui nécessitent une comparaison avec le casting de type, il est recommandé de pré-écrire des vérifications pour les valeurs qui renvoient des variables et de gérer les incohérences et les erreurs.

Webhook Média

Fin 2019 et début 2020, l'équipe d'intégration de Zabbix a activement développé des Webhooks et des intégrations prêtes à l'emploi fournies avec la distribution Zabbix.

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript
Lien vers le documentation

Prétraitement

  • L'avènement du prétraitement en JavaScript a permis d'abandonner la plupart des scripts externes, et actuellement dans Zabbix, vous pouvez obtenir n'importe quelle valeur et la convertir en une valeur complètement différente.
  • Le prétraitement dans Zabbix est implémenté par du code JavaScript, qui, lorsqu'il est compilé en bytecode, est converti en une fonction qui prend une valeur unique comme paramètre Plus-value sous forme de chaîne (une chaîne peut contenir à la fois un chiffre et un nombre).
  • Étant donné que la sortie est une fonction, à la fin du script est requis retourner.
  • Il est possible d'utiliser des macros personnalisées dans le code.
  • Les ressources peuvent être limitées non seulement au niveau du système d'exploitation, mais également par programmation. L'étape de prétraitement se voit allouer un maximum de 10 mégaoctets de RAM et une limite de temps d'exécution de 10 secondes.

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript

NOTE. La valeur du délai d'attente de 10 secondes est beaucoup, car la collecte conditionnelle de milliers d'éléments de données en 1 seconde selon un scénario de prétraitement plutôt "lourd" peut ralentir Zabbix. Par conséquent, il n'est pas recommandé d'utiliser le prétraitement pour exécuter des scripts JavaScript à part entière via les éléments de données fantômes (éléments factices), qui ne sont exécutés que pour effectuer le prétraitement..

Vous pouvez vérifier votre code via le test de prétraitement ou en utilisant l'utilitaire 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`

Tâches pratiques

Tâche 1

Remplacez l'élément calculé par le prétraitement.

Condition: Obtenir la température en Fahrenheit du capteur pour la stocker en Celsius.

Auparavant, nous créions un élément qui collecte la température en degrés Fahrenheit. Après cela, un autre élément de données (calculé) qui convertirait Fahrenheit en Celsius en utilisant une formule.

Problèmes:

  • Il est nécessaire de dupliquer les éléments de données et de stocker toutes les valeurs dans la base de données.
  • Vous devez convenir des intervalles pour l'élément de données "parent" qui est calculé et utilisé dans la formule, et pour l'élément de données calculé. Sinon, l'élément calculé peut entrer dans un état non pris en charge ou calculer une valeur précédente, ce qui affectera la fiabilité des résultats de surveillance.

Une solution consistait à s'éloigner des intervalles de vérification flexibles au profit d'intervalles fixes pour s'assurer que l'élément calculé est évalué après l'élément qui reçoit les données (dans notre cas, la température en degrés Fahrenheit).

Mais si, par exemple, nous utilisons le modèle pour vérifier un grand nombre d'appareils et que la vérification est effectuée une fois toutes les 30 secondes, Zabbix "pirate" pendant 29 secondes et à la dernière seconde, il commence à vérifier et à calculer. Cela crée une file d'attente et affecte les performances. Par conséquent, il est recommandé d'utiliser des intervalles fixes uniquement si cela est vraiment nécessaire.

Dans ce problème, la solution optimale est un prétraitement JavaScript sur une ligne qui convertit les degrés Fahrenheit en degrés Celsius :

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

C'est rapide et facile, vous n'avez pas besoin de créer des éléments de données inutiles et d'en conserver un historique, et vous pouvez également utiliser des intervalles flexibles pour les vérifications.

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript

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

Mais, si dans une situation hypothétique, il est nécessaire d'ajouter l'élément de données reçu, par exemple, avec n'importe quelle constante définie dans la macro, il faut tenir compte du fait que le paramètre Plus-value se développe en une chaîne. Dans une opération d'addition de chaînes, deux chaînes sont simplement combinées en une seule.

Nous résolvons des problèmes pratiques dans Zabbix en utilisant JavaScript

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

Pour obtenir le résultat d'une opération mathématique, il est nécessaire de convertir les types des valeurs obtenues au format numérique. Pour cela, vous pouvez utiliser la fonction parseInt (), qui produit un entier, une fonction analyserFloat(), qui produit un nombre décimal, ou une fonction nombre, qui renvoie un nombre entier ou décimal.

Tâche 2

Obtenez le temps en secondes jusqu'à la fin du certificat.

Condition: un service émet une date d'expiration du certificat au format "Feb 12 12:33:56 2022 GMT".

Dans ECMAScript5 Date.parse () accepte une date au format ISO 8601 (AAAA-MM-JJTHH:mm:ss.sssZ). Il est nécessaire de lui envoyer une chaîne au format MMM JJ AAAA HH:mm:ss ZZ

problème: La valeur du mois est exprimée sous forme de texte et non sous forme de nombre. Les données dans ce format ne sont pas acceptées par Duktape.

Exemple de solution:

  • Tout d'abord, une variable est déclarée qui prend une valeur (le script entier est une déclaration de variables qui sont listées séparées par des virgules).

  • Dans la première ligne, nous obtenons la date dans le paramètre Plus-value et séparez-le par des espaces en utilisant la méthode scission. Ainsi, nous obtenons un tableau, où chaque élément du tableau, commençant à l'index 0, correspond à un élément de date avant et après un espace. diviser(0) - mois, diviser(1) - nombre, diviser(2) - une chaîne avec l'heure, etc. Ensuite, chaque élément de la date est accessible par index dans le tableau.

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

  • Chaque mois (dans l'ordre chronologique) correspond à l'indice de sa position dans le tableau (de 0 à 11). Pour convertir une valeur textuelle en valeur numérique, un est ajouté à l'index des mois (car les mois sont numérotés à partir de 1). Dans ce cas, l'expression avec l'ajout d'un est prise entre parenthèses, car sinon une chaîne sera obtenue, pas un nombre. A la fin on fait tranche() - couper le tableau à partir de la fin pour ne laisser que deux caractères (ce qui est important pour les mois avec un nombre à deux chiffres).

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

  • Nous formons une chaîne au format ISO à partir des valeurs obtenues par l'ajout habituel de chaînes dans l'ordre approprié.

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

Les données dans le format résultant sont le nombre de secondes de 1970 à un certain point dans le futur. Il est presque impossible d'utiliser des données au format reçu dans les déclencheurs, car Zabbix vous permet de fonctionner uniquement avec des macros {Date} и {Temps}, qui renvoient la date et l'heure dans un format convivial.

  • Nous pouvons ensuite obtenir la date actuelle en JavaScript au format Unix Timestamp et la soustraire de la date d'expiration du certificat résultant pour obtenir le nombre de millisecondes à partir de maintenant jusqu'à l'expiration du certificat.

`now = Date.now();`

  • Nous divisons la valeur reçue par mille pour obtenir des secondes dans Zabbix.

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

Dans le déclencheur, vous pouvez spécifier l'expression 'dernier' suivi d'un ensemble de chiffres correspondant au nombre de secondes de la période à laquelle vous souhaitez répondre, par exemple, en semaines. Ainsi, le déclencheur notifiera que le certificat expire dans une semaine.

NOTE. Attention à l'utilisation parseInt () en fonction retournerpour convertir le nombre fractionnaire résultant de la division des millisecondes en un entier. Vous pouvez aussi utiliser analyserFloat() et stocker des données fractionnaires.

Regarder le rapport

Source: habr.com

Ajouter un commentaire