Riešime praktické úlohy v Zabbix pomocou JavaScriptu

Riešime praktické úlohy v Zabbix pomocou JavaScriptu
Tikhon Uskov, inžinier tímu integrácie Zabbix

Zabbix je prispôsobiteľná platforma, ktorá sa používa na monitorovanie akýchkoľvek údajov. Od najskorších verzií Zabbix mali správcovia monitorovania možnosť spúšťať rôzne skripty cez Akcie pre kontroly na cieľových uzloch siete. Pri tom spúšťanie skriptov viedlo k niektorým komplikáciám, vrátane potreby podpory skriptov, ich dodávky na uzly komunikácie a proxy, ako aj podpory rôznych verzií.

JavaScript pre Zabbix

V apríli 2019 bola predstavená verzia Zabbix 4.2 s funkciou predspracovania v JavaScripte. Mnohí sa nadchli myšlienkou vzdať sa písania skriptov, ktoré niekde získavajú údaje, spracovávajú ich a poskytujú už v zrozumiteľnom formáte pre Zabbix, a vykonávať jednoduché kontroly, ktoré budú získavať nepripravené údaje na uloženie a spracovanie v Zabbix, a potom spracovávať tento prúd údajov pomocou prostriedkov Zabbix a JavaScript. V spojení s nízkoúrovňovým objavovaním a závislými prvkami údajov, ktoré sa objavili v Zabbix 3.4, vznikla dostatočne flexibilná koncepcia na triedenie a riadenie získaných údajov.

V Zabbix 4.4, ako logické pokračovanie predspracovania v JavaScripte, sa objavil nový spôsob oznamovania — Webhook, ktorý sa dá použiť na jednoduchú integráciu upozornení Zabbix s externými aplikáciami.

JavaScript a Duktape

Prečo boli vybrané práve JavaScript a Duktape? Zvažovali sa rôzne možnosti jazykov a enginov:

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

Hlavnými kritériami výberu boli rozšírenosť, jednoduchosť integrácie enginu do produktu, nízka spotreba prostriedkov a celkový výkon enginu, a bezpečnosť zavedenia kódu v tomto jazyku do monitorovania. Na základe týchto kritérií zvíťazil JavaScript na engine Duktape.

Riešime praktické úlohy v Zabbix pomocou JavaScriptu

Kritériá výberu a výkonové testovanie

Vlastnosti Duktape:

— Štandard ECMAScript E5/E5.1
— Moduly Zabbix pre Duktape:

  • Zabbix.log() — umožňuje zapisovať priamo do logu Zabbix Server správy s rôznymi úrovňami detailnosti, čo poskytuje možnosť porovnávať chyby, napríklad v Webhook s stavom servera.
  • CurlHttpRequest() — umožňuje vykonávať HTTP požiadavky do siete, na čom je založené použitie Webhook.
  • atob() a btoa() — umožňujú kódovať a dekódovať reťazce do formátu Base64.

POZNÁMKA. Duktape je v súlade so štandardmi ACME. V Zabbixe sa používa verzia skriptu z roku 2015. Následné zmeny sú zanedbateľné, a preto ich možno ignorovať..

Kúzlo JavaScriptu

Všetko kúzlo JavaScriptu spočíva v dynamickej typizácii a prevodoch typov: reťazcových, číselných a logických.

To znamená, že nie je potrebné vopred deklarovať, akého typu by mala premenná vrátiť hodnotu.

Pri matematických operáciách sa hodnoty, ktoré vracajú funkčné operátory, prevádzajú na čísla. Výnimkou z takýchto operácií je sčítanie, pretože ak aspoň jeden zčítač je reťazec, na všetky zčítače sa aplikuje reťazcová konverzia.

POZNÁMKA. Metódy, ktoré sú zodpovedné za takéto konverzie, sú zvyčajne implementované v rodičovských prototypoch objektov, valueOf a toString. valueOf sa vyžaduje pri numerickej konverzii a vždy pred metódou toString. Metóda valueOf musí vracať primitívne hodnoty, inak sa jej výsledok ignoruje.

Pre objekt sa volá metóda valueOF. Ak sa nenájde alebo nevráti primitívnu hodnotu, volá sa metóda toString. Ak metóda toString nie je nájdená, hľadá sa valueOf v prototypoch objektu a celý proces sa opakuje, kým sa nedokončí spracovanie hodnoty a nedôjde k prevodu všetkých hodnôt vo výraze na jeden typ.. Ak je pre objekt implementovaná metóda toString, ktorá vracia primitívnu hodnotu, potom sa táto metóda používa na reťazcovú konverziu. Pri tom výsledok aplikácie tejto metódy nie je nevyhnutne reťazec.

Napríklad, ak pre objekt ‘obj‘ je definovaná metóda toString,

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

metóda toString vracia práve reťazec, a pri sčítaní reťazca s číslom dostávame zlúčený reťazec:

`obj + 1 // '2001'` 

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

Ale ak prepíšeme toString, aby metóda vracala číslo, pri sčítaní objektu bude vykonaná matematická operácia s číselnou konverziou a dostaneme výsledok matematického sčítania.

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

`obj + 1 // '2001'`

Pri tom, ak vykonávame sčítanie s reťazcom, prebieha reťazcová konverzia a dostávame zlúčený reťazec.

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

Práve v tom spočíva dôvod mnohých chýb začínajúcich používateľov JavaScriptu.

Do metódy toString môžeš napísať funkciu, ktorá zvýši aktuálnu hodnotu objektu o 1.

Riešime praktické úlohy v Zabbix pomocou JavaScriptu
Spustenie skriptu za predpokladu, že premenná je 3, a tá istá premenná je 4.

Pri porovnávaní s porovnávaním typov (==) sa zakaždým vykonáva metóda toString s funkciou na zvýšenie hodnoty. Vzhľadom na to sa hodnota pri každom nasledujúcom porovnaní zvyšuje. Tomuto sa dá vyhnúť použitím porovnávania bez konverzie typov (===).

Riešime praktické úlohy v Zabbix pomocou JavaScriptu
Porovnávanie bez konverzie typov

POZNÁMKA. Nepoužívajte porovnávanie s konverziou typov bez potreby.

Pre zložité skripty, ako napríklad Webhook so zložitou logikou, kde je potrebné porovnávanie s konverziou typov, sa odporúča najskôr napísať kontroly pre hodnoty, ktoré vracajú premenné a spracovať nezhody a chyby.

Webhook Media

Na konci roku 2019 a začiatkom roku 2020 sa tím integrácie Zabbix aktívne zaoberal vývojom Webhooks a integrácií „out of the box“, ktoré sú dodávané v distribúcii Zabbix.

Riešime praktické úlohy v Zabbix pomocou JavaScriptu
Odkaz na dokumentácii

Predspracovanie

  • Objavenie sa predspracovania na JavaScripte umožnilo zbaviť sa väčšiny externých skriptov a v súčasnosti je v Zabbixe možné získať akúkoľvek hodnotu a pretransformovať ju na akúkoľvek inú hodnotu.
  • Predspracovanie v Zabbixe je implementované kódom na JavaScripte, ktorý sa pri kompilácii do bajtkódu transformuje na funkciu, ktorá prijíma jediné hodnoty ako parameter value v podobe reťazca (v reťazci môže byť aj číslo, aj číselná hodnota).
  • Keďže výsledkom je funkcia, na konci skriptu je povinné return.
  • Možné je použitie používateľských makier v kóde.
  • Zdroje môžu byť obmedzené nielen na úrovni operačného systému, ale aj programovo. Pre krok predspracovania je vyčlenených maximálne 10 megabajtov operačnej pamäte a časový limit vykonávania 10 sekúnd.

Riešime praktické úlohy v Zabbix pomocou JavaScriptu

POZNÁMKA. Hodnoty časového limitu 10 sekúnd sú celkom veľa, pretože zber podmienečne tisíc elementov dát za 1 sekundu pri dosť „náročnom“ scenári predspracovania môže spomaliť Zabbix. Preto sa neodporúča používať predspracovanie na vykonávanie plnohodnotných skriptov na JavaScripte prostredníctvom takzvaných tieňových elementov dát (dummy items), ktoré sa spúšťajú len na vykonávanie predspracovania..

Svoj kód môžete skontrolovať prostredníctvom testu predspracovania alebo pomocou nástroja 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`

Praktické úlohy

Úloha 1

Nahradiť vypočítaný prvok údajov predspracovaním.

Podmienka: získavame z čidla teplotu vo stupňoch Fahrenheita na uloženie v stupňoch Celzia.

Predtým sme vytvorili prvok údajov, ktorý zhromažďoval teplotu vo stupňoch Fahrenheita. Potom — ďalší prvok údajov (vypočítaný), ktorý by pomocou vzorca prevádzal stupne Fahrenheita na stupne Celzia.

Problémy:

  • Je potrebné duplikovať prvky údajov a uchovávať všetky hodnoty v databáze.
  • Je potrebné zosúladiť intervaly pre „rodičovský“ prvok údajov, ktorý sa vypočítava a využíva vo vzorci, a pre vypočítaný prvok údajov. V opačnom prípade sa môže vypočítaný prvok údajov dostat do nepodporovaného stavu alebo bude počítať predchádzajúcu hodnotu, čo ovplyvní spoľahlivosť výsledkov monitorovania.

Jedným z riešení bolo vzdať sa flexibilných kontrolných intervalov v prospech pevných intervalov, aby sa zabezpečilo, že sa vypočítaný prvok údajov vypočíta po prvku údajov, ktorý získava dáta (v našom prípade — teplota vo stupňoch Fahrenheita).

Ale ak, napríklad, používame šablónu na kontrolu veľkého počtu zariadení a kontrola sa vykonáva raz za 30 sekúnd, 29 sekúnd Zabbix „nečinne“, a v poslednej sekunde začína kontroly a výpočty. To vedie k vytvoreniu fronty a ovplyvňuje výkon. Preto sa odporúča používať pevné intervaly, iba ak je to naozaj potrebné.

V tejto úlohe je optimálnym riešením predspracovanie z jedného riadku v JavaScripte, ktoré konvertuje stupne Fahrenheita na stupne Celzia:

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

Je to rýchle a jednoduché, netreba vytvárať ďalšie prvky údajov a uchovávať ich históriu, a tiež sa dá použiť na kontroly flexibilné intervaly.

Riešime praktické úlohy v Zabbix pomocou JavaScriptu

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

Ale ak, v hypotetickej situácii, je potrebné získaný prvok údajov sčítať, napríklad, s nejakou konštantou definovanou v makre, je potrebné mať na pamäti, že parameter value sa rozširuje na reťazec. Pri operácii sčítania reťazcov, dve reťazce sa jednoducho skombinujú do jedného.

Riešime praktické úlohy v Zabbix pomocou JavaScriptu

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

Na dosiahnutie výsledku matematickej operácie je potrebné previesť typy získaných hodnôt do číselného formátu. Na to môžete použiť funkciu parseInt(), ktorá vracia celé číslo, funkciu parseFloat(), ktorá vracia desatinné číslo, alebo funkciu number, ktorá vracia celé číslo alebo desatinné číslo.

Úloha 2

Získať čas v sekundách do vypršania certifikátu.

Podmienka: istá služba vydáva dátum vypršania certifikátu vo formáte "Feb 12 12:33:56 2022 GMT".

V ECMAScript5 Date.parse() prijíma dátum vo formáte ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ). Je nutné previest reťazec do tohto formátu z formátu MMM DD YYYY HH:mm:ss ZZ

Problém: hodnota mesiaca je vyjadrená textom, nie číslom. Údaje v tomto formáte nie sú akceptované Duktape.

Príklad riešenia:

  • Najprv sa vyhlási premenná, ktorá prijme hodnotu (celý skript je vyhlásenie premenných, ktoré sú uvedené oddelené čiarkou).

  • V prvom riadku získame dátum v parametri value a rozdelíme ho pomocou medzier metódou split. Týmto spôsobom získame pole, kde každému prvku poľa, počnúc indexom 0, zodpovedá jeden prvok dátumu pred a po medzere. split(0) — mesiac, split(1) — deň, split(2) — reťazec s časom atď. Potom sa dá k jednotlivým prvkom dátumu pristupovať podľa indexu v poli.

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

  • Každému mesiacu (v chronologickom poradí) zodpovedá index jeho umiestnenia v poli (od 0 do 11). Ak chcete previesť textovú hodnotu na číselnú, k indexu mesiaca sa pripočíta jedna (pretože číslovanie mesiacov začína od 1). Pri tomto výraze na pripočítanie jednotky je potrebné použiť zátvorky, pretože inak dostaneme reťazec, nie číslo. Na konci vykonáme slice() — rez poľa zozadu, aby zostali iba dva znaky (čo je dôležité pre mesiace s dvojciferným číslom).

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

  • Tvoríme z získaných hodnôt reťazec vo formáte ISO obyčajným sčítaním reťazcov v príslušnom poradí.

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

Údaje v získanom formáte sú počet sekúnd od roku 1970 do nejakej budúcnosti. Použiť údaje v tomto formáte v spúšťačoch je takmer nemožné, pretože Zabbix umožňuje manipuláciu iba s makrami {Date} a {Time}, ktoré vracajú dátum a čas v používateľsky zrozumiteľnom formáte.

  • Potom môžeme získať v JavaScripte aktuálny dátum vo formáte Unix Timestamp a odčítať ho od získanej hodnoty dátumu skončenia certifikátu, aby sme získali počet milisekúnd od aktuálneho momentu do momentu skončenia certifikátu.

`now = Date.now();`

  • Delíme získanú hodnotu tisíc, aby sme získali sekundy v Zabbix.

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

V spúšťači môžete uviesť výraz 'last<' a súbor číslic, ktorý zodpovedá počtu sekúnd v období, na ktoré je potrebné reagovať, napríklad v týždňoch. Takto bude spúšťač upozorňovať na to, že platnosť certifikátu sa končí o týždeň.

POZNÁMKA. Venovať pozornosť používaniu parseInt() v funkcii return, aby sme prevedený zlomok, získaný výsledkom delenia milisekúnd, premenili na celé číslo. Môžeme tiež použiť parseFloat() a uchovávať desatinné údaje.

Pozrieť prezentáciu

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster