Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript
Tichon Uskow, Ingenieur des Zabbix-Integrationsteams

Zabbix ist eine anpassbare Plattform, die zur Überwachung jeglicher Art von Daten verwendet wird. Seit den frühesten Versionen von Zabbix hatten Überwachungsadministratoren die Möglichkeit, verschiedene Skripte über auszuführen Aktionen zur Überprüfung von Zielnetzwerkknoten. Gleichzeitig führte die Einführung von Skripten zu einer Reihe von Schwierigkeiten, darunter die Notwendigkeit, Skripte zu unterstützen, ihre Bereitstellung an Kommunikationsknoten und Proxys sowie die Unterstützung verschiedener Versionen.

JavaScript für Zabbix

Im April 2019 wurde Zabbix 4.2 mit JavaScript-Vorverarbeitung eingeführt. Viele Leute waren begeistert von der Idee, das Schreiben von Skripten aufzugeben, die Daten irgendwohin bringen, verarbeiten und in einem Format bereitstellen, das Zabbix versteht, und einfache Prüfungen durchzuführen, die Daten empfangen, die nicht für die Speicherung und Verarbeitung durch Zabbix bereit sind, und Verarbeiten Sie diesen Datenstrom dann mit den Tools Zabbix und JavaScript. In Verbindung mit Low-Level-Discovery und abhängigen Elementen, die in Zabbix 3.4 erschienen, haben wir ein ziemlich flexibles Konzept zum Sortieren und Verwalten der empfangenen Daten erhalten.

In Zabbix 4.4 ist als logische Fortsetzung der Vorverarbeitung in JavaScript eine neue Benachrichtigungsmethode erschienen – Webhook, mit der sich Zabbix-Benachrichtigungen einfach in Anwendungen von Drittanbietern integrieren lassen.

JavaScript und Duktapes

Warum wurden JavaScript und Duktape ausgewählt? Es wurden verschiedene Optionen für Sprachen und Engines in Betracht gezogen:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - Duktape
  • Javascript - JerryScript
  • Eingebettetes Python
  • Eingebettetes Perl

Die wichtigsten Auswahlkriterien waren Verbreitung, einfache Integration der Engine in das Produkt, geringer Ressourcenverbrauch und Gesamtleistung der Engine sowie die Sicherheit der Einführung von Code in dieser Sprache in die Überwachung. Basierend auf der Kombination von Indikatoren gewann JavaScript auf der Duktape-Engine.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript

Auswahlkriterien und Leistungstests

Duktape-Funktionen:

— Standard ECMAScript E5/E5.1
— Zabbix-Module für Duktape:

  • Zabbix.log() – ermöglicht es Ihnen, Nachrichten mit unterschiedlichem Detaillierungsgrad direkt in das Zabbix-Serverprotokoll zu schreiben, was es ermöglicht, Fehler, beispielsweise in einem Webhook, mit dem Serverstatus zu korrelieren.
  • CurlHttpRequest() – ermöglicht es Ihnen, HTTP-Anfragen an das Netzwerk zu stellen, auf denen die Verwendung von Webhook basiert.
  • atob() und btoa() – ermöglicht das Kodieren und Dekodieren von Zeichenfolgen im Base64-Format.

HINWEIS. Duktape entspricht den ACME-Standards. Zabbix verwendet die Version 2015 des Skripts. Nachfolgende Änderungen sind geringfügig und können daher ignoriert werden..

JavaScript-Magie

Die ganze Magie von JavaScript liegt in der dynamischen Typisierung und Typumwandlung: Zeichenfolge, Zahl und Boolescher Wert.

Dies bedeutet, dass es nicht notwendig ist, im Voraus zu deklarieren, welchen Typ die Variable einen Wert zurückgeben soll.

Bei mathematischen Operationen werden die von Funktionsoperatoren zurückgegebenen Werte in Zahlen umgewandelt. Die Ausnahme bei solchen Operationen ist die Addition, denn wenn mindestens einer der Begriffe eine Zeichenfolge ist, wird die Zeichenfolgenkonvertierung auf alle Begriffe angewendet.

HINWEIS. Die für solche Transformationen verantwortlichen Methoden werden normalerweise in den übergeordneten Prototypen des Objekts implementiert. Wert von и toString. Wert von Wird während der numerischen Konvertierung und immer vor der Methode aufgerufen toString. Methode Wert von muss primitive Werte zurückgeben, andernfalls wird das Ergebnis ignoriert.

Eine Methode wird für ein Objekt aufgerufen Wert von. Wenn es nicht gefunden wird oder keinen primitiven Wert zurückgibt, wird die Methode aufgerufen toString. Wenn die Methode toString nicht gefunden, gesucht Wert von im Prototyp des Objekts, und alles wird wiederholt, bis die Verarbeitung des Werts abgeschlossen ist und alle Werte im Ausdruck in denselben Typ umgewandelt werden. Wenn das Objekt eine Methode implementiert toString, der einen primitiven Wert zurückgibt, dann wird dieser für die String-Konvertierung verwendet. Das Ergebnis der Anwendung dieser Methode ist jedoch nicht unbedingt eine Zeichenfolge.

Wenn zum Beispiel für for object 'obj' Methode ist definiert toString,

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

метод toString gibt genau einen String zurück, und wenn wir einen String mit einer Zahl hinzufügen, erhalten wir einen geklebten String:

`obj + 1 // '2001'` 

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

Aber wenn Sie umschreiben toStringDamit die Methode eine Zahl zurückgibt, wird beim Hinzufügen des Objekts eine mathematische Operation mit numerischer Konvertierung ausgeführt und das Ergebnis der mathematischen Addition erhalten.

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

`obj + 1 // '2001'`

Wenn wir in diesem Fall eine Addition mit einer Zeichenfolge durchführen, wird eine Zeichenfolgenkonvertierung durchgeführt und wir erhalten eine geklebte Zeichenfolge.

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

Dies ist der Grund für eine große Anzahl von Fehlern bei unerfahrenen JavaScript-Benutzern.

Die Methode toString Sie können eine Funktion schreiben, die den aktuellen Wert des Objekts um 1 erhöht.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript
Ausführung des Skripts, vorausgesetzt, die Variable ist gleich 3 und sie ist auch gleich 4.

Beim Vergleich mit einer Umwandlung (==) wird die Methode jedes Mal ausgeführt toString mit Wertsteigerungsfunktion. Dementsprechend erhöht sich der Wert mit jedem weiteren Vergleich. Dies kann durch die Verwendung eines Non-Cast-Vergleichs (===) vermieden werden.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript
Vergleich ohne Typguss

HINWEIS. Benutzen Sie Besetzungsvergleiche nicht unnötig.

Für komplexe Skripte wie Webhooks mit komplexer Logik, die einen Vergleich mit Typumwandlung erfordern, empfiehlt es sich, vorab Prüfungen für die Werte zu schreiben, die Variablen zurückgeben und Inkonsistenzen und Fehler behandeln.

Webhook-Medien

Ende 2019 und Anfang 2020 hat das Zabbix-Integrationsteam aktiv Webhooks und sofort einsatzbereite Integrationen entwickelt, die mit der Zabbix-Distribution geliefert werden.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript
Link zu Dokumentation

Anarbeitung

  • Das Aufkommen der Vorverarbeitung in JavaScript machte es möglich, auf die meisten externen Skripte zu verzichten, und derzeit können Sie in Zabbix jeden Wert abrufen und ihn in einen völlig anderen Wert konvertieren.
  • Die Vorverarbeitung in Zabbix wird durch JavaScript-Code implementiert, der beim Kompilieren in Bytecode in eine Funktion umgewandelt wird, die einen einzelnen Wert als Parameter annimmt Wert als String (ein String kann sowohl eine Ziffer als auch eine Zahl enthalten).
  • Da es sich bei der Ausgabe um eine Funktion handelt, ist am Ende ein Skript erforderlich Rückkehr.
  • Es ist möglich, benutzerdefinierte Makros im Code zu verwenden.
  • Ressourcen können nicht nur auf Betriebssystemebene, sondern auch programmgesteuert begrenzt werden. Dem Vorverarbeitungsschritt werden maximal 10 Megabyte RAM und eine Laufzeitbegrenzung von 10 Sekunden zugewiesen.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript

HINWEIS. Der Timeout-Wert von 10 Sekunden ist ziemlich hoch, da das bedingte Sammeln von Tausenden von Datenelementen in 1 Sekunde gemäß einem eher „schweren“ Vorverarbeitungsszenario Zabbix verlangsamen kann. Daher wird nicht empfohlen, die Vorverarbeitung zum Ausführen vollwertiger JavaScript-Skripte über die sogenannten Schattendatenelemente (Dummy-Elemente) zu verwenden, die nur zur Durchführung der Vorverarbeitung ausgeführt werden.

Sie können Ihren Code durch den Vorverarbeitungstest oder mithilfe des Dienstprogramms überprüfen 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`

Praktische Aufgaben

Aufgabe 1

Berechnetes Element durch Vorverarbeitung ersetzen.

Bedingung: Rufen Sie die Temperatur in Fahrenheit vom Sensor ab, um sie in Celsius zu speichern.

Zuvor haben wir ein Element erstellt, das die Temperatur in Grad Fahrenheit erfasst. Danach ein weiteres Datenelement (berechnet), das Fahrenheit mithilfe einer Formel in Celsius umrechnen würde.

Probleme:

  • Es ist notwendig, Datenelemente zu duplizieren und alle Werte in der Datenbank zu speichern.
  • Sie müssen sich auf die Intervalle für das „übergeordnete“ Datenelement, das berechnet und in der Formel verwendet wird, und für das berechnete Datenelement einigen. Andernfalls geht das berechnete Element möglicherweise in einen nicht unterstützten Zustand über oder berechnet einen vorherigen Wert, was sich auf die Zuverlässigkeit der Überwachungsergebnisse auswirkt.

Eine Lösung bestand darin, von flexiblen Prüfintervallen zu festen Intervallen zu wechseln, um sicherzustellen, dass das berechnete Element nach dem Element ausgewertet wird, das die Daten empfängt (in unserem Fall die Temperatur in Grad Fahrenheit).

Wenn wir jedoch beispielsweise die Vorlage verwenden, um eine große Anzahl von Geräten zu überprüfen, und die Überprüfung alle 30 Sekunden durchgeführt wird, „hackt“ Zabbix 29 Sekunden lang und beginnt in der letzten Sekunde mit der Überprüfung und Berechnung. Dadurch entsteht eine Warteschlange und die Leistung wird beeinträchtigt. Daher empfiehlt es sich, feste Intervalle nur dann zu nutzen, wenn es wirklich notwendig ist.

Bei diesem Problem ist die optimale Lösung eine einzeilige JavaScript-Vorverarbeitung, die Grad Fahrenheit in Grad Celsius umrechnet:

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

Es geht schnell und einfach, Sie müssen keine unnötigen Datenelemente erstellen und einen Verlauf darüber führen, und Sie können auch flexible Intervalle für Überprüfungen verwenden.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript

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

Wenn es jedoch in einer hypothetischen Situation erforderlich ist, das empfangene Datenelement beispielsweise mit einer im Makro definierten Konstante zu ergänzen, muss dieser Parameter berücksichtigt werden Wert wird zu einer Zeichenfolge erweitert. Bei einer String-Additionsoperation werden einfach zwei Strings zu einem kombiniert.

Wir lösen praktische Probleme in Zabbix mithilfe von JavaScript

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

Um das Ergebnis einer mathematischen Operation zu erhalten, ist es notwendig, die Typen der erhaltenen Werte in ein numerisches Format umzuwandeln. Hierzu können Sie die Funktion nutzen parseInt (), was eine Ganzzahl, eine Funktion, erzeugt parseFloat(), was eine Dezimalzahl oder eine Funktion erzeugt Anzahl, das eine Ganzzahl oder Dezimalzahl zurückgibt.

Aufgabe 2

Erhalten Sie die Zeit in Sekunden bis zum Ende des Zertifikats.

Bedingung: Ein Dienst gibt ein Zertifikatsablaufdatum im Format „12. Februar 12:33:56 2022 GMT“ aus.

In ECMAScript5 Date.parse () akzeptiert ein Datum im ISO 8601-Format (JJJJ-MM-TTTHH:mm:ss.sssZ). Es ist notwendig, eine Zeichenfolge im Format MMM TT JJJJ HH:mm:ss ZZ umzuwandeln

Problem: Der Monatswert wird als Text und nicht als Zahl ausgedrückt. Daten in diesem Format werden von Duktape nicht akzeptiert.

Lösungsbeispiel:

  • Zunächst wird eine Variable deklariert, die einen Wert annimmt (das gesamte Skript ist eine Deklaration von Variablen, die durch Kommas getrennt aufgelistet werden).

  • In der ersten Zeile erhalten wir im Parameter das Datum Wert und trennen Sie es mithilfe der Methode durch Leerzeichen gespalten. Somit erhalten wir ein Array, in dem jedes Element des Arrays, beginnend bei Index 0, einem Datumselement vor und nach einem Leerzeichen entspricht. teilen(0) - Monat, teilen(1) - Nummer, teilen(2) - eine Zeichenfolge mit Zeit usw. Danach kann auf jedes Element des Datums über den Index im Array zugegriffen werden.

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

  • Jeder Monat (in chronologischer Reihenfolge) entspricht dem Index seiner Position im Array (von 0 bis 11). Um einen Textwert in einen numerischen Wert umzuwandeln, wird eins zum Monatsindex hinzugefügt (da Monate beginnend bei 1 nummeriert werden). In diesem Fall wird der Ausdruck mit dem Zusatz eins in Klammern gesetzt, da sonst eine Zeichenfolge und keine Zahl entsteht. Am Ende tun wir es Scheibe() - Schneiden Sie das Array vom Ende ab, sodass nur noch zwei Zeichen übrig bleiben (was für Monate mit einer zweistelligen Zahl wichtig ist).

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

  • Aus den erhaltenen Werten bilden wir durch übliche Addition von Strings in der entsprechenden Reihenfolge einen String im ISO-Format.

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

Die Daten im resultierenden Format sind die Anzahl der Sekunden von 1970 bis zu einem Zeitpunkt in der Zukunft. Es ist nahezu unmöglich, Daten im empfangenen Format in Triggern zu verwenden, da Sie mit Zabbix nur mit Makros arbeiten können {Datum} и {Zeit}, die Datum und Uhrzeit in einem benutzerfreundlichen Format zurückgeben.

  • Wir können dann das aktuelle Datum in JavaScript im Unix-Zeitstempelformat abrufen und es vom resultierenden Ablaufdatum des Zertifikats subtrahieren, um die Anzahl der Millisekunden von jetzt an bis zum Ablauf des Zertifikats zu erhalten.

`now = Date.now();`

  • Wir teilen den empfangenen Wert durch tausend, um Sekunden in Zabbix zu erhalten.

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

Im Trigger können Sie den Ausdruck angeben 'zuletzt' gefolgt von einer Reihe von Ziffern, die der Anzahl der Sekunden in dem Zeitraum entsprechen, auf den Sie antworten möchten, beispielsweise in Wochen. Daher benachrichtigt der Auslöser, dass das Zertifikat in einer Woche abläuft.

HINWEIS. Achten Sie auf die Verwendung parseInt () in Funktion Rückkehrum die Bruchzahl, die sich aus der Division von Millisekunden ergibt, in eine ganze Zahl umzuwandeln. Sie können auch verwenden parseFloat() und Bruchdaten speichern.

Bericht ansehen

Source: habr.com

Kommentar hinzufügen