Resolem problemes pràctics a Zabbix mitjançant JavaScript

Resolem problemes pràctics a Zabbix mitjançant JavaScript
Tikhon Uskov, enginyer de l'equip d'integració Zabbix

Zabbix és una plataforma personalitzable que s'utilitza per controlar qualsevol tipus de dades. Des de les primeres versions de Zabbix, els administradors de supervisió han tingut la possibilitat d'executar diversos scripts mitjançant Accions per a comprovacions als nodes de la xarxa objectiu. Al mateix temps, el llançament dels scripts va comportar una sèrie de dificultats, com ara la necessitat de donar suport als scripts, el seu lliurament a nodes de comunicació i servidors intermediaris, així com el suport per a diferents versions.

JavaScript per a Zabbix

L'abril de 2019, es va introduir Zabbix 4.2 amb preprocessament de JavaScript. Moltes persones es van entusiasmar amb la idea d'abandonar els scripts d'escriptura que porten dades en algun lloc, les digereixen i les proporcionen en un format que Zabbix entén, i realitzen comprovacions senzilles que rebran dades que no estan preparades per a l'emmagatzematge i el processament per part de Zabbix, i després processeu aquest flux de dades amb les eines Zabbix i JavaScript. Juntament amb el descobriment de baix nivell i els elements dependents que van aparèixer a Zabbix 3.4, vam obtenir un concepte bastant flexible per ordenar i gestionar les dades rebudes.

A Zabbix 4.4, com a continuació lògica del preprocessament en JavaScript, ha aparegut un nou mètode de notificació: Webhook, que es pot utilitzar per integrar fàcilment les notificacions de Zabbix amb aplicacions de tercers.

JavaScript i Duktapes

Per què es van triar JavaScript i Duktape? Es van considerar diverses opcions d'idiomes i motors:

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

Els principals criteris de selecció van ser la prevalença, la facilitat d'integració del motor al producte, el baix consum de recursos i el rendiment global del motor, i la seguretat d'introduir codi en aquest llenguatge en la supervisió. A partir de la combinació d'indicadors, JavaScript va guanyar al motor Duktape.

Resolem problemes pràctics a Zabbix mitjançant JavaScript

Criteris de selecció i proves de rendiment

Característiques de Duktape:

- Estàndard ECMAScript E5/E5.1
— Mòduls Zabbix per a Duktape:

  • Zabbix.log() - us permet escriure missatges amb diferents nivells de detall directament al registre del servidor Zabbix, cosa que permet correlacionar errors, per exemple, en un Webhook, amb l'estat del servidor.
  • CurlHttpRequest() - us permet fer peticions HTTP a la xarxa, en què es basa l'ús de Webhook.
  • atob() i btoa() - us permet codificar i descodificar cadenes en format Base64.

NOTA. Duktape compleix amb els estàndards ACME. Zabbix utilitza la versió 2015 del guió. Els canvis posteriors són menors, de manera que es poden ignorar..

Màgia de JavaScript

Tota la màgia de JavaScript rau en l'escriptura dinàmica i el càsting de tipus: cadena, numèric i booleà.

Això vol dir que no cal declarar per endavant quin tipus ha de retornar un valor la variable.

En les operacions matemàtiques, els valors retornats pels operadors de funció es converteixen en nombres. L'excepció d'aquestes operacions és l'addició, perquè si almenys un dels termes és una cadena, la conversió de cadena s'aplica a tots els termes.

NOTA. Els mètodes responsables d'aquestes transformacions solen implementar-se en els prototips pare de l'objecte, el valor de и toString. el valor de cridat durant la conversió numèrica i sempre abans del mètode toString. Mètode el valor de ha de retornar valors primitius, en cas contrari, el seu resultat s'ignora.

Es crida un mètode a un objecte el valor de. Si no es troba o no retorna un valor primitiu, es crida el mètode toString. Si el mètode toString no trobat, buscant el valor de al prototip de l'objecte, i tot es repeteix fins que s'ha completat el processament del valor i tots els valors de l'expressió s'emeten al mateix tipus. Si l'objecte implementa un mètode toString, que retorna un valor primitiu, llavors és el que s'utilitza per a la conversió de cadena. Tanmateix, el resultat d'aplicar aquest mètode no és necessàriament una cadena.

Per exemple, si per a l'objecte 'objEs defineix el mètode toString,

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

метод toString retorna exactament una cadena, i quan afegim una cadena amb un número, obtenim una cadena enganxada:

`obj + 1 // '2001'` 

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

Però si tornes a escriure toString, de manera que el mètode retorni un número, quan s'afegeix l'objecte, es realitzarà una operació matemàtica amb una conversió numèrica i s'obtindrà el resultat de la suma matemàtica.

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

`obj + 1 // '2001'`

En aquest cas, si fem una suma amb una cadena, es realitza una conversió de cadena i obtenim una cadena enganxada.

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

Aquesta és la raó d'un gran nombre d'errors per part dels usuaris novells de JavaScript.

El mètode toString podeu escriure una funció que augmentarà el valor actual de l'objecte en 1.

Resolem problemes pràctics a Zabbix mitjançant JavaScript
Execució de l'script, sempre que la variable sigui igual a 3, i també sigui igual a 4.

En comparació amb un repartiment (==), el mètode s'executa cada vegada toString amb funció d'augment de valor. En conseqüència, amb cada comparació posterior, el valor augmenta. Això es pot evitar utilitzant una comparació sense emissió (===).

Resolem problemes pràctics a Zabbix mitjançant JavaScript
Comparació sense tipus de fosa

NOTA. No utilitzeu la comparació de repartiment innecessàriament.

Per a scripts complexos, com ara Webhooks amb lògica complexa, que requereixen una comparació amb el càsting de tipus, es recomana escriure prèviament comprovacions dels valors que retornen variables i gestionen incoherències i errors.

Webhook Media

A finals de 2019 i principis de 2020, l'equip d'integració de Zabbix ha estat desenvolupant activament Webhooks i integracions prèvies que inclouen la distribució Zabbix.

Resolem problemes pràctics a Zabbix mitjançant JavaScript
Enllaç a documentació

Preprocessament

  • L'arribada del preprocessament a JavaScript va fer possible abandonar la majoria dels scripts externs, i actualment a Zabbix podeu obtenir qualsevol valor i convertir-lo en un valor completament diferent.
  • El preprocessament a Zabbix s'implementa mitjançant codi JavaScript, que, quan es compila en bytecode, es converteix en una funció que pren un sol valor com a paràmetre. valor com una cadena (una cadena pot contenir tant un dígit com un nombre).
  • Com que la sortida és una funció, cal al final de l'script return.
  • És possible utilitzar macros personalitzades al codi.
  • Els recursos es poden limitar no només a nivell de sistema operatiu, sinó també programàticament. Al pas de preprocessament se li assigna un màxim de 10 megabytes de RAM i un límit de temps d'execució de 10 segons.

Resolem problemes pràctics a Zabbix mitjançant JavaScript

NOTA. El valor de temps d'espera de 10 segons és molt, perquè la recollida condicional de milers d'elements de dades en 1 segon segons un escenari de preprocessament bastant "pesat" pot frenar Zabbix. Per tant, no es recomana utilitzar el preprocessament per executar scripts de JavaScript complets mitjançant els anomenats elements de dades ombra (elements ficticis), que s'executen només per realitzar el preprocessament..

Podeu comprovar el vostre codi mitjançant la prova de preprocessament o mitjançant la utilitat 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`

Tasques pràctiques

Tasca 1

Substituïu l'element calculat per preprocessament.

Condició: Obteniu la temperatura en Fahrenheit del sensor per emmagatzemar-la en Celsius.

Anteriorment, crearíem un element que reculli la temperatura en graus Fahrenheit. Després d'això, un altre element de dades (calculat) que convertiria Fahrenheit a Celsius mitjançant una fórmula.

Problemes:

  • Cal duplicar els elements de dades i emmagatzemar tots els valors a la base de dades.
  • Heu d'acordar els intervals per a l'element de dades "parent" que es calcula i s'utilitza a la fórmula, i per a l'element de dades calculat. En cas contrari, l'element calculat pot passar a un estat no compatible o calcular un valor anterior, cosa que afectarà la fiabilitat dels resultats del seguiment.

Una solució va ser allunyar-se dels intervals de control flexibles a favor d'intervals fixos per assegurar-se que l'element calculat s'avalués després de l'element que rep les dades (en el nostre cas, la temperatura en graus Fahrenheit).

Però si, per exemple, utilitzem la plantilla per comprovar un gran nombre de dispositius, i la comprovació es realitza una vegada cada 30 segons, Zabbix "hackeja" durant 29 segons, i en l'últim segon comença a comprovar i calcular. Això crea una cua i afecta el rendiment. Per tant, es recomana utilitzar intervals fixos només si és realment necessari.

En aquest problema, la solució òptima és un preprocessament JavaScript d'una línia que converteix graus Fahrenheit en graus Celsius:

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

És ràpid i fàcil, no cal que creeu elements de dades innecessaris i que en conserveu un historial, i també podeu utilitzar intervals flexibles per a les comprovacions.

Resolem problemes pràctics a Zabbix mitjançant JavaScript

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

Però, si en una situació hipotètica cal afegir l'element de dades rebut, per exemple, amb qualsevol constant definida a la macro, cal tenir en compte que el paràmetre valor s'expandeix en una cadena. En una operació d'addició de cadenes, dues cadenes simplement es combinen en una.

Resolem problemes pràctics a Zabbix mitjançant JavaScript

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

Per obtenir el resultat d'una operació matemàtica, cal convertir els tipus de valors obtinguts a un format numèric. Per a això podeu utilitzar la funció parseInt(), que produeix un nombre enter, una funció parseFloat(), que produeix un decimal o una funció nombre, que retorna un nombre enter o decimal.

Tasca 2

Obteniu el temps en segons fins al final del certificat.

Condició: un servei emet una data de caducitat del certificat en el format "Feb 12 12:33:56 2022 GMT".

A ECMAScript5 data.parse() accepta una data en format ISO 8601 (AAAA-MM-DDTHH:mm:ss.sssZ). Cal llançar-hi una cadena en el format MMM DD AAAA HH:mm:ss ZZ

problema: el valor del mes s'expressa com a text, no com a nombre. Les dades en aquest format no són acceptades per Duktape.

Exemple de solució:

  • En primer lloc, es declara una variable que pren un valor (tot l'script és una declaració de variables que s'enumeren separades per comes).

  • A la primera línia obtenim la data al paràmetre valor i separar-lo amb espais mitjançant el mètode dividit. Així, obtenim una matriu, on cada element de la matriu, començant per l'índex 0, correspon a un element de data abans i després d'un espai. dividir (0) - mes, dividir (1) - nombre, dividir (2) - una cadena amb el temps, etc. Després d'això, es pot accedir a cada element de la data per índex a la matriu.

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

  • Cada mes (en ordre cronològic) correspon a l'índex de la seva posició a la matriu (de 0 a 11). Per convertir un valor de text en un valor numèric, s'afegeix un a l'índex del mes (perquè els mesos es numeran a partir de l'1). En aquest cas, l'expressió amb l'addició d'un es pren entre parèntesis, perquè sinó s'obtindrà una cadena, no un número. Al final ho fem llesca () - retalla la matriu des del final per deixar només dos caràcters (cosa important durant mesos amb un número de dos dígits).

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

  • Formem una cadena en format ISO a partir dels valors obtinguts mitjançant l'addició habitual de cadenes en l'ordre adequat.

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

Les dades en el format resultant són el nombre de segons des de 1970 fins a algun moment en el futur. És gairebé impossible utilitzar dades en el format rebut en activadors, perquè Zabbix us permet operar només amb macros {Data} и {Temps}, que retornen la data i l'hora en un format fàcil d'utilitzar.

  • Aleshores podem obtenir la data actual en JavaScript en format Unix Timestamp i restar-la de la data de caducitat del certificat resultant per obtenir el nombre de mil·lisegons des d'ara fins que caduca el certificat.

`now = Date.now();`

  • Dividim el valor rebut per mil per obtenir segons a Zabbix.

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

Al disparador, podeu especificar l'expressió 'darrer' seguit d'un conjunt de dígits que correspon al nombre de segons del període al qual voleu respondre, per exemple, en setmanes. Així, el disparador notificarà que el certificat caduca en una setmana.

NOTA. Presteu atenció a l’ús parseInt() en funció returnper convertir el nombre fraccionari resultant de la divisió de mil·lisegons a un nombre enter. També pots utilitzar parseFloat() i emmagatzemar dades fraccionades.

Mira l'informe

Font: www.habr.com

Afegeix comentari