Praktische problemen oplossen in Zabbix met behulp van JavaScript

Praktische problemen oplossen in Zabbix met behulp van JavaScript
Tikhon Uskov, ingenieur van het Zabbix-integratieteam

Zabbix is een aanpasbaar platform dat wordt gebruikt voor het monitoren van allerlei gegevens. Sinds de vroege versies van Zabbix hadden monitoringbeheerders de mogelijkheid om verschillende scripts uit te voeren via Acties voor controles op de doelknopen van het netwerk. Het uitvoeren van scripts leidde echter tot verschillende complicaties, zoals de noodzaak voor het onderhouden van scripts, hun distributie naar netwerk- en proxyknopen, evenals het ondersteunen van verschillende versies.

JavaScript voor Zabbix

In april 2019 werd Zabbix 4.2 geïntroduceerd met de functie voor preprocessing in JavaScript. Veel mensen raakten enthousiast over het idee om geen scripts meer te schrijven die ergens gegevens ophalen, deze verwerken en in een voor Zabbix begrijpelijk formaat beschikbaar stellen, maar in plaats daarvan eenvoudige controles uit te voeren die onbewerkte gegevens ontvangen en deze vervolgens verwerken met behulp van Zabbix en JavaScript. In combinatie met low-level detectie en afhankelijke gegevenselementen, die in Zabbix 3.4 zijn geïntroduceerd, ontstond er een voldoende flexibele conceptie voor het sorteren en beheren van de ontvangen gegevens.

In Zabbix 4.4, als logisch vervolg op de preprocessing in JavaScript, is er een nieuwe meldingsmethode — Webhook — die kan worden gebruikt voor eenvoudige integratie van Zabbix-meldingen met externe applicaties.

JavaScript en Duktape

Waarom werden JavaScript en Duktape gekozen? Er werden verschillende programmeertalen en engines overwogen:

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

De belangrijkste selectiecriteria waren verspreiding, eenvoud van integratie van de engine in het product, laag resourceverbruik, algemene prestaties van de engine en de veiligheid van het integreren van code in de monitoring. Gezien al deze criteria won JavaScript op de Duktape-engine.

Praktische problemen oplossen in Zabbix met behulp van JavaScript

Selectiecriteria en prestatietests

Kenmerken van Duktape:

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

  • Zabbix.log() — stelt in staat om logberichten op verschillende detailniveau's rechtstreeks naar Zabbix Server te schrijven, wat de mogelijkheid biedt om fouten, bijvoorbeeld in Webhook, te koppelen aan de status van de server.
  • CurlHttpRequest() — maakt het mogelijk om HTTP-verzoeken over het netwerk te doen, waarop de toepassing van Webhook is gebaseerd.
  • atob() en btoa() — maken het mogelijk om strings te coderen en decoderen naar het Base64-formaat.

OPMERKING. Duktape voldoet aan de ACME-normen. In Zabbix wordt versie 2015 van het script gebruikt. Latere veranderingen zijn gering, dus die kunnen worden genegeerd..

De magie van JavaScript

De hele magie van JavaScript is te vinden in dynamische type-inferentie en type-conversie: van strings, getallen en booleaanse waarden.

Dit betekent dat je niet van tevoren hoeft aan te geven van welk type de variabele een waarde moet opleveren.

Bij wiskundige bewerkingen worden de waarden die door functies worden teruggegeven, omgezet in getallen. Een uitzondering op deze bewerkingen is optelling, omdat, als een van de opgetallen een string is, er stringconversie op alle opgetallen wordt toegepast.

OPMERKING. De methoden die verantwoordelijk zijn voor dergelijke conversies zijn doorgaans geïmplementeerd in de ouderprototypes van objecten, valueOf en toString. valueOf wordt aangeroepen bij numerieke conversie en altijd vóór de methode toString. De methode valueOf moet primitieve waarden retourneren; anders wordt het resultaat genegeerd.

Voor een object wordt de methode valueOFaangeropen. Als deze niet wordt gevonden of geen primitieve waarde retourneert, wordt de methode toStringaangeropen. Als de methode toString niet wordt gevonden, wordt er gezocht valueOf in het prototype van het object, en het proces herhaalt zich totdat de waarde is afgehandeld en alle waarden in de expressie naar één type zijn omgezet.. Als er voor het object een methode is gedefinieerd toString, die een primitieve waarde retourneert, dan wordt deze gebruikt voor stringconversie. Het resultaat van het toepassen van deze methode hoeft echter geen string te zijn.

Bijvoorbeeld, als voor het object ‘obj‘ de methode wordt gedefinieerd toString,

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

methode toString geeft precies de string terug, en bij het optellen van een string met een getal krijgen we een samengevoegde string:

`obj + 1 // '2001'` 

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

Maar als we het herschrijven toString, zodat de methode een getal retourneert, wordt er bij het optellen van het object een wiskundige bewerking uitgevoerd met getalconversie, en krijgen we het resultaat van de wiskundige optelling.

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

`obj + 1 // '2001'`

Als we optellen met een string, vindt er stringconversie plaats, en krijgen we een samengevoegde string.

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

Dit is de reden voor de vele fouten die beginnende JavaScript-gebruikers maken.

In de methode toString Je kunt een functie schrijven die de huidige waarde van een object met 1 verhoogt.

Praktische problemen oplossen in Zabbix met behulp van JavaScript
Voer het script uit op voorwaarde dat de variabele gelijk is aan 3, en dat ze ook gelijk is aan 4.

Bij vergelijking met type-conversie (==) wordt elke keer de methode uitgevoerd toString met de functie om de waarde te verhogen. Bij elke volgende vergelijking wordt de waarde dus verhoogd. Dit kan worden vermeden door type-veilige vergelijking (===) te gebruiken.

Praktische problemen oplossen in Zabbix met behulp van JavaScript
Type-veilige vergelijking

OPMERKING. Gebruik geen type-vergelijking zonder noodzaak..

Voor complexe scripts, zoals Webhooks met gecompliceerde logica, waarin type-conversie nodig is, wordt aanbevolen om vooraf controles te schrijven voor de waarden die door variabelen worden geretourneerd en om inconsistenties en fouten te verwerken.

Webhook Media

Aan het einde van 2019 en het begin van 2020 was het integratieteam van Zabbix actief bezig met de ontwikkeling van Webhooks en kant-en-klare integraties die met de Zabbix-distributie worden geleverd.

Praktische problemen oplossen in Zabbix met behulp van JavaScript
Link naar documentatie

Voorbewerking

  • De introductie van voorbewerking in JavaScript heeft het mogelijk gemaakt om de meeste externe scripts weg te laten, en momenteel kan in Zabbix elke waarde worden verkregen en omgezet naar elke andere waarde.
  • Voorbewerking in Zabbix is geïmplementeerd met JavaScript-code, die bij compilatie naar bytecode wordt omgezet in een functie die één enkele waarde als parameter accepteert. value als een string (de string kan zowel een cijfer als een getal bevatten).
  • Aangezien er een functie als resultaat is, is aan het einde van het script noodzakelijk. terug.
  • Het is mogelijk om gebruikersmacro's in de code te gebruiken.
  • Hulpmiddelen kunnen niet alleen op het niveau van het besturingssysteem worden beperkt, maar ook programmatisch. Voor de voorbewerkingsstap is er een maximum van 10 megabyte RAM en een tijdslimiet van 10 seconden.

Praktische problemen oplossen in Zabbix met behulp van JavaScript

OPMERKING. De time-out waarde van 10 seconden is behoorlijk veel, omdat het verzamelen van duizenden data-elementen in 1 seconde bij een vrij 'zware' voorbewerkingsscenarios de werking van Zabbix kan vertragen. Daarom wordt het niet aanbevolen om voorbewerking te gebruiken voor het uitvoeren van volledige JavaScript-applicaties via de zogenaamde dummy-gegevenselementen, die alleen worden uitgevoerd om voorbewerking uit te voeren..

Je kunt je code controleren via de preprocessing-test of met behulp van de tool. zabbix_js:

`zabbix_js -s *script-bestand -p *input-parameter* [-l log-niveau] [-t timeout]`

`zabbix_js -s script-bestand -i input-bestand [-l log-niveau] [-t timeout]`

`zabbix_js -h`

`zabbix_js -V`

Praktische taken

Task 1

Vervang het berekende gegevensitem door preprocessing.

Voorwaarde: we krijgen de temperatuur van de sensor in graden Fahrenheit voor opslag in graden Celsius.

Vroeger zouden we een gegevensitem hebben gemaakt dat de temperatuur in graden Fahrenheit verzamelt. Daarna een ander gegevensitem (berekend) dat op basis van een formule de graden Fahrenheit zou omrekenen naar graden Celsius.

Problemen:

  • Het is nodig om gegevensitems te dupliceren en alle waarden in de database op te slaan.
  • Het is noodzakelijk om de intervallen voor het 'ouder'-gegevensitem, dat wordt berekend en gebruikt in de formule, en het berekende gegevensitem op elkaar af te stemmen. Anders kan het berekende gegevensitem in een niet-ondersteunde staat komen of de vorige waarde berekenen, wat de betrouwbaarheid van de monitoringresultaten beïnvloedt.

Een van de oplossingen was om af te zien van flexibele controleschema's ten gunste van vaste intervallen, om er zeker van te zijn dat het berekende gegevensitem na het gegevensitem dat de gegevens ontvangt (in ons geval de temperatuur in graden Fahrenheit) wordt berekend.

Maar als we bijvoorbeeld de sjabloon gebruiken voor het controleren van een groot aantal apparaten, en de controle elke 30 seconden wordt uitgevoerd, 'werkt' Zabbix 29 seconden niet en begint pas in de laatste seconde met controles en berekeningen. Dit leidt tot een wachtrij en beïnvloedt de prestaties. Daarom wordt het aangeraden om vaste intervallen alleen te gebruiken als dat echt nodig is.

In deze taak is de optimale oplossing een preprocessing van één regel in JavaScript, die graden Fahrenheit omzet naar graden Celsius:

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

Dit is snel en eenvoudig, er hoeven geen extra gegevensitems te worden aangemaakt en de geschiedenis ervan wordt niet opgeslagen. Het kan ook worden gebruikt voor flexibele controleschema's.

Praktische problemen oplossen in Zabbix met behulp van JavaScript

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

Maar als in een hypothetische situatie het verkregen gegevensitem bijvoorbeeld moet worden opgeteld bij een constante die in de macro is gedefinieerd, moet rekening worden gehouden met het feit dat de parameter value wordt in één lijn weergegeven. Bij de bewerking van stringoptellingen worden twee strings eenvoudigweg samengevoegd tot één.

Praktische problemen oplossen in Zabbix met behulp van JavaScript

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

Om het resultaat van een wiskundige bewerking te verkrijgen, moeten de typen van de verkregen waarden naar numeriek formaat worden omgezet. Hiervoor kan de functie worden gebruikt parseInt(), die een geheel getal retourneert, de functie parseFloat(), die een decimaal getal retourneert, of de functie number, die een geheel getal of decimaal getal retourneert.

Taak 2

Verkrijg de tijd in seconden tot het verlopen van het certificaat.

Voorwaarde: een bepaalde service geeft de vervaldatum van het certificaat in het formaat "Feb 12 12:33:56 2022 GMT".

In ECMAScript5 Date.parse() neemt een datum in ISO 8601-formaat (YYYY-MM-DDTHH:mm:ss.sssZ). Het is nodig om de string om te zetten naar het formaat MMM DD YYYY HH:mm:ss ZZ

Probleem: de maandwaarde wordt uitgedrukt in tekst in plaats van in een getal. Gegevens in dit formaat worden niet geaccepteerd door Duktape.

Voorbeeldoplossing:

  • Eerst wordt een variabele gedeclareerd die een waarde aanneemt (de hele script is een declaratie van variabelen die door een komma zijn gescheiden).

  • In de eerste regel verkrijgen we de datum in de parameter value en splitsen deze met spaties met behulp van de methode split. Op deze manier krijgen we een array waarin elk element van de array, beginnend vanaf index 0, overeenkomt met een element van de datum voor en na de spatie. split(0) — maand, split(1) — dag, split(2) — string met tijd, enz. Daarna kan voor elk element van de datum via de index in de array worden verwezen.

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

  • Aan elke maand (in chronologische volgorde) komt de index toe van zijn positie in de array (van 0 tot 11). Om de tekstwaarde om te zetten naar een numerieke waarde, wordt 1 bij de maandindex opgeteld (omdat de nummering van maanden begint bij 1). Het is belangrijk dat de expressie met de optelling van 1 tussen haakjes staat, omdat er anders een string in plaats van een getal wordt verkregen. Aan het einde voeren we slice() uit — een snede van de array van het einde om alleen twee cijfers te behouden (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),`

  • Vorm een string in ISO-formaat uit de verkregen waarden door gewone stringconcatenatie in de juiste volgorde.

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

De gegevens in het ontvangen formaat zijn het aantal seconden vanaf 1970 tot een bepaald moment in de toekomst. Het is praktisch onmogelijk om de gegevens in het ontvangen formaat in triggers te gebruiken, omdat Zabbix alleen met macro's kan werken. {Date} en {Time}, die de datum en tijd in een voor de gebruiker begrijpelijk formaat teruggeven.

  • Daarna kunnen we in JavaScript de huidige datum in Unix Timestamp-formaat verkrijgen en deze van de ontvangen waarde van de einddatum van het certificaat aftrekken, om het aantal milliseconden van het huidige moment tot het eindmoment van het certificaat te krijgen.

`now = Date.now();`

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

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

In de trigger kan een expressie worden opgegeven ‘last<‘ en een reeks cijfers die overeenkomt met het aantal seconden in de periode waarop moet worden gereageerd, bijvoorbeeld in weken. Op die manier zal de trigger waarschuwen dat de geldigheidsduur van het certificaat over een week afloopt.

OPMERKING. Let op het gebruik van parseInt() in de functie terug, om het decimale getal, dat het resultaat is van de deling van milliseconden, om te zetten in een geheel getal. Het is ook mogelijk om parseFloat() en decimale gegevens op te slaan..

Bekijk de presentatie.

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster