Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript
Tichon Uskow, inżynier zespołu integracyjnego Zabbix

Zabbix to konfigurowalna platforma, która służy do monitorowania wszelkiego rodzaju danych. Od najwcześniejszych wersji Zabbix administratorzy monitorowania mieli możliwość uruchamiania różnych skryptów poprzez Akcje do kontroli docelowych węzłów sieci. Jednocześnie uruchomienie skryptów wiązało się z szeregiem trudności, w tym koniecznością obsługi skryptów, ich dostarczania do węzłów komunikacyjnych i serwerów proxy, a także obsługi różnych wersji.

JavaScript dla Zabbixa

W kwietniu 2019 roku wprowadzono Zabbix 4.2 z przetwarzaniem wstępnym JavaScript. Wiele osób ekscytowało się pomysłem porzucenia pisania skryptów, które gdzieś pobierają dane, trawią je i dostarczają w formacie zrozumiałym dla Zabbix oraz wykonują proste kontrole, które otrzymają dane, które nie są gotowe do przechowywania i przetwarzania przez Zabbix, oraz następnie przetwarzaj ten strumień danych za pomocą narzędzi Zabbix i JavaScript. W połączeniu z niskim poziomem wykrywania i elementami zależnymi, które pojawiły się w Zabbix 3.4, otrzymaliśmy dość elastyczną koncepcję sortowania i zarządzania otrzymanymi danymi.

W Zabbix 4.4, jako logiczna kontynuacja przetwarzania wstępnego w JavaScript, pojawiła się nowa metoda powiadomień – Webhook, za pomocą której można łatwo zintegrować powiadomienia Zabbix z aplikacjami firm trzecich.

JavaScript i Duktape

Dlaczego wybrano JavaScript i Duktape? Rozważano różne opcje języków i silników:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript — Duktape
  • JavaScript – JerryScript
  • Wbudowany Python
  • Wbudowany Perl

Głównymi kryteriami wyboru były rozpowszechnienie, łatwość integracji silnika z produktem, niskie zużycie zasobów i ogólna wydajność silnika oraz bezpieczeństwo wprowadzenia kodu w tym języku do monitoringu. Bazując na kombinacji wskaźników, JavaScript wygrał na silniku Duktape.

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript

Kryteria wyboru i testy wydajności

Cechy Duktape'a:

— Standardowy ECMAScript E5/E5.1
— Moduły Zabbix dla Duktape:

  • Zabbix.log() - umożliwia zapisywanie komunikatów o różnych poziomach szczegółowości bezpośrednio do dziennika Zabbix Server, co umożliwia korelację błędów, na przykład w Webhooku, ze stanem serwera.
  • CurlHttpRequest() - umożliwia wysyłanie żądań HTTP do sieci, na których opiera się korzystanie z Webhooka.
  • atob() i btoa() - umożliwia kodowanie i dekodowanie napisów w formacie Base64.

UWAGA. Duktape jest zgodny ze standardami ACME. Zabbix używa skryptu w wersji 2015. Kolejne zmiany są niewielkie, więc można je zignorować..

Magia JavaScriptu

Cała magia JavaScript polega na dynamicznym typowaniu i rzutowaniu typów: łańcuchowych, liczbowych i boolowskich.

Oznacza to, że nie trzeba z góry deklarować, jakiego typu zmienna ma zwracać wartość.

W operacjach matematycznych wartości zwracane przez operatory funkcji są konwertowane na liczby. Wyjątkiem od takich operacji jest dodawanie, ponieważ jeśli co najmniej jeden z terminów jest łańcuchem, konwersja łańcuchów jest stosowana do wszystkich terminów.

UWAGA. Metody odpowiedzialne za takie przekształcenia są zwykle zaimplementowane w prototypach nadrzędnych obiektu, wartość и do Ciągu. wartość wywoływana podczas konwersji numerycznej i zawsze przed metodą do Ciągu. metoda wartość musi zwracać wartości pierwotne, w przeciwnym razie jego wynik jest ignorowany.

Metoda jest wywoływana na obiekcie wartość. Jeśli nie zostanie znaleziona lub nie zwróci wartości pierwotnej, metoda zostanie wywołana do Ciągu. Jeśli metoda do Ciągu nie znaleziono, szukam wartość w prototypie obiektu i wszystko jest powtarzane aż do zakończenia przetwarzania wartości i rzutowania wszystkich wartości w wyrażeniu na ten sam typ. Jeśli obiekt implementuje metodę do Ciągu, która zwraca wartość pierwotną, to właśnie ona jest używana do konwersji łańcuchów. Jednak wynikiem zastosowania tej metody niekoniecznie jest ciąg znaków.

Na przykład, jeśli for for obiekt 'ObjMetoda jest zdefiniowana do Ciągu,

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

Metoda do Ciągu zwraca dokładnie ciąg, a dodając ciąg z liczbą otrzymujemy sklejony ciąg:

`obj + 1 // '2001'` 

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

Ale jeśli napiszesz od nowa do Ciągu, aby metoda zwracała liczbę, po dodaniu obiektu zostanie wykonana operacja matematyczna z konwersją liczbową i otrzymany zostanie wynik dodawania matematycznego.

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

`obj + 1 // '2001'`

W takim przypadku, jeśli wykonamy dodawanie za pomocą łańcucha, zostanie dokonana konwersja ciągu i otrzymamy sklejony ciąg.

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

Jest to powodem dużej liczby błędów popełnianych przez początkujących użytkowników JavaScript.

Metoda do Ciągu możesz napisać funkcję, która zwiększy aktualną wartość obiektu o 1.

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript
Wykonanie skryptu pod warunkiem, że zmienna jest równa 3, a także jest równa 4.

W porównaniu z rzutowaniem (==) metoda jest wykonywana za każdym razem do Ciągu z funkcją wzrostu wartości. W związku z tym z każdym kolejnym porównaniem wartość wzrasta. Można tego uniknąć, stosując porównanie bez rzutowania (===).

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript
Porównanie bez rzutowania typów

UWAGA. Nie używaj niepotrzebnie porównania obsady.

W przypadku złożonych skryptów, takich jak Webhook ze złożoną logiką, które wymagają porównania z rzutowaniem typów, zaleca się wstępne sprawdzenie wartości, które zwracają zmienne i obsługują niespójności i błędy.

Media webhook

Pod koniec 2019 i na początku 2020 roku zespół integracyjny Zabbix aktywnie rozwijał Webhooki i gotowe integracje, które są dostarczane z dystrybucją Zabbix.

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript
Link do dokumentacja

Przetwarzanie wstępne

  • Pojawienie się preprocessingu w JavaScript umożliwiło rezygnację z większości zewnętrznych skryptów, a obecnie w Zabbix można uzyskać dowolną wartość i przekonwertować ją na zupełnie inną wartość.
  • Przetwarzanie wstępne w Zabbix jest realizowane przez kod JavaScript, który po skompilowaniu do kodu bajtowego jest konwertowany na funkcję przyjmującą jako parametr pojedynczą wartość wartość jako ciąg znaków (łańcuch znaków może zawierać zarówno cyfrę, jak i liczbę).
  • Ponieważ wyjście jest funkcją, na końcu skryptu jest wymagane powrót.
  • Możliwe jest użycie niestandardowych makr w kodzie.
  • Zasoby można ograniczać nie tylko na poziomie systemu operacyjnego, ale także programowo. Etap przetwarzania wstępnego ma przydzielone maksymalnie 10 megabajtów pamięci RAM i limit czasu działania wynoszący 10 sekund.

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript

UWAGA. Wartość limitu czasu wynosząca 10 sekund to całkiem sporo, ponieważ gromadzenie warunkowych tysięcy elementów danych w ciągu 1 sekundy zgodnie z dość „ciężkim” scenariuszem przetwarzania wstępnego może spowolnić działanie Zabbix. W związku z tym nie zaleca się wykorzystywania preprocessingu do wykonywania pełnowartościowych skryptów JavaScript poprzez tzw..

Możesz sprawdzić swój kod za pomocą testu wstępnego przetwarzania lub za pomocą narzędzia 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`

Zadania praktyczne

Zadanie 1

Zastąp obliczony element wstępnym przetwarzaniem.

Stan: schorzenie: Pobierz temperaturę w stopniach Fahrenheita z czujnika, aby zapisać ją w stopniach Celsjusza.

Wcześniej tworzyliśmy element, który zbierał temperaturę w stopniach Fahrenheita. Następnie inny element danych (obliczony), który przeliczy stopnie Fahrenheita na stopnie Celsjusza przy użyciu wzoru.

Problemy:

  • Konieczne jest zduplikowanie elementów danych i przechowywanie wszystkich wartości w bazie danych.
  • Należy uzgodnić interwały dla „nadrzędnego” elementu danych, który jest obliczany i używany w formule, oraz dla obliczanego elementu danych. W przeciwnym razie wyliczana pozycja może przejść w stan nieobsługiwany lub obliczyć poprzednią wartość, co wpłynie na wiarygodność wyników monitoringu.

Jednym z rozwiązań było odejście od elastycznych interwałów sprawdzania na rzecz stałych interwałów, aby zapewnić, że obliczany element jest oceniany po elemencie, który otrzymuje dane (w naszym przypadku temperatura w stopniach Fahrenheita).

Ale jeśli na przykład użyjemy szablonu do sprawdzenia dużej liczby urządzeń, a kontrola jest wykonywana raz na 30 sekund, Zabbix „hakuje” przez 29 sekund, aw ostatniej sekundzie zaczyna sprawdzać i obliczać. Spowoduje to utworzenie kolejki i wpłynie na wydajność. Dlatego zaleca się stosowanie stałych interwałów tylko wtedy, gdy jest to naprawdę konieczne.

W tym problemie optymalnym rozwiązaniem jest jednoliniowe przetwarzanie wstępne JavaScript, które konwertuje stopnie Fahrenheita na stopnie Celsjusza:

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

Jest to szybkie i łatwe, nie trzeba tworzyć zbędnych elementów danych i przechowywać ich historii, a także można stosować elastyczne interwały kontroli.

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript

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

Jeżeli jednak w hipotetycznej sytuacji zachodzi konieczność dodania otrzymanego elementu danych, np. z dowolną stałą zdefiniowaną w makrze, to należy wziąć pod uwagę, że parametr wartość rozwija się w ciąg. W operacji dodawania ciągów dwa ciągi są po prostu łączone w jeden.

Rozwiązujemy praktyczne problemy w Zabbix za pomocą JavaScript

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

Aby uzyskać wynik operacji matematycznej, konieczne jest przekonwertowanie typów uzyskanych wartości na format liczbowy. W tym celu możesz użyć funkcji parseInt(), która tworzy liczbę całkowitą, funkcję parseFloat(), która tworzy ułamek dziesiętny lub funkcję numer, która zwraca liczbę całkowitą lub dziesiętną.

Zadanie 2

Uzyskaj czas w sekundach do końca ważności certyfikatu.

Stan: schorzenie: usługa wystawia datę wygaśnięcia certyfikatu w formacie „Feb 12 12:33:56 2022 GMT”.

W ECMAScript5 Analiza daty() akceptuje datę w formacie ISO 8601 (RRRR-MM-DDTHH:mm:ss.sssZ). Konieczne jest rzutowanie na niego napisu w formacie MMM DD RRRR HH:mm:ss ZZ

problem: Wartość miesiąca jest wyrażona jako tekst, a nie jako liczba. Dane w tym formacie nie są akceptowane przez Duktape.

Przykład rozwiązania:

  • Przede wszystkim deklarowana jest zmienna, która przyjmuje wartość (cały skrypt jest deklaracją zmiennych, które są wymienione oddzielone przecinkami).

  • W pierwszym wierszu otrzymujemy datę w parametrze wartość i oddziel je spacjami za pomocą metody dzielić. W ten sposób otrzymujemy tablicę, w której każdy element tablicy, zaczynając od indeksu 0, odpowiada jednemu elementowi daty przed i po spacji. podział(0) - miesiąc, podział(1) - numer, podział(2) - ciąg z czasem itp. Następnie każdy element daty może być dostępny poprzez indeks w tablicy.

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

  • Każdy miesiąc (w porządku chronologicznym) odpowiada indeksowi jego pozycji w tablicy (od 0 do 11). Aby przekonwertować wartość tekstową na wartość liczbową, do indeksu miesiąca dodaje się jedynkę (ponieważ numeracja miesięcy zaczyna się od 1). W tym przypadku wyrażenie z dodatkiem jedynki jest brane w nawiasy, ponieważ w przeciwnym razie otrzymamy ciąg znaków, a nie liczbę. Na koniec robimy plasterek() - odetnij tablicę od końca, aby zostawić tylko dwa znaki (co jest ważne w przypadku miesięcy z liczbą dwucyfrową).

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

  • Tworzymy ciąg w formacie ISO z uzyskanych wartości przez zwykłe dodanie ciągów w odpowiedniej kolejności.

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

Dane w formacie wynikowym to liczba sekund od roku 1970 do pewnego momentu w przyszłości. Wykorzystanie danych w odebranym formacie w wyzwalaczach jest prawie niemożliwe, ponieważ Zabbix pozwala operować tylko makrami {Data} и {Czas}, które zwracają datę i godzinę w przyjaznym dla użytkownika formacie.

  • Następnie możemy pobrać aktualną datę w JavaScript w formacie Unix Timestamp i odjąć ją od wynikowej daty wygaśnięcia certyfikatu, aby uzyskać liczbę milisekund od teraz do wygaśnięcia certyfikatu.

`now = Date.now();`

  • Otrzymaną wartość dzielimy przez tysiąc, aby uzyskać sekundy w Zabbix.

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

W wyzwalaczu możesz określić wyrażenie „ostatni', po którym następuje zestaw cyfr odpowiadający liczbie sekund w okresie, na który chcesz odpowiedzieć, na przykład w tygodniach. W ten sposób wyzwalacz powiadomi, że certyfikat wygaśnie za tydzień.

UWAGA. Zwróć uwagę na użycie parseInt() w funkcji powrótzamienić liczbę ułamkową wynikającą z dzielenia milisekund na liczbę całkowitą. Możesz także użyć parseFloat() i przechowywać dane ułamkowe.

Obejrzyj raport

Źródło: www.habr.com

Dodaj komentarz