We lossen praktische problemen in Zabbix op met behulp van JavaScript

We lossen praktische problemen in Zabbix op met behulp van JavaScript
Tichon Uskov, Zabbix-integratieteamingenieur

Zabbix is ​​​​een aanpasbaar platform dat wordt gebruikt om alle soorten gegevens te controleren. Sinds de vroegste versies van Zabbix hebben monitoringbeheerders de mogelijkheid gehad om verschillende scripts uit te voeren via Acties voor controles op doelnetwerkknooppunten. Tegelijkertijd leidde de lancering van scripts tot een aantal problemen, waaronder de noodzaak om scripts te ondersteunen, hun levering aan communicatieknooppunten en proxy's, evenals ondersteuning voor verschillende versies.

JavaScript voor Zabbix

In april 2019 werd Zabbix 4.2 geïntroduceerd met JavaScript-voorverwerking. Veel mensen raakten enthousiast over het idee om af te zien van het schrijven van scripts die gegevens ergens naartoe brengen, verwerken en verstrekken in een formaat dat Zabbix begrijpt, en eenvoudige controles uitvoeren om gegevens te ontvangen die niet klaar zijn voor opslag en verwerking door Zabbix, en verwerk deze gegevensstroom vervolgens met Zabbix- en JavaScript-tools. In combinatie met detectie op laag niveau en afhankelijke items die verschenen in Zabbix 3.4, kregen we een redelijk flexibel concept voor het sorteren en beheren van de ontvangen gegevens.

In Zabbix 4.4 is, als een logische voortzetting van voorverwerking in JavaScript, een nieuwe meldingsmethode verschenen - Webhook, die kan worden gebruikt om Zabbix-meldingen eenvoudig te integreren met applicaties van derden.

JavaScript en Duktapes

Waarom is er gekozen voor JavaScript en Duktape? Er werden verschillende opties voor talen en motoren overwogen:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - Duktape
  • Javascript - JerryScript
  • Ingebedde python
  • Ingebedde Perl

De belangrijkste selectiecriteria waren prevalentie, gemakkelijke integratie van de engine in het product, laag verbruik van hulpbronnen en algehele prestaties van de engine, en de veiligheid van het introduceren van code in deze taal in monitoring. Op basis van de combinatie van indicatoren won JavaScript op de Duktape-engine.

We lossen praktische problemen in Zabbix op met behulp van JavaScript

Selectiecriteria en prestatietesten

Kenmerken van Duktape:

— Standaard ECMAScript E5/E5.1
— Zabbix-modules voor Duktape:

  • Zabbix.log() - stelt u in staat om berichten met verschillende detailniveaus rechtstreeks in het Zabbix Server-logboek te schrijven, wat het mogelijk maakt om fouten, bijvoorbeeld in een webhook, te correleren met de serverstatus.
  • CurlHttpRequest() - hiermee kunt u HTTP-verzoeken doen aan het netwerk waarop het gebruik van Webhook is gebaseerd.
  • atob() en btoa() - hiermee kunt u strings in Base64-indeling coderen en decoderen.

NOTE. Duktape voldoet aan de ACME-normen. Zabbix gebruikt de 2015-versie van het script. Latere wijzigingen zijn klein, dus ze kunnen worden genegeerd..

JavaScript-magie

Alle magie van JavaScript ligt in dynamisch typen en typecasting: string, numeriek en booleaans.

Dit betekent dat het niet nodig is om vooraf aan te geven welk type de variabele een waarde moet teruggeven.

Bij wiskundige bewerkingen worden de waarden die door functie-operatoren worden geretourneerd, omgezet in getallen. De uitzondering op dergelijke bewerkingen is optellen, want als ten minste één van de termen een tekenreeks is, wordt tekenreeksconversie toegepast op alle termen.

NOTE. De methoden die verantwoordelijk zijn voor dergelijke transformaties worden meestal geïmplementeerd in de bovenliggende prototypen van het object, waarde van и naarString. waarde van aangeroepen tijdens numerieke conversie en altijd vóór de methode naarString. Methode waarde van moet primitieve waarden retourneren, anders wordt het resultaat genegeerd.

Een methode wordt aangeroepen op een object waarde van. Als deze niet wordt gevonden of geen primitieve waarde retourneert, wordt de methode aangeroepen naarString. Als de methode naarString niet gevonden, zoeken waarde van in het prototype van het object, en alles wordt herhaald totdat de verwerking van de waarde is voltooid en alle waarden in de uitdrukking naar hetzelfde type zijn gegoten. Als het object een methode implementeert naarString, die een primitieve waarde retourneert, dan wordt deze gebruikt voor tekenreeksconversie. Het resultaat van het toepassen van deze methode is echter niet noodzakelijkerwijs een string.

Als bijvoorbeeld voor voor object 'obj' methode is gedefinieerd naarString,

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

метод naarString geeft precies een string terug, en als we een string met een getal toevoegen, krijgen we een gelijmde string:

`obj + 1 // '2001'` 

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

Maar als je herschrijft naarString, zodat de methode een getal retourneert, wanneer het object wordt toegevoegd, wordt een wiskundige bewerking met een numerieke conversie uitgevoerd en wordt het resultaat van wiskundige optelling verkregen.

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

`obj + 1 // '2001'`

Als we in dit geval optellen met een string, wordt er een stringconversie uitgevoerd en krijgen we een gelijmde string.

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

Dit is de reden voor een groot aantal fouten door beginnende JavaScript-gebruikers.

De methode naarString je kunt een functie schrijven die de huidige waarde van het object met 1 verhoogt.

We lossen praktische problemen in Zabbix op met behulp van JavaScript
Uitvoering van het script, op voorwaarde dat de variabele gelijk is aan 3, en deze ook gelijk is aan 4.

In vergelijking met een cast (==) wordt de methode elke keer uitgevoerd naarString met waardeverhogende functie. Dienovereenkomstig neemt bij elke volgende vergelijking de waarde toe. Dit kan worden vermeden door niet-castvergelijking te gebruiken (===).

We lossen praktische problemen in Zabbix op met behulp van JavaScript
Vergelijking zonder typegieten

NOTE. Gebruik Cast-vergelijking niet onnodig.

Voor complexe scripts, zoals webhooks met complexe logica, die vergelijking met typecasting vereisen, wordt aanbevolen om vooraf controles uit te schrijven voor de waarden die variabelen retourneren en omgaan met inconsistenties en fouten.

Webhook-media

Eind 2019 en begin 2020 heeft het Zabbix-integratieteam actief webhooks en kant-en-klare integraties ontwikkeld die bij de Zabbix-distributie horen.

We lossen praktische problemen in Zabbix op met behulp van JavaScript
Link naar de documentatie

Voorverwerking

  • De komst van voorverwerking in JavaScript maakte het mogelijk om de meeste externe scripts achterwege te laten, en momenteel kun je in Zabbix elke waarde krijgen en deze naar een geheel andere waarde converteren.
  • Voorverwerking in Zabbix wordt geïmplementeerd door JavaScript-code, die, wanneer gecompileerd in bytecode, wordt omgezet in een functie die een enkele waarde als parameter aanneemt waarde als een string (een string kan zowel een cijfer als een getal bevatten).
  • Aangezien de uitvoer een functie is, is aan het einde van het script vereist terugkeer.
  • Het is mogelijk om aangepaste macro's in de code te gebruiken.
  • Bronnen kunnen niet alleen op besturingssysteemniveau worden beperkt, maar ook programmatisch. De voorverwerkingsstap krijgt maximaal 10 megabyte RAM toegewezen en een looptijdlimiet van 10 seconden.

We lossen praktische problemen in Zabbix op met behulp van JavaScript

NOTE. De time-outwaarde van 10 seconden is vrij veel, omdat het verzamelen van voorwaardelijke duizenden gegevensitems in 1 seconde volgens een nogal "zwaar" voorverwerkingsscenario Zabbix kan vertragen. Daarom wordt het niet aanbevolen om preprocessing te gebruiken om volwaardige JavaScript-scripts uit te voeren via de zogenaamde schaduwgegevenselementen (dummy-items), die alleen worden uitgevoerd om preprocessing uit te voeren.

U kunt uw code controleren via de preprocessing-test of met behulp van het hulpprogramma 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 taken

Taak 1

Vervang berekend item door voorverwerking.

Staat: Haal de temperatuur in Fahrenheit van de sensor om op te slaan in Celsius.

Voorheen maakten we een item dat de temperatuur in graden Fahrenheit verzamelt. Daarna nog een gegevensitem (berekend) dat Fahrenheit naar Celsius zou converteren met behulp van een formule.

Problemen:

  • Het is noodzakelijk om gegevenselementen te dupliceren en alle waarden in de database op te slaan.
  • U moet overeenstemming bereiken over de intervallen voor het "bovenliggende" gegevensitem dat wordt berekend en gebruikt in de formule, en voor het berekende gegevensitem. Anders kan het berekende item een ​​niet-ondersteunde status krijgen of een eerdere waarde berekenen, wat de betrouwbaarheid van de monitoringresultaten zal beïnvloeden.

Een oplossing was om af te stappen van flexibele controle-intervallen ten gunste van vaste intervallen om ervoor te zorgen dat het berekende item wordt geëvalueerd na het item dat de gegevens ontvangt (in ons geval de temperatuur in graden Fahrenheit).

Maar als we bijvoorbeeld de sjabloon gebruiken om een ​​groot aantal apparaten te controleren, en de controle wordt elke 30 seconden uitgevoerd, "hackt" Zabbix gedurende 29 seconden en op de laatste seconde begint het te controleren en te berekenen. Dit creëert een wachtrij en beïnvloedt de prestaties. Daarom is het aan te raden om alleen vaste intervallen te gebruiken als het echt nodig is.

In dit probleem is de optimale oplossing een eenregelige JavaScript-voorverwerking die graden Fahrenheit omzet in graden Celsius:

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

Het is snel en gemakkelijk, u hoeft geen onnodige gegevensitems aan te maken en er een historie bij te houden, en u kunt ook flexibele intervallen gebruiken voor controles.

We lossen praktische problemen in Zabbix op met behulp van JavaScript

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

Maar als het in een hypothetische situatie nodig is om het ontvangen gegevenselement toe te voegen, bijvoorbeeld met een constante gedefinieerd in de macro, moet er rekening mee worden gehouden dat de parameter waarde breidt zich uit tot een string. Bij een bewerking voor het optellen van een string worden twee strings eenvoudig gecombineerd tot één.

We lossen praktische problemen in Zabbix op met behulp van JavaScript

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

Om het resultaat van een wiskundige bewerking te verkrijgen, is het noodzakelijk om de soorten verkregen waarden om te zetten in een numeriek formaat. Hiervoor kun je de functie gebruiken ontledenInt(), wat een geheel getal oplevert, een functie ontleedFloat(), wat een decimaal of een functie oplevert aantal, die een geheel getal of decimaal retourneert.

Taak 2

Krijg de tijd in seconden tot het einde van het certificaat.

Staat: een service geeft een vervaldatum van het certificaat af in het formaat "Feb 12 12:33:56 2022 GMT".

In ECMAScript5 Date.parse () accepteert een datum in ISO 8601-indeling (JJJJ-MM-DDTUU:mm:ss.sssZ). Het is noodzakelijk om er een string naar toe te casten in het formaat MMM DD JJJJ UU:mm:ss ZZ

probleem: De maandwaarde wordt uitgedrukt als tekst, niet als een getal. Gegevens in dit formaat worden door Duktape niet geaccepteerd.

Oplossing voorbeeld:

  • Allereerst wordt een variabele gedeclareerd die een waarde aanneemt (het hele script is een declaratie van variabelen die worden weergegeven, gescheiden door komma's).

  • In de eerste regel krijgen we de datum in de parameter waarde en scheid het met spaties met behulp van de methode spleet. We krijgen dus een array, waarbij elk element van de array, beginnend bij index 0, overeenkomt met één datumelement voor en na een spatie. splitsen(0) - maand, splitsen(1) - nummer, splitsen(2) - een string met tijd, enz. Daarna is elk element van de datum toegankelijk via index in de array.

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

  • Elke maand (in chronologische volgorde) komt overeen met de index van zijn positie in de reeks (van 0 tot 11). Om een ​​tekstwaarde om te zetten in een numerieke waarde, wordt er één toegevoegd aan de maandindex (omdat maanden beginnen met 1). In dit geval wordt de uitdrukking met de toevoeging van één tussen haakjes genomen, omdat anders een string wordt verkregen, geen getal. Aan het einde doen we dat plak() - knip de array vanaf het einde om slechts twee tekens over te laten (wat belangrijk is voor maanden met een tweecijferig nummer).

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

  • We vormen een string in ISO-formaat van de verkregen waarden door de gebruikelijke toevoeging van strings in de juiste volgorde.

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

De gegevens in het resulterende formaat zijn het aantal seconden vanaf 1970 tot een bepaald punt in de toekomst. Het is bijna onmogelijk om gegevens in het ontvangen formaat in triggers te gebruiken, omdat u met Zabbix alleen met macro's kunt werken {Datum} и {Tijd}, die de datum en tijd in een gebruiksvriendelijke indeling retourneren.

  • We kunnen dan de huidige datum in JavaScript in Unix Timestamp-indeling krijgen en deze aftrekken van de resulterende vervaldatum van het certificaat om het aantal milliseconden te krijgen vanaf nu totdat het certificaat verloopt.

`now = Date.now();`

  • We delen de ontvangen waarde door duizend om seconden in Zabbix te krijgen.

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

In de trigger kunt u de uitdrukking 'laatst' gevolgd door een reeks cijfers die overeenkomt met het aantal seconden in de periode waarop u wilt reageren, bijvoorbeeld in weken. De trigger zal dus melden dat het certificaat binnen een week verloopt.

NOTE. Let op het gebruik ontledenInt() in functie terugkeerom het breukgetal dat resulteert uit de deling van milliseconden om te zetten in een geheel getal. Je kan ook gebruiken ontleedFloat() en bewaar fractionele gegevens.

Bekijk verslag

Bron: www.habr.com

Voeg een reactie