Lösa praktiska problem i Zabbix med hjÀlp av JavaScript

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript
Tikhon Uskov, ingenjör för integrationsgruppen Zabbix

Zabbix Ă€r en anpassningsbar plattform som anvĂ€nds för att övervaka alla typer av data. FrĂ„n de tidigaste versionerna av Zabbix hade övervakningsadministratörer möjlighet att köra olika skript genom ÅtgĂ€rder för kontroller pĂ„ nĂ€tverkets mĂ„lknutpunkter. Att köra skript medförde dock en rad svĂ„righeter, inklusive behovet av att stödja skript, leverera dem till anslutningspunkter och proxyer samt stödja olika versioner.

JavaScript för Zabbix

I april 2019 presenterades Zabbix 4.2 med funktionen för förbearbetning i JavaScript. MÄnga blev inspirerade av tanken att överge skrivandet av skript som hÀmtar data, bearbetar dem och presenterar dem i ett format som Zabbix förstÄr, och i stÀllet utföra enkla kontroller som fÄr oförberedd data för lagring och bearbetning i Zabbix, för att sedan bearbeta denna datastream med hjÀlp av Zabbix och JavaScript. Tillsammans med lÄg-nivÄ upptÀckter och beroende datakomponenter som introducerades i Zabbix 3.4, skapades ett tillrÀckligt flexibelt koncept för sortering och hantering av erhÄllen data.

I Zabbix 4.4, som en logisk fortsĂ€ttning pĂ„ förbearbetning i JavaScript, introducerades ett nytt varningssĂ€tt — Webhook, som kan anvĂ€ndas för enkel integration av Zabbix-varningar med tredjepartsapplikationer.

JavaScript och Duktape

Varför valdes just JavaScript och Duktape? Olika alternativ för sprÄk och motorer övervÀgdes:

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

De huvudsakliga urvalskriterierna var spridning, enkelhet av motorens integration i produkten, lÄg resursförbrukning och den allmÀnna prestandan hos motorn, samt sÀkerheten av att integrera kod pÄ detta sprÄk i övervakningen. Baserat pÄ dessa kriterier vann JavaScript med Duktape-motorn.

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript

Urvalskriterier och prestandatestning

Egenskaper hos Duktape:

— Standard ECMAScript E5/E5.1
— Zabbix-moduler för Duktape:

  • Zabbix.log() — gör att meddelanden med olika detaljeringsnivĂ„er kan skrivas direkt i Zabbix Server-loggen, vilket möjliggör jĂ€mförelse av fel, till exempel i Webhook, med serverstatus.
  • CurlHttpRequest() — möjliggör HTTP-begĂ€rningar till nĂ€tverket, vilket utgör grunden för anvĂ€ndning av Webhook.
  • atob() och btoa() — möjliggör kodning och avkodning av strĂ€ngar i Base64-format.

OBS. Duktape uppfyller ACME-standarder. I Zabbix anvÀnds skriptversionen frÄn 2015. Efterföljande Àndringar Àr obetydliga och kan dÀrför ignoreras..

Magin med JavaScript

All magi i JavaScript ligger i den dynamiska typningen och typkonverteringarna: strÀngar, nummer och logiska vÀrden.

Detta innebÀr att man inte behöver deklarera pÄ förhand vilken typ av variabel som ska returnera ett vÀrde.

Vid matematiska operationer konverteras vÀrden som returneras av operator-funktioner till siffror. Undantaget frÄn sÄdana operationer Àr addition, eftersom om minst en av summorna Àr en strÀng, tillÀmpas strÀngkonvertering pÄ alla summor.

OBS. Metoder som ansvarar för sÄdana konverteringar implementeras vanligtvis i förÀlderprototyper av objekt, valueOf och toString. valueOf anropas vid numerisk konvertering och kommer alltid före metoden toString. Metoden valueOf mÄste returnera primitiva vÀrden, annars ignoreras dess resultat.

För ett objekt anropas metoden valueOF. Om den inte hittas eller inte returnerar ett primitivt vĂ€rde, anropas metoden toString. Om metoden toString inte hittas, letas det i objektets prototyp, och allt upprepas tills vĂ€rdet har behandlats och alla vĂ€rden i uttrycket har konverterats till samma typ. valueOf Om ett objekt har en metod. , som returnerar ett primitivt vĂ€rde, anvĂ€nds den för strĂ€ngkonvertering. toStringResultatet av att anvĂ€nda denna metod behöver dock inte nödvĂ€ndigtvis vara en strĂ€ng. Till exempel, om ett objekt ‘

‘ definierar metodenobj`var obj = { toString() { return "200" }}` toString,

returnerar just en strÀng, och vid addition av strÀngen med ett nummer fÄr vi en sammansatt strÀng: 

metod toString `obj + 1 // '2001'``obj + 'a' // '200a'`

Men om vi skriver om

, sÄ att metoden returnerar ett nummer, kommer additionen av objektet att utföra en matematisk operation med numerisk konvertering och resultatet blir resultatet av matematisk addition. toString`var obj = { toString() { return 200 }}``obj + 1 // '2001'`

Om vi dessutom utför addition med en strÀng, görs strÀngkonvertering, och vi fÄr en sammansatt strÀng.

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

Detta Àr anledningen till att nybörjare ofta fÄr mÄnga fel i JavaScript.

Man kan skriva en funktion som ökar det aktuella vÀrdet i objektet med 1.

I metoden toString Körning av skriptet under förutsÀttning att variabeln Àr lika med 3, och den Àr ocksÄ lika med 4.

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript
Kör skriptet under förutsÀttning att variabeln Àr lika med 3 och den ocksÄ Àr lika med 4.

Vid jÀmförelse med typkonvertering (==) anropas metoden varje gÄng toString med vÀrdeökande funktion. DÀrför ökar vÀrdet vid varje efterföljande jÀmförelse. Detta kan undvikas genom att anvÀnda jÀmförelse utan typkonvertering (===).

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript
JÀmförelse utan typkonvertering

OBS. AnvÀnd inte typkonvertering vid jÀmförelse utan behov.

För komplexa skript, till exempel Webhook med komplex logik, dÀr jÀmförelse med typkonvertering Àr nödvÀndig, rekommenderas det att först skriva kontroller för vÀrdena som returneras av variabler och hantera avvikelser och fel.

Webhook Media

I slutet av 2019 och början av 2020 arbetade Zabbix integreringsteam aktivt med utveckling av Webhooks och

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript
LĂ€nk till dokumentationen

Förbehandling

  • FramvĂ€xten av förbehandling pĂ„ JavaScript har möjliggjort avskaffandet av de flesta externa skript, och just nu kan man i Zabbix fĂ„ vilket vĂ€rde som helst och omvandla det till ett annat vĂ€rde.
  • Förbehandling i Zabbix implementeras med kod pĂ„ JavaScript, som vid kompilering till bytekod omvandlas till en funktion som tar ett enda vĂ€rde som parameter value i form av en strĂ€ng (den kan innehĂ„lla bĂ„de siffror och tecken).
  • Eftersom utdata Ă€r en funktion, Ă€r det obligatoriskt i slutet av skriptet Ă„tervĂ€nda.
  • AnvĂ€ndning av anvĂ€ndardefinierade makron i koden Ă€r möjlig.
  • Resurser kan begrĂ€nsas inte bara pĂ„ operativsystemsnivĂ„ utan ocksĂ„ programmĂ€ssigt. För steget förbehandling tilldelas maximalt 10 megabyte RAM och en exekveringstid pĂ„ 10 sekunder.

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript

OBS. Timeout-vÀrdena pÄ 10 sekunder Àr ganska mycket, eftersom insamling av tusentals datainmatningar per sekund enligt ett ganska "tungt" förbehandlingssÀtt kan bromsa Zabbix. DÀrför rekommenderas det inte att anvÀnda förbehandling för att köra fullfjÀdrade skript pÄ JavaScript via sÄ kallade dummy-dataelement, som endast körs för att utföra förbehandling..

Du kan kontrollera din kod genom förbehandlingsrelaterad test eller med hjÀlp av verktyget 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`

Praktiska uppgifter

Uppgift 1

ErsÀtt den berÀknade datan med en förbehandling.

Villkor: vi fÄr temperaturen frÄn sensorn i Fahrenheit för att lagra den i Celsius.

Tidigare skulle vi ha skapat en datakomponent som samlar in temperaturen i Fahrenheit. Efter det — en annan datakomponent (berĂ€knad) som med en formel omvandlar grader Fahrenheit till grader Celsius.

Problem:

  • Det Ă€r nödvĂ€ndigt att duplicera datakomponenter och lagra alla vĂ€rden i databasen.
  • Det Ă€r nödvĂ€ndigt att samordna intervallen för den 'parent'-datakomponenten, som berĂ€knas och anvĂ€nds i formeln, med den berĂ€knade datakomponenten. Annars kan den berĂ€knade datakomponenten gĂ„ in i ett otillĂ„tet tillstĂ„nd eller rĂ€kna det föregĂ„ende vĂ€rdet, vilket pĂ„verkar tillförlitligheten i övervakningsresultaten.

En av lösningarna var att överge flexibla kontrollintervall till förmĂ„n för fasta intervall, för att sĂ€kerstĂ€lla att den berĂ€knade datakomponenten berĂ€knas efter datakomponenten som fĂ„r data (i vĂ„rt fall — temperaturen i Fahrenheit).

Men om, till exempel, mallen vi anvÀnder för att kontrollera ett stort antal enheter, och kontrollen genomförs vart 30:e sekund, sÄ 'slappar' Zabbix i 29 sekunder, och börjar kontroller och berÀkningar under den sista sekunden. Detta leder till skapandet av en kö och pÄverkar prestandan. DÀrför rekommenderas fasta intervall endast om det verkligen Àr nödvÀndigt.

För denna uppgift Àr den optimala lösningen en förbehandling pÄ en rad i JavaScript som omvandlar grader Fahrenheit till grader Celsius:

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

Det Àr snabbt och enkelt, det krÀvs inte att skapa onödiga datakomponenter och lagra historik för dem, och det kan ocksÄ anvÀndas för flexibla kontrollintervall.

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript

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

Men om, i en hypotetisk situation, det Àr nödvÀndigt att summera den erhÄllna datakomponenten med, till exempel, en konstant definierad i makrot, mÄste vi ta hÀnsyn till att parametern value avtÀckes i en strÀng. Vid addition av strÀngar sammanfogas de helt enkelt till en strÀng.

Lösa praktiska problem i Zabbix med hjÀlp av JavaScript

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

För att fÄ resultaten av en matematisk operation mÄste vÀrdenas typer konverteras till numeriskt format. För detta kan du anvÀnda funktionen parseInt(), som ger ett heltal, funktionen parseFloat(), som ger ett decimaltal, eller funktionen number, som ger antingen ett heltal eller ett decimaltal.

Uppgift 2

FÄ tiden i sekunder till certifikatets utgÄng.

Villkor: en viss tjÀnst ger certifikatets utgÄngsdatum i formatet "Feb 12 12:33:56 2022 GMT".

I ECMAScript5 Date.parse() tar emot datum i ISO 8601-format (YYYY-MM-DDTHH:mm:ss.sssZ). Det Àr nödvÀndigt att konvertera strÀngen till formatet MMM DD YYYY HH:mm:ss ZZ

Problemet: mÄnadens vÀrde uttrycks i textform och inte som ett nummer. Data i detta format godtas inte av Duktape.

Exempel pÄ lösning:

  • Först deklareras en variabel som fĂ„r ett vĂ€rde (hela skriptet bestĂ„r av deklarationer av variabler som anges med kommatecken).

  • I den första raden fĂ„r vi datumet i parametern value och delar den med mellanslag med metoden split. SĂ„ledes fĂ„r vi en array dĂ€r varje element, med början frĂ„n index 0, motsvarar ett datumselement före och efter mellanslaget. split(0) — mĂ„nad, split(1) — dag, split(2) — tidsstrĂ€ng osv. Efter detta kan varje datumselement nĂ„s via index i arrayen.

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

  • Varje mĂ„nad (i kronologisk ordning) motsvarar index för dess position i arrayen (frĂ„n 0 till 11). För att konvertera textvĂ€rdet till ett numeriskt lĂ€ggs ett till mĂ„nadens index (eftersom mĂ„nadnumreringen börjar frĂ„n 1). Detta uttryck med tillĂ€gg av ett görs i parentes, eftersom det annars skulle ge en strĂ€ng istĂ€llet för ett nummer. I slutet utför vi slice() — en skĂ€rning av arrayen frĂ„n slutet för att behĂ„lla endast tvĂ„ tecken (vilket Ă€r viktigt för mĂ„nader med tvĂ„siffriga 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),`

  • Vi formar en strĂ€ng i ISO-format frĂ„n de erhĂ„llna vĂ€rdena genom att helt enkelt addera strĂ€ngar i rĂ€tt ordning.

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

Data i det erhÄllna formatet representerar antalet sekunder sedan 1970 till en viss tidpunkt i framtiden. Att anvÀnda data i det formatet i triggers Àr praktiskt taget omöjligt, eftersom Zabbix endast tillÄter att arbeta med makron {Date} och {Time}, som returnerar datum och tid i ett anvÀndarvÀnligt format.

  • Efter detta kan vi fĂ„ det aktuella datumet i JavaScript i Unix Timestamp-format och subtrahera det frĂ„n det erhĂ„llna certifikatets slutdatum för att fĂ„ antal millisekunder frĂ„n nuvarande ögonblick till certifikatets utgĂ„ngstid.

`now = Date.now();`

  • Vi delar det erhĂ„llna vĂ€rdet med tusen för att fĂ„ sekunder i Zabbix.

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

I triggern kan man ange uttrycket ‘last<‘ och en uppsĂ€ttning siffror som motsvarar antalet sekunder i den period som ska reageras pĂ„, till exempel i veckor. PĂ„ sĂ„ sĂ€tt kommer triggern att meddela att certifikatets giltighetstid löper ut om en vecka.

OBS. Observera anvÀndningen av parseInt() i funktionen ÄtervÀnda, för att konvertera det decimala talet som erhÄllits som resultat av division med millisekunder till ett heltal. Det gÄr ocksÄ att anvÀnda parseFloat() och lagra decimala data.

Se rapporten

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster