Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript
Tikhon Uskov, inženjer Zabbix integracijskog tima

Zabbix je prilagodljiva platforma koja se koristi za praćenje svih podataka. Od najranijih verzija Zabbixa, nadzorni administratori su imali mogućnost pokretanja raznih skripti putem Akcije za provjere na ciljnim mrežnim čvorovima. Istovremeno, pokretanje skripti dovelo je do brojnih poteškoća, uključujući potrebu za podrškom skripti, njihovu isporuku komunikacijskim čvorovima i proksijima, kao i podršku za različite verzije.

JavaScript za Zabbix

U aprilu 2019. godine predstavljen je Zabbix 4.2 sa funkcijom preprocesiranja JavaScript. Mnogi ljudi su došli na ideju da odustanu od pisanja skripti koje negdje uzimaju podatke, probavljaju ih i pružaju u formatu razumljivom Zabbixu, te umjesto toga obavljaju jednostavne provjere koje će primiti podatke koji nisu spremni za pohranu i obradu od strane Zabbix, a zatim obraditi ovaj tok podataka koristeći Zabbix i JavaScript alate. U kombinaciji sa otkrivanjem niskog nivoa i zavisnim elementima podataka, koji su se pojavili u Zabbixu 3.4, rezultat je bio prilično fleksibilan koncept za sortiranje i upravljanje primljenim podacima.

U Zabbixu 4.4, kao logičan nastavak preprocesiranja u JavaScript-u, pojavila se nova metoda notifikacije - Webhook, koja se može koristiti za jednostavnu integraciju Zabbix obavijesti sa aplikacijama trećih strana.

JavaScript i Duktape

Zašto su odabrani JavaScript i Duktape? Razmotrene su različite opcije za jezike i motore:

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

Glavni kriteriji odabira bili su rasprostranjenost, lakoća integracije motora u proizvod, niska potrošnja resursa i ukupne performanse motora, te sigurnost implementacije koda na ovom jeziku u nadzor. Na osnovu ukupnog broja pokazatelja, pobijedio je JavaScript na Duktape engine-u.

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript

Kriteriji odabira i testiranje performansi

Karakteristike Duktape-a:

— Standardno ECMAScript E5/E5.1
— Zabbix moduli za Duktape:

  • Zabbix.log() - omogućava vam pisanje poruka sa različitim nivoima detalja direktno u zapisnik Zabbix servera, što omogućava upoređivanje grešaka, na primer, u Webhooku sa stanjem servera.
  • CurlHttpRequest() - omogućava vam da šaljete HTTP zahteve mreži, na čemu se zasniva Webhook.
  • atob() i btoa() - omogućava vam da kodirate i dekodirate nizove u Base64 format.

NAPOMENA. Duktape je u skladu sa ACME standardima. Zabbix koristi verziju skripte iz 2015. Naknadne promjene su male i mogu se zanemariti.

Magija JavaScripta

Sva magija JavaScript-a leži u dinamičkom kucanju i prelivanju tipova: string, numerički i boolean.

To znači da nema potrebe unaprijed deklarirati koji tip varijabla treba da vrati.

U matematičkim operacijama, vrijednosti koje vraćaju funkcijski operatori se pretvaraju u brojeve. Izuzetak od takvih operacija je dodavanje, jer ako je barem jedan od pojmova string, konverzija stringova se primjenjuje na sve termine.

NAPOMENA. Metode odgovorne za takve transformacije obično se implementiraju u prototipove nadređenih objekata, valueOf и toString. valueOf poziva se tokom numeričke konverzije i uvijek prije metode toString. Metoda valueOf mora vratiti primitivne vrijednosti, inače se njegov rezultat zanemaruje.

Metoda se poziva na objektu valueOF. Ako se ne pronađe ili ne vrati primitivnu vrijednost, poziva se metoda toString. Ako je metoda toString nije pronađeno, traži se valueOf u prototipu objekta, i sve se ponavlja dok se vrijednost ne obradi i sve vrijednosti u izrazu se prebace na isti tip. Ako objekt ima implementiranu metodu toString, koji vraća primitivnu vrijednost, onda se koristi za konverziju stringova. Međutim, rezultat korištenja ove metode nije nužno niz.

Na primjer, ako je za za objekt 'obj' metoda je definirana toString,

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

Metoda toString vraća tačno niz, a kada dodamo niz sa brojem dobijamo spojeni niz:

`obj + 1 // '2001'` 

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

Ali ako prepišete toStringDa bi metoda vratila broj, prilikom dodavanja objekta izvršit će se matematička operacija sa numeričkom konverzijom i dobiti rezultat matematičkog sabiranja.

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

`obj + 1 // '2001'`

Štaviše, ako izvršimo sabiranje niza, vrši se konverzija niza i dobijamo spojeni niz.

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

Upravo to je razlog velikog broja grešaka početnika JavaScript korisnika.

U metodi toString Možete unijeti funkciju koja će povećati trenutnu vrijednost objekta za 1.

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript
Izvršenje skripte pod uslovom da je varijabla jednaka 3, a takođe je jednaka 4.

Kada se poredi sa ubacivanjem tipa (==), metoda se izvršava svaki put toString sa funkcijom povećanja vrijednosti. Shodno tome, sa svakim sljedećim poređenjem vrijednost raste. Ovo se može izbjeći korištenjem poređenja bez ulijevanja tipa (===).

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript
Poređenje bez odljeva tipa

NAPOMENA. Nemojte nepotrebno koristiti poređenja glumaca.

Za složene skripte, kao što je Webhook sa složenom logikom, u kojima su poređenja sa izmjenama tipova neophodna, preporučuje se prethodno pisanje provjera vrijednosti koje varijable vraćaju i rukovanje nedosljednostima i greškama.

Webhook Media

Krajem 2019. i početkom 2020. Zabbix integracijski tim je aktivno razvijao Webhookove i gotove integracije koje dolaze sa Zabbix distribucijom.

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript
Link do dokumentaciju

Predobrada

  • Pojava predprocesiranja u JavaScriptu omogućila je napuštanje većine vanjskih skripti, a sada u Zabbixu možete uzeti bilo koju vrijednost i transformirati je u potpuno drugu vrijednost.
  • Prethodnu obradu u Zabbix-u implementira JavaScript kod, koji se, kada se prevede u bytecode, pretvara u funkciju koja uzima jednu vrijednost kao parametar vrijednost kao string (string može sadržavati i broj i broj).
  • Pošto je izlaz funkcija, na kraju skripte je obavezna povratak.
  • Moguće je koristiti prilagođene makroe u kodu.
  • Resursi se mogu ograničiti ne samo na nivou operativnog sistema, već i programski. Korak predobrade dodjeljuje se maksimalno 10 megabajta RAM-a i ograničenje vremena izvođenja od 10 sekundi.

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript

NAPOMENA. Vrijednost vremenskog ograničenja od 10 sekundi je prilično velika, jer prikupljanje hiljada elemenata podataka u 1 sekundi korištenjem prilično "teškog" scenarija preprocesiranja može usporiti Zabbix. Zbog toga se ne preporučuje korištenje predprocesiranja za izvršavanje punopravnih JavaScript skripti kroz takozvane elemente sjenčanih podataka (lažne stavke), koji se pokreću samo za obavljanje predobrade.

Možete provjeriti svoj kod kroz test preprocesiranja ili korištenjem uslužnog programa 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`

Praktični problemi

Cilj 1

Zamijenite izračunatu stavku podataka prethodnom obradom.

Stanje: Primite temperaturu u stepenima Farenhajta sa senzora za skladištenje u stepenima Celzijusa.

Ranije bismo kreirali element podataka koji je prikupljao temperaturu u stepenima Farenhajta. Nakon toga, još jedna stavka podataka (izračunata) koja bi koristila formulu za pretvaranje Farenhajta u Celzijus.

Problemi:

  • Potrebno je duplicirati elemente podataka i pohraniti sve vrijednosti u bazu podataka.
  • Morate se dogovoriti o intervalima za "roditeljsku" stavku podataka koja se izračunava i koristi u formuli i izračunatoj stavci podataka. U suprotnom, izračunata stavka podataka može ući u nepodržano stanje ili prebrojati prethodnu vrijednost, što će uticati na pouzdanost rezultata praćenja.

Jedno rješenje je bilo da se odmakne od fleksibilnih intervala provjere u korist fiksnih intervala kako bi se osiguralo da se izračunata stavka podataka izračuna nakon stavke podataka koja prima (u našem slučaju temperatura u stepenima Farenhajta).

Ali ako, na primjer, koristimo šablon za provjeru velikog broja uređaja, a provjera se vrši jednom svakih 30 sekundi, Zabbix „zastoji“ 29 sekundi, a u posljednjoj sekundi počinje provjeravati i računati. Ovo stvara red čekanja i utiče na performanse. Stoga se preporučuje korištenje fiksnih intervala samo ako je to apsolutno neophodno.

Za ovaj problem, optimalno rješenje je jednolinijska JavaScript predobrada koja pretvara Farenhajt u Celzijus:

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

Brzo je i jednostavno, ne morate kreirati nepotrebne elemente podataka i pohranjivati ​​historiju na njih, a možete koristiti i fleksibilne intervale za provjere.

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript

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

Ali, ako je u hipotetičkoj situaciji potrebno dodati rezultirajući element podataka, na primjer, s nekom konstantom definiranom u makrou, potrebno je uzeti u obzir da parametar vrijednost širi u liniju. U operaciji sabiranja nizova, dva niza se jednostavno kombinuju u jedan.

Mi rješavamo praktične probleme u Zabbixu koristeći JavaScript

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

Da biste dobili rezultat matematičke operacije, potrebno je pretvoriti vrste dobivenih vrijednosti u numerički format. Da biste to učinili, možete koristiti funkciju parseInt(), koji proizvodi cijeli broj, funkciju parseFloat(), koji proizvodi decimalni razlomak ili funkciju broj, koji proizvodi cijeli broj ili decimalni razlomak.

Problem 2

Dobijte vrijeme u sekundama do isteka certifikata.

Stanje: određeni servis izdaje datum isteka certifikata u formatu "12. februar 12:33:56 2022 GMT".

U ECMAScript5 date.parse() prihvata datum u ISO 8601 formatu (GGGG-MM-DDTHH:mm:ss.sssZ). Morate ga pretvoriti u niz u formatu MMM DD GGGG HH:mm:ss ZZ

problem: Vrijednost mjeseca se izražava kao tekst, a ne kao broj. Duktape ne prihvata podatke u ovom formatu.

Primjer rješenja:

  • Prije svega, deklarira se varijabla koja uzima vrijednost (cijela skripta je deklaracija varijabli koje su navedene odvojene zarezima).

  • U prvom redu dobijamo datum u parametru vrijednost i odvojite ga razmacima koristeći metodu Split. Tako dobijamo niz u kojem svaki element niza, počevši od indeksa 0, odgovara jednom elementu datuma prije i poslije razmaka. split(0) - mjesec, split(1) - broj, split(2) - string sa vremenom, itd. Nakon toga, svakom elementu datuma može se pristupiti indeksom u nizu.

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

  • Svaki mjesec (hronološkim redom) odgovara indeksu svoje pozicije u nizu (od 0 do 11). Da biste pretvorili tekstualnu vrijednost u numeričku vrijednost, jedan se dodaje indeksu mjeseca (jer numeriranje mjeseca počinje od 1). U ovom slučaju, izraz sa dodatkom jedinice uzima se u zagrade, jer će u suprotnom rezultat biti niz, a ne broj. Na kraju nastupamo kriška() — izrežite niz s kraja da ostavite samo dva znaka (što je važno za mjesece sa dvocifrenim brojem).

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

  • Od dobijenih vrijednosti formiramo niz u ISO formatu jednostavnim dodavanjem nizova odgovarajućim redoslijedom.

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

Podaci u rezultirajućem formatu su broj sekundi od 1970. do neke tačke u budućnosti. Gotovo je nemoguće koristiti podatke u rezultirajućem formatu u okidačima, jer vam Zabbix dozvoljava rad samo s makroima {Datum} и {vrijeme}, koji vraćaju datum i vrijeme u formatu koji može čitati korisnik.

  • Tada možemo dobiti trenutni datum u JavaScript-u u Unix formatu Timestamp i oduzeti ga od rezultirajućeg datuma isteka certifikata da dobijemo broj milisekundi od sada do isteka certifikata.

`now = Date.now();`

  • Dobivenu vrijednost podijelimo sa hiljadu da dobijemo sekunde u Zabbixu.

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

U okidaču možete specificirati izraz 'zadnji' i skup brojeva koji odgovara broju sekundi u periodu na koji trebate reagirati, na primjer, u sedmicama. Dakle, okidač će obavijestiti da certifikat ističe za tjedan dana.

NAPOMENA. Obratite pažnju na upotrebu parseInt() u funkciji povratakza pretvaranje razlomka broja koji nastaje dijeljenjem milisekundi u cijeli broj. Također možete koristiti parseFloat() i pohraniti frakcione podatke.

Pogledaj izvještaj

izvor: www.habr.com

Dodajte komentar