Praktické problémy řešíme v Zabbixu pomocí JavaScriptu

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu
Tichon Uskov, inženýr integračního týmu Zabbix

Zabbix je přizpůsobitelná platforma, která se používá ke sledování jakéhokoli druhu dat. Od nejstarších verzí Zabbix měli správci monitorování možnost spouštět různé skripty prostřednictvím Akce pro kontroly cílových síťových uzlů. Spuštění skriptů zároveň vedlo k řadě obtíží, včetně nutnosti podporovat skripty, jejich doručování do komunikačních uzlů a proxy a také podporu různých verzí.

JavaScript pro Zabbix

V dubnu 2019 byl představen Zabbix 4.2 s předzpracováním JavaScriptu. Mnoho lidí se nadchlo myšlenkou upustit od psaní skriptů, které někam berou data, stráví je a poskytují ve formátu, kterému Zabbix rozumí, a provádějí jednoduché kontroly, které přijmou data, která nejsou připravena pro uložení a zpracování v Zabbix, a poté tento datový tok zpracujte pomocí nástrojů Zabbix a JavaScript. Ve spojení s nízkoúrovňovým objevováním a závislými položkami, které se objevily v Zabbix 3.4, jsme získali poměrně flexibilní koncept pro třídění a správu přijatých dat.

V Zabbix 4.4 se jako logické pokračování předzpracování v JavaScriptu objevila nová metoda upozornění – Webhook, kterou lze snadno integrovat upozornění Zabbixu s aplikacemi třetích stran.

JavaScript a duktapes

Proč byly vybrány JavaScript a Duktape? Byly zváženy různé možnosti jazyků a motorů:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - duktape
  • Javascript - JerryScript
  • Vestavěný Python
  • Embedded Perl

Hlavními kritérii výběru byla rozšířenost, snadná integrace motoru do produktu, nízká spotřeba zdrojů a celkový výkon motoru a bezpečnost zavedení kódu v tomto jazyce do monitorování. Na základě kombinace indikátorů zvítězil JavaScript na enginu Duktape.

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu

Kritéria výběru a testování výkonu

Vlastnosti Duktape:

- Standard ECMAScript E5/E5.1
- Moduly Zabbix pro Duktape:

  • Zabbix.log() – umožňuje zapisovat zprávy s různou úrovní podrobností přímo do protokolu serveru Zabbix, což umožňuje korelovat chyby, například ve Webhooku, se stavem serveru.
  • CurlHttpRequest() - umožňuje zadávat HTTP požadavky do sítě, na které je založeno použití Webhooku.
  • atob() a btoa() - umožňuje kódovat a dekódovat řetězce ve formátu Base64.

POZNÁMKA. Duktape vyhovuje standardům ACME. Zabbix používá verzi skriptu z roku 2015. Následné změny jsou drobné, takže je lze ignorovat..

Magie JavaScriptu

Veškeré kouzlo JavaScriptu spočívá v dynamickém psaní a přetypování: řetězcové, číselné a booleovské.

To znamená, že není nutné předem deklarovat, jaký typ má proměnná vracet hodnotu.

V matematických operacích jsou hodnoty vrácené funkčními operátory převedeny na čísla. Výjimkou z těchto operací je sčítání, protože pokud je alespoň jeden z výrazů řetězec, převod řetězce se použije na všechny výrazy.

POZNÁMKA. Metody odpovědné za takové transformace jsou obvykle implementovány v nadřazených prototypech objektu, hodnota и toString. hodnota volána při numerickém převodu a vždy před metodou toString. Metoda hodnota musí vrátit primitivní hodnoty, jinak je jeho výsledek ignorován.

Na objektu je volána metoda hodnota. Pokud není nalezen nebo nevrací primitivní hodnotu, je zavolána metoda toString. Pokud metoda toString nenalezeno, hledám hodnota v prototypu objektu a vše se opakuje, dokud není dokončeno zpracování hodnoty a všechny hodnoty ve výrazu jsou přetypovány na stejný typ. Pokud objekt implementuje metodu toString, která vrací primitivní hodnotu, pak je to ta, která se používá pro převod řetězce. Výsledkem použití této metody však nemusí být nutně řetězec.

Pokud například for for object 'Objje definována metoda toString,

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

Metoda toString vrátí přesně řetězec a při přidání řetězce s číslem dostaneme slepený řetězec:

`obj + 1 // '2001'` 

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

Ale když přepíšeš toString, tak aby metoda vrátila číslo, při sečtení objektu se provede matematická operace s numerickým převodem a získá se výsledek matematického sčítání.

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

`obj + 1 // '2001'`

V tomto případě, pokud provádíme sčítání pomocí provázku, provede se převod řetězce a získáme slepený provázek.

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

To je důvodem velkého počtu chyb začínajících uživatelů JavaScriptu.

Metoda toString můžete napsat funkci, která zvýší aktuální hodnotu objektu o 1.

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu
Provedení skriptu za předpokladu, že proměnná je rovna 3 a je také rovna 4.

Při porovnání s přetypováním (==) se metoda provede pokaždé toString s funkcí zvýšení hodnoty. V souladu s tím se s každým dalším srovnáním hodnota zvyšuje. Tomu se lze vyhnout použitím nepřetypovaného porovnání (===).

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu
Srovnání bez typového odlitku

POZNÁMKA. Nepoužívejte porovnávání obsazení zbytečně.

U složitých skriptů, jako jsou webhooky se složitou logikou, které vyžadují srovnání s přetypováním, se doporučuje předem zapsat kontroly hodnot, které vracejí proměnné a řeší nekonzistence a chyby.

Webhook Media

Koncem roku 2019 a začátkem roku 2020 integrační tým Zabbix aktivně vyvíjel webhooky a integrované integrace, které přicházejí s distribucí Zabbix.

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu
Odkaz na dokumentace

Předběžné zpracování

  • Nástup předzpracování v JavaScriptu umožnil opustit většinu externích skriptů a aktuálně v Zabbixu můžete získat libovolnou hodnotu a převést ji na úplně jinou hodnotu.
  • Předzpracování v Zabbix je implementováno kódem JavaScript, který se po zkompilování do bajtkódu převede na funkci, která má jako parametr jedinou hodnotu hodnota jako řetězec (řetězec může obsahovat číslici i číslo).
  • Vzhledem k tomu, že výstupem je funkce, je na konci skriptu vyžadováno zpáteční.
  • V kódu je možné použít vlastní makra.
  • Prostředky lze omezit nejen na úrovni operačního systému, ale také programově. Kroku předběžného zpracování je přiděleno maximálně 10 megabajtů paměti RAM a doba běhu je omezena na 10 sekund.

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu

POZNÁMKA. Hodnota časového limitu 10 sekund je poměrně hodně, protože shromažďování podmíněných tisíců datových položek za 1 sekundu podle poměrně „těžkého“ scénáře předzpracování může Zabbix zpomalit. Proto se nedoporučuje používat předzpracování pro spouštění plnohodnotných JavaScriptových skriptů prostřednictvím tzv. stínových datových prvků (dummy items), které jsou spouštěny pouze za účelem provedení předzpracování.

Svůj kód můžete zkontrolovat pomocí testu předběžného zpracování nebo pomocí nástroje 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é úkoly

Úkol 1

Nahraďte vypočítanou položku předzpracováním.

Stav: Získání teploty ve stupních Fahrenheita ze senzoru pro uložení ve stupních Celsia.

Dříve jsme vytvořili položku, která shromažďuje teplotu ve stupních Fahrenheita. Poté další datová položka (vypočtená), která by pomocí vzorce převedla Fahrenheita na stupně Celsia.

Problémy:

  • Je nutné duplikovat datové prvky a uložit všechny hodnoty do databáze.
  • Musíte se dohodnout na intervalech pro „nadřazenou“ datovou položku, která se počítá a používá ve vzorci, a pro počítanou datovou položku. V opačném případě může vypočítaná položka přejít do nepodporovaného stavu nebo vypočítat předchozí hodnotu, což ovlivní spolehlivost výsledků monitorování.

Jedním z řešení bylo upustit od flexibilních kontrolních intervalů ve prospěch pevných intervalů, aby bylo zajištěno, že počítaná položka bude vyhodnocena po položce, která přijímá data (v našem případě teplota ve stupních Fahrenheita).

Pokud ale například pomocí šablony kontrolujeme velké množství zařízení a kontrola se provádí jednou za 30 sekund, Zabbix „hackuje“ 29 sekund a na poslední sekundu začne kontrolovat a počítat. To vytváří frontu a ovlivňuje výkon. Proto se doporučuje používat pevné intervaly pouze v případě, že je to skutečně nutné.

V tomto problému je optimálním řešením jednořádkové předběžné zpracování JavaScriptu, které převádí stupně Fahrenheita na stupně Celsia:

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

Je to rychlé a snadné, nemusíte vytvářet zbytečné datové položky a vést na nich historii a můžete využít i flexibilní intervaly kontrol.

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu

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

Pokud je však v hypotetické situaci nutné přidat přijatý datový prvek, například s jakoukoli konstantou definovanou v makru, je třeba vzít v úvahu, že parametr hodnota expanduje do řetězce. Při operaci sčítání řetězců se dva řetězce jednoduše spojí do jednoho.

Praktické problémy řešíme v Zabbixu pomocí JavaScriptu

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

Pro získání výsledku matematické operace je nutné převést typy získaných hodnot do číselného formátu. K tomu můžete použít funkci parseInt(), který vytváří celé číslo, funkci parseFloat(), který vytváří desetinné číslo nebo funkci číslo, který vrací celé číslo nebo desetinné číslo.

2 výzva

Získejte čas v sekundách do konce certifikátu.

Stav: služba vydává datum vypršení platnosti certifikátu ve formátu „12. února 12:33:56 2022 GMT“.

V ECMAScript5 date.parse() přijímá datum ve formátu ISO 8601 (RRRR-MM-DDTHH:mm:ss.sssZ). Je nutné do něj přetypovat řetězec ve formátu MMM DD RRRR HH:mm:ss ZZ

problém: Hodnota měsíce je vyjádřena jako text, nikoli jako číslo. Data v tomto formátu Duktape nepřijímá.

Příklad řešení:

  • Nejprve se deklaruje proměnná, která nabývá hodnoty (celý skript je deklarace proměnných, které jsou uvedeny oddělené čárkami).

  • V prvním řádku dostaneme datum v parametru hodnota a oddělte jej mezerami pomocí metody rozdělit. Dostaneme tedy pole, kde každý prvek pole počínaje indexem 0 odpovídá jednomu datovému prvku před a za mezerou. rozdělit(0) - Měsíc, rozdělit(1) - číslo, rozdělit(2) - řetězec s časem atd. Poté lze ke každému prvku data přistupovat pomocí indexu v poli.

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

  • Každý měsíc (v chronologickém pořadí) odpovídá indexu jeho pozice v poli (od 0 do 11). Chcete-li převést textovou hodnotu na číselnou hodnotu, je k indexu měsíce přidána jedna (protože měsíce jsou číslovány od 1). V tomto případě se výraz s přidáním jedničky bere v závorkách, protože jinak se získá řetězec, nikoli číslo. Nakonec ano plátek() - ořízněte pole od konce, aby zůstaly pouze dva znaky (což je důležité pro měsíce s dvouciferným číslem).

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

  • Ze získaných hodnot vytvoříme řetězec ve formátu ISO obvyklým sčítáním řetězců v příslušném pořadí.

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

Data ve výsledném formátu představují počet sekund od roku 1970 do určitého bodu v budoucnosti. Použít data v přijatém formátu ve triggerech je téměř nemožné, protože Zabbix umožňuje operovat pouze s makry {Datum} и {Čas}, které vracejí datum a čas v uživatelsky přívětivém formátu.

  • Poté můžeme získat aktuální datum v JavaScriptu ve formátu Unix Timestamp a odečíst ho od výsledného data vypršení platnosti certifikátu, abychom získali počet milisekund od nynějška do vypršení platnosti certifikátu.

`now = Date.now();`

  • Přijatou hodnotu vydělíme tisíci, abychom dostali sekundy v Zabbixu.

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

Ve spouštěči můžete zadat výraz 'poslední' následovaný sadou číslic, která odpovídá počtu sekund v období, na které chcete odpovědět, například v týdnech. Spouštěč tedy oznámí, že platnost certifikátu za týden vyprší.

POZNÁMKA. Věnujte pozornost použití parseInt() ve funkci zpátečnípřevést zlomkové číslo vyplývající z dělení milisekund na celé číslo. Můžete také použít parseFloat() a ukládat zlomková data.

Podívejte se na reportáž

Zdroj: www.habr.com

Přidat komentář