Ni solvas praktikajn problemojn en Zabbix uzante JavaScript

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript
Tiĥon Uskov, Zabbix integriga teaminĝeniero

Zabbix estas agordebla platformo, kiu estas uzata por monitori ajnan specon de datumoj. Ekde la plej fruaj versioj de Zabbix, monitoradadministrantoj havis la kapablon ruli diversajn skriptojn per agoj por kontroloj sur celretaj nodoj. Samtempe, la lanĉo de skriptoj kaŭzis kelkajn malfacilaĵojn, inkluzive de la bezono subteni skriptojn, ilian liveron al komunikaj nodoj kaj prokuriloj, same kiel subteno por malsamaj versioj.

JavaScript por Zabbix

En April 2019, Zabbix 4.2 estis lanĉita kun JavaScript-antaŭprocesado. Multaj homoj entuziasmiĝis pri la ideo forlasi skribajn skriptojn, kiuj prenas datumojn ien, digestas ĝin kaj provizas ĝin en formato kiun Zabbix komprenas, kaj plenumas simplajn kontrolojn, kiuj ricevos datumojn, kiuj ne estas pretaj por stokado kaj prilaborado de Zabbix, kaj tiam prilaboru ĉi tiun datumfluon per Zabbix kaj JavaScript-iloj. Kune kun malaltnivela malkovro kaj dependaj eroj, kiuj aperis en Zabbix 3.4, ni ricevis sufiĉe flekseblan koncepton por ordigi kaj administri la ricevitajn datumojn.

En Zabbix 4.4, kiel logika daŭrigo de antaŭtraktado en JavaScript, aperis nova sciiga metodo - Webhook, kiu povas esti uzata por facile integri Zabbix-sciojn kun triaj aplikaĵoj.

JavaScript kaj Duktapes

Kial estis elektitaj JavaScript kaj Duktape? Oni konsideris diversajn eblojn por lingvoj kaj motoroj:

  • Lua - Lua 5.1
  • Lua - LuaJIT
  • Javascript - Duktape
  • Javaskripto - JerryScript
  • Enigita Python
  • Enigita Perl

La ĉefaj elektkriterioj estis tropezo, facileco de integriĝo de la motoro en la produkton, malalta resursokonsumo kaj totala efikeco de la motoro, kaj la sekureco de enkondukado de kodo en tiu lingvo en monitoradon. Surbaze de la kombinaĵo de indikiloj, JavaScript venkis sur la Duktape-motoro.

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript

Elektkriterioj kaj agado-testado

Karakterizaĵoj de Duktape:

— Normo ECMAScript E5/E5.1
— Zabbix-moduloj por Duktape:

  • Zabbix.log() - permesas vin skribi mesaĝojn kun malsamaj niveloj de detalo rekte en la Zabbix Server-protokolo, kio ebligas korelacii erarojn, ekzemple, en Webhook, kun la servila stato.
  • CurlHttpRequest() - permesas vin fari HTTP-petojn al la reto, sur kiu baziĝas la uzo de Webhook.
  • atob() kaj btoa() - permesas vin kodi kaj malkodi ĉenojn en Base64-formato.

NOTO. Duktape konformas al ACME-normoj. Zabbix uzas la 2015-datita version de la manuskripto. Postaj ŝanĝoj estas negravaj, do ili povas esti ignoritaj..

JavaScript Magio

La tuta magio de JavaScript kuŝas en dinamika tajpado kaj tajpado: ĉeno, nombra kaj bulea.

Ĉi tio signifas, ke ne necesas anticipe deklari, kian tipon la variablo devas redoni valoron.

En matematikaj operacioj, la valoroj redonitaj de funkciaj operatoroj estas konvertitaj al nombroj. La escepto al tiaj operacioj estas aldono, ĉar se almenaŭ unu el la terminoj estas ŝnuro, ŝnurokonverto estas aplikata al ĉiuj terminoj.

NOTO. La metodoj respondecaj por tiaj transformoj estas kutime efektivigitaj en la gepatroprototipoj de la objekto, valoroDe и al Kordo. valoroDe vokita dum nombra konvertiĝo kaj ĉiam antaŭ la metodo al Kordo. Metodo valoroDe devas redoni primitivajn valorojn, alie ĝia rezulto estas ignorita.

Metodo estas vokita sur objekto valorOF. Se ĝi ne estas trovita aŭ ne redonas primitivan valoron, la metodo estas vokita al Kordo. Se la metodo al Kordo ne trovita, serĉanta valoroDe en la prototipo de la objekto, kaj ĉio ripetiĝas ĝis la prilaborado de la valoro finiĝos kaj ĉiuj valoroj en la esprimo estas ĵetitaj al la sama tipo.. Se la objekto efektivigas metodon al Kordo, kiu resendas primitivan valoron, tiam ĝi estas uzata por ŝnuro konvertiĝo. Tamen, la rezulto de aplikado de ĉi tiu metodo ne estas nepre ŝnuro.

Ekzemple, se por por objekto 'objekto' metodo estas difinita al Kordo,

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

metodo al Kordo redonas precize ŝnuron, kaj aldonante ŝnuron kun nombro, ni ricevas gluitan ŝnuron:

`obj + 1 // '2001'` 

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

Sed se vi reverkas al Kordo, tiel ke la metodo resendas nombron, kiam la objekto estas aldonita, matematika operacio kun nombra konvertiĝo estos farita kaj la rezulto de matematika aldono estos akirita.

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

`obj + 1 // '2001'`

En ĉi tiu kazo, se ni plenumas aldonon per ŝnuro, ŝnuro konvertiĝo estas farita, kaj ni ricevas gluitan ŝnuron.

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

Ĉi tio estas la kialo de granda nombro da eraroj de komencantoj de JavaScript-uzantoj.

La metodo al Kordo vi povas skribi funkcion, kiu pliigos la nunan valoron de la objekto je 1.

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript
Efektivigo de la skripto, kondiĉe ke la variablo estas egala al 3, kaj ĝi ankaŭ estas egala al 4.

Kompare kun rolantaro (==), la metodo estas efektivigita ĉiufoje al Kordo kun funkcio de pliigo de valoro. Sekve, kun ĉiu posta komparo, la valoro pliiĝas. Ĉi tio povas esti evitita uzante ne-roltan komparon (===).

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript
Komparo sen tipa fandado

NOTO. Ne Uzu Rolantaro-Komparon Nenecese.

Por kompleksaj skriptoj, kiel Webhooks kun kompleksa logiko, kiuj postulas komparon kun tipa casting, oni rekomendas antaŭskribi kontrolojn por la valoroj, kiuj resendas variablojn kaj pritraktas nekonsekvencojn kaj erarojn.

Webhook Media

Fine de 2019 kaj komence de 2020, la integriga teamo de Zabbix aktive disvolvas Webhooks kaj pretekstajn integriĝojn, kiuj venas kun la Zabbix-distribuo.

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript
Ligilo al dokumentado

Antaŭtraktado

  • La apero de antaŭprocesado en JavaScript ebligis forlasi la plej multajn eksterajn skriptojn, kaj nuntempe en Zabbix vi povas akiri ajnan valoron kaj konverti ĝin al tute alia valoro.
  • Antaŭprocesado en Zabbix estas efektivigita per JavaScript-kodo, kiu, kiam kompilita en bajtkodon, estas konvertita en funkcion kiu prenas ununuran valoron kiel parametron. valoro kiel ŝnuro (ĉeno povas enhavi kaj ciferon kaj nombron).
  • Ĉar la eligo estas funkcio, ĉe la fino de la skripto estas postulata reveno.
  • Eblas uzi kutimajn makroojn en la kodo.
  • Rimedoj povas esti limigitaj ne nur je la mastruma sistemo, sed ankaŭ programe. La antaŭprilabora paŝo estas asignita maksimume 10 megabajtoj da RAM kaj rultempolimo de 10 sekundoj.

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript

NOTO. La tempodaŭro de 10 sekundoj estas sufiĉe multe, ĉar kolektado de kondiĉaj miloj da datumoj en 1 sekundo laŭ sufiĉe "peza" antaŭprilabora scenaro povas malrapidigi Zabbix. Tial, oni ne rekomendas uzi antaŭtraktadon por ekzekuti plenrajtajn JavaScript-skriptojn per la tiel nomataj ombraj datumelementoj (faŭlaj ​​eroj), kiuj estas rulitaj nur por plenumi antaŭtraktadon..

Vi povas kontroli vian kodon per la antaŭprocesa testo aŭ uzante la ilon 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`

Praktikaj taskoj

Objektivo 1

Anstataŭigi kalkulitan eron per antaŭprilaborado.

Kondiĉo: Akiru la temperaturon en Fahrenheit de la sensilo por stoki en Celsius.

Antaŭe, ni kreus objekton, kiu kolektas la temperaturon en gradoj Fahrenheit. Post tio, alia datumo (kalkulita) kiu konvertus Fahrenheit al Celsius per formulo.

Problemoj:

  • Necesas duplikati datumajn elementojn kaj stoki ĉiujn valorojn en la datumbazo.
  • Vi devas konsenti pri la intervaloj por la "gepatra" datumo, kiu estas kalkulita kaj uzata en la formulo, kaj por la kalkulita datuma ero. Alie, la komputita objekto povas iri en nesubtenitan staton aŭ kalkuli antaŭan valoron, kiu influos la fidindecon de la monitoraj rezultoj.

Unu solvo estis malproksimigi de flekseblaj kontrolintervaloj en favoro de fiksaj intervaloj por certigi ke la komputita objekto estas taksita post la objekto kiu ricevas la datumojn (en nia kazo, la temperaturo en gradoj Fahrenheit).

Sed se, ekzemple, ni uzas la ŝablonon por kontroli grandan nombron da aparatoj, kaj la kontrolo estas farita unufoje ĉiujn 30 sekundojn, Zabbix "hakas" dum 29 sekundoj, kaj ĉe la lasta sekundo ĝi komencas kontroli kaj kalkuli. Ĉi tio kreas atendovicon kaj influas rendimenton. Tial oni rekomendas uzi fiksajn intervalojn nur se ĝi vere necesas.

En ĉi tiu problemo, la optimuma solvo estas unulinia JavaScript-antaŭprocesado kiu konvertas gradojn Fahrenheit al celsiaj gradoj:

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

Ĝi estas rapida kaj facila, vi ne bezonas krei nenecesajn datumojn kaj konservi historion pri ili, kaj vi ankaŭ povas uzi flekseblajn intervalojn por kontroloj.

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript

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

Sed, se en hipoteza situacio necesas aldoni la ricevitan datumelementon, ekzemple, kun iu konstanto difinita en la makroo, oni devas konsideri, ke la parametro valoro disetendiĝas en ŝnuron. En korda aldono operacio, du kordoj estas simple kombinitaj en unu.

Ni solvas praktikajn problemojn en Zabbix uzante JavaScript

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

Por akiri la rezulton de matematika operacio, necesas konverti la tipojn de la akiritaj valoroj al nombra formato. Por tio vi povas uzi la funkcion parseInt(), kiu produktas entjeron, funkcion parseFloat (), kiu produktas decimalon, aŭ funkcion nombro, kiu resendas entjeron aŭ decimalon.

Tasko 2

Akiru la tempon en sekundoj ĝis la fino de la atestilo.

Kondiĉo: servo eldonas atestilan limdaton en la formato "Feb 12 12:33:56 2022 GMT".

En ECMAScript5 dato.parse() akceptas daton en formato ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ). Necesas ĵeti ŝnuron al ĝi en la formato MMM DD YYYY HH:mm:ss ZZ

problemo: La monata valoro estas esprimita kiel teksto, ne kiel nombro. Datumoj en ĉi tiu formato ne estas akceptitaj de Duktape.

Solvo ekzemplo:

  • Antaŭ ĉio, variablo estas deklarita kiu prenas valoron (la tuta skripto estas deklaro de variabloj kiuj estas listigitaj apartigitaj per komoj).

  • En la unua linio ni ricevas la daton en la parametro valoro kaj apartigu ĝin per spacoj uzante la metodon disigo. Tiel, ni ricevas tabelon, kie ĉiu elemento de la tabelo, komencante ĉe indekso 0, respondas al unu data elemento antaŭ kaj post spaco. disigo(0) - monato, disigo(1) - nombro, disigo(2) - ĉeno kun tempo, ktp. Post tio, ĉiu elemento de la dato estas alirebla per indekso en la tabelo.

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

  • Ĉiu monato (en kronologia ordo) respondas al la indekso de ĝia pozicio en la tabelo (de 0 ĝis 11). Por konverti tekstan valoron al nombra valoro, oni aldonas unu al la monata indekso (ĉar monatoj estas numeritaj ekde 1). En ĉi tiu kazo, la esprimo kun aldono de unu estas prenita inter krampoj, ĉar alie ricevos ĉeno, ne nombro. Fine ni faras tranĉaĵo () - tranĉu la tabelon de la fino por lasi nur du signojn (kio gravas dum monatoj kun ducifera nombro).

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

  • Ni formas ĉenon en ISO-formato el la akiritaj valoroj per la kutima aldono de ĉenoj en la taŭga ordo.

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

La datumoj en la rezulta formato estas la nombro da sekundoj de 1970 ĝis iu punkto en la estonteco. Estas preskaŭ neeble uzi datumojn en la ricevita formato en ellasiloj, ĉar Zabbix permesas funkcii nur per makrooj. {Dato} и {Tempo}, kiuj resendas la daton kaj horon en uzant-amika formato.

  • Ni povas tiam ricevi la aktualan daton en JavaScript en Unix Timestamp-formato kaj subtrahi ĝin de la rezulta atestildato por ricevi la nombron da milisekundoj de nun ĝis la atestilo eksvalidiĝos.

`now = Date.now();`

  • Ni dividas la ricevitan valoron per mil por akiri sekundojn en Zabbix.

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

En la ellasilo, vi povas specifi la esprimon 'lasta' sekvata de aro de ciferoj, kiuj respondas al la nombro da sekundoj en la periodo al kiu vi volas respondi, ekzemple, en semajnoj. Tiel, la ellasilo sciigos, ke la atestilo eksvalidiĝas post semajno.

NOTO. Atentu la uzon parseInt() en funkcio revenokonverti la frakcian nombron rezultantan el divido de milisekundoj al entjero. Vi ankaŭ povas uzi parseFloat () kaj stoki frakciajn datumojn.

Rigardu raporton

fonto: www.habr.com

Aldoni komenton