Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu
Tikhon Uskov, inženýr týmu integrace Zabbix

Zabbix je přizpůsobitelná platforma, která se používá k monitorování jakýchkoli dat. Od nejranějších verzí Zabbix měli správci monitorování možnost spouštět různé skripty prostřednictvím Akce pro kontroly na cílových uzlech sítě. Spuštění skriptů však vedlo k různým obtížím, včetně potřeby podpory skriptů, jejich dodání na spojovací uzly a proxy, stejně jako podpory různých verzí.

JavaScript pro Zabbix

V dubnu 2019 byla představena verze Zabbix 4.2 s funkcí předzpracování na JavaScriptu. Mnozí byli nadšeni myšlenkou vzdát se psaní skriptů, které někde získávají data, zpracovávají je a poskytují v formátu srozumitelném pro Zabbix, a místo toho provádět jednoduché kontroly, které získají nehotová data pro ukládání a zpracování v Zabbixu a poté zpracovávají tento datový tok pomocí prostředků Zabbix a JavaScriptu. V kombinaci s nízkoúrovňovým objevováním a závislými prvky dat, které se objevily v Zabbix 3.4, vznikla dostatečně flexibilní koncepce pro třídění a řízení získaných dat.

V Zabbix 4.4, jako logické pokračování předzpracování na JavaScriptu, se objevil nový způsob upozorňování — Webhook, který lze použít pro jednoduchou integraci upozornění Zabbix s externími aplikacemi.

JavaScript a Duktape

Proč byly vybrány právě JavaScript a Duktape? Byly zvažovány různé možnosti jazyků a enginů:

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

Hlavními kritérii výběru byly rozšířenost, jednoduchost integrace enginu do produktu, nízká spotřeba zdrojů a celkový výkon enginu, a bezpečnost vkládání kódu v tomto jazyce do monitorování. Na základě těchto kritérií zvítězil JavaScript na enginu Duktape.

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu

Kritéria výběru a performance testing

Charakteristiky Duktape:

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

  • Zabbix.log() — umožňuje zapisovat přímo do logu Zabbix Server zprávy s různými úrovněmi detailů, což umožňuje porovnávat chyby, například v Webhooku, se stavem serveru.
  • CurlHttpRequest() — umožňuje provádět HTTP požadavky na síť, na čemž je založeno použití Webhooku.
  • atob() a btoa() — umožňují kódovat a dekódovat řetězce do formátu Base64.

POZNÁMKA. Duktape splňuje standardy ACME. Ve Zabbixu je použita verze skriptu z roku 2015. Následné změny jsou zanedbatelné, a tedy je možné je ignorovat..

Kouzlo JavaScriptu

Veškeré kouzlo JavaScriptu spočívá v dynamické typizaci a konverzi typů: řetězcových, číselných a logických.

To znamená, že není nutné předem deklarovat, jaký typ by měla proměnná vrátit.

Při matematických operacích se hodnoty, které vrací funkce-operátory, převádějí na čísla. Výjimkou z těchto operací je sčítání, protože pokud je alespoň jeden z cifer řetězec, na všechny cifry se použije řetězcová konverze.

POZNÁMKA. Metody, které se postarají o takové konverze, jsou obvykle implementovány v rodičovských prototypech objektů, valueOf a toString. valueOf se volá při číselné konverzi a vždy před metodou toString. Metoda valueOf musí vracet primitivní hodnoty, jinak je její výsledek ignorován.

Pro objekt se zavolá metoda valueOf. Pokud není nalezena nebo nevrací primitivní hodnotu, zavolá se metoda toString. Pokud metoda toString není nalezena, hledá se valueOf v prototypu objektu a vše se opakuje, dokud není vyřešena hodnota a všechny hodnoty ve výrazu jsou převedeny na jeden typ.. Pokud pro objekt existuje metoda toString, která vrací primitivní hodnotu, bude právě ta použita pro řetězcovou konverzi. Přitom výsledkem aplikace této metody nemusí být nutně řetězec.

Například, pokud pro objekt ‘obj‘ je definována metoda toString,

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

metoda toString skutečně vrátí řetězec, a při sčítání řetězce s číslem dostaneme spojení řetězce:

`obj + 1 // '2001'` 

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

Ale pokud bychom přepsali toString, aby metoda vracela číslo, při sčítání objektu by se vykonávala matematická operace s číselnou konverzí a dostali bychom výsledek matematického sčítání.

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

`obj + 1 // '2001'`

Přitom, pokud provádíme sčítání se stringem, probíhá řetězcová konverze, a dostáváme spojení řetězce.

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

Právě v tom spočívá důvod pro velké množství chyb začínajících uživatelů JavaScriptu.

Do metody toString je možné zapsat funkci, která zvýší aktuální hodnotu objektu o 1.

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu
Vykonání skriptu za podmínky, že proměnná je rovna 3, a zároveň je rovna 4.

Při porovnání s přetypováním (==) se vždy spouští metoda toString s funkcí zvyšování hodnoty. V souladu s tím se při každém dalším porovnání hodnota zvyšuje. Tomu se lze vyhnout použitím porovnání bez přetypování (===).

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu
Porovnání bez přetypování

POZNÁMKA. Nepoužívejte porovnání s přetypováním bez důvodu.

Pro složité skripty, jako například Webhook se složitou logikou, ve kterých je třeba provést porovnání s přetypováním, se doporučuje předem napsat kontroly pro hodnoty, které vracejí proměnné, a zpracovat nesoulady a chyby.

Webhook Media

Na konci roku 2019 a na začátku roku 2020 se tým integrace Zabbix aktivně věnoval vývoji Webhooků a "out-of-the-box" integrací dodávaných v distribuci Zabbix.

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu
Odkaz na dokumentaci

Preprocessing

  • Objevení předzpracování v JavaScriptu umožnilo opustit většinu externích skriptů, a v současné době lze v Zabbixu získat jakoukoli hodnotu a převést ji na jakoukoli jinou hodnotu.
  • Předzpracování v Zabbixu je realizováno kódem v JavaScriptu, který se při kompilaci do bajtkódu převádí na funkci, která přijímá jediné hodnoty jako parametr value ve formě řetězce (v řetězci může být také číslo).
  • Protože na výstupu vzniká funkce, na konci skriptu je povinný vrátit.
  • Možnost použití uživatelských makro v kódu.
  • Zdroje lze omezit nejen na úrovni operačního systému, ale také programově. Pro krok předzpracování je vyhrazeno maximálně 10 megabajtů operační paměti a časový limit provádění je 10 sekund.

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu

POZNÁMKA. Hodnoty časového limitu 10 sekund jsou poměrně dostatečné, protože shromáždění podmínkových tisíců datových prvků za 1 sekundu při poměrně "těžkém" scénáři předzpracování může zpomalit práci Zabbixu. Proto se nedoporučuje využívat předzpracování k provádění plnohodnotných skriptů v JavaScriptu prostřednictvím takzvaných dummy items, které se spouštějí pouze k provedení předzpracování..

Své kódy můžete zkontrolovat pomocí testu předzpracování nebo pomocí utility. 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

Nahradit vypočítávanou datovou položku předzpracováním.

Podmínka: získáváme ze senzoru teplotu ve stupních Fahrenheita pro uchování ve stupních Celsia.

Dříve bychom vytvořili datovou položku, která shromažďuje teplotu ve stupních Fahrenheita. Poté další datovou položku (vypočítávanou), která by podle vzorce převáděla stupně Fahrenheita na stupně Celsia.

Problémy:

  • Je nutné duplikovat datové položky a uchovávat všechny hodnoty v databázi.
  • Je nutné sladit intervaly pro 'rodičovskou' datovou položku, která se počítá a používá ve vzorci, a pro vypočítávanou datovou položku. Jinak se vypočítávaná datová položka může dostat do neudržovaného stavu nebo počítat předchozí hodnotu, což ovlivní spolehlivost výsledků monitorování.

Jedním z řešení bylo vzdát se flexibilních kontrolních intervalů ve prospěch pevných intervalů, aby bylo zaručeno, že se vypočítávaná datová položka vypočítá po datové položce, která získává data (v našem případě — teplota ve stupních Fahrenheita).

Ale pokud například používáme šablonu pro kontrolu velkého množství zařízení a kontrola se provádí každých 30 sekund, 29 sekund Zabbix 'odpočívá' a v poslední sekundě začíná kontroly a výpočty. To vede ke vzniku fronty 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 úkolu je optimálním řešením předzpracování z jednoho řádku v JavaScriptu, které převádí stupně Fahrenheita na stupně Celsia:

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

Je to rychlé a jednoduché, není potřeba vytvářet zbytečné datové položky a uchovávat historii, a navíc je možné použít flexibilní intervaly pro kontroly.

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu

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

Ale pokud by v hypotetické situaci bylo nutné získanou datovou položku sečíst například s nějakou konstantou definovanou v makru, je třeba vzít v úvahu, že parametr value se rozvine do řetězce. Při operaci sčítání řetězců se dva řetězce jednoduše spojí do jednoho.

Řešíme praktické úkoly v Zabbixu pomocí JavaScriptu

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

Aby získali výsledek matematické operace, je nutné převést typy získaných hodnot na číselný formát. K tomu lze použít funkci parseInt(), která vrací celé číslo, funkci parseFloat(), která vrací desetinné číslo, nebo funkci number, která vrací celé číslo nebo desetinné číslo.

Úkol 2

Získat čas v sekundách do vypršení platnosti certifikátu.

Podmínka: nějaká služba vrací datum vypršení platnosti certifikátu ve formátu "Feb 12 12:33:56 2022 GMT".

V ECMAScript5 Date.parse() přijímá datum ve formátu ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ). Je nutné převést řetězec na formát MMM DD YYYY HH:mm:ss ZZ

Problém: hodnota měsíce je vyjádřena textem, nikoli číslem. Tato data v takovém formátu nejsou akceptována Duktape.

Příklad řešení:

  • Nejprve se deklaruje proměnná, která přijímá hodnotu (celý skript je deklarace proměnných, které jsou uvedeny odděleně čárkou).

  • V prvním řádku získáváme datum v parametru value a dělíme ho mezerami metodou split. Takto získáme pole, kde každému prvku pole, počínaje indexem 0, odpovídá jeden prvek data před a za mezerou. split(0) — měsíc, split(1) — den, split(2) — řetězec s časem atd. Poté je možné k jednotlivým prvkům data přistupovat podle indexu v poli.

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

  • Každému měsíci (v chronologickém pořadí) odpovídá index jeho polohy v poli (od 0 do 11). Abychom převedli textovou hodnotu na číselnou, k indexu měsíce se přičte jedna (protože číslování měsíců začíná od 1). Při tomto výrazu je přičtení jedničky uzavřeno do závorek, protože jinak by vznikl řetězec, nikoli číslo. Nakonec provádíme slice() — výřez pole z konce, abychom ponechali pouze dva znaky (což je důležité pro měsíce s dvoumístný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),`

  • Tvoříme z získaných hodnot řetězec ve formátu ISO běžným sčítáním řetězců v odpovídajícím pořadí.

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

Data v získaném formátu — počet sekund od roku 1970 do nějakého okamžiku v budoucnosti. Použít data v tomto formátu v spouštěčích je prakticky nemožné, protože Zabbix umožňuje pracovat pouze s makry {Date} a {Time}, které vracejí datum a čas v uživatelsky přívětivém formátu.

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

`now = Date.now();`

  • Dělíme získanou hodnotu tisícem, abychom dostali sekundy v Zabbixu.

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

V triggeru lze uvést výraz ‘last<‘ a sadu číslic, která odpovídá počtu sekund v období, na které je třeba reagovat, například v týdnech. Takže trigger bude upozorňovat na to, že platnost certifikátu končí za týden.

POZNÁMKA. Všimněte si použití parseInt() ve funkci vrátit, aby konvertoval desetinné číslo získané z dělení milisekund na celé číslo. Také lze použít parseFloat() a ukládat desetinná data..

Podívejte se na zprávu.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster