123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163 |
- // Main JavaScript file for the Netdata GUI.
- // Codacy declarations
- /* global NETDATA */
- // netdata snapshot data
- var netdataSnapshotData = null;
- // enable alarms checking and notifications
- var netdataShowAlarms = true;
- // enable registry updates
- var netdataRegistry = true;
- // forward definition only - not used here
- var netdataServer = undefined;
- var netdataServerStatic = undefined;
- var netdataCheckXSS = undefined;
- // control the welcome modal and analytics
- var this_is_demo = null;
- function escapeUserInputHTML(s) {
- return s.toString()
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"')
- .replace(/#/g, '#')
- .replace(/'/g, ''')
- .replace(/\(/g, '(')
- .replace(/\)/g, ')')
- .replace(/\//g, '/');
- }
- function verifyURL(s) {
- if (typeof (s) === 'string' && (s.startsWith('http://') || s.startsWith('https://'))) {
- return s
- .replace(/'/g, '%22')
- .replace(/"/g, '%27')
- .replace(/\)/g, '%28')
- .replace(/\(/g, '%29');
- }
- console.log('invalid URL detected:');
- console.log(s);
- return 'javascript:alert("invalid url");';
- }
- // --------------------------------------------------------------------
- // urlOptions
- var urlOptions = {
- hash: '#',
- theme: null,
- help: null,
- mode: 'live', // 'live', 'print'
- update_always: false,
- pan_and_zoom: false,
- server: null,
- after: 0,
- before: 0,
- highlight: false,
- highlight_after: 0,
- highlight_before: 0,
- nowelcome: false,
- show_alarms: false,
- chart: null,
- family: null,
- alarm: null,
- alarm_unique_id: 0,
- alarm_id: 0,
- alarm_event_id: 0,
- alarm_when: 0,
- hasProperty: function (property) {
- // console.log('checking property ' + property + ' of type ' + typeof(this[property]));
- return typeof this[property] !== 'undefined';
- },
- genHash: function (forReload) {
- var hash = urlOptions.hash;
- if (urlOptions.pan_and_zoom === true) {
- hash += ';after=' + urlOptions.after.toString() +
- ';before=' + urlOptions.before.toString();
- }
- if (urlOptions.highlight === true) {
- hash += ';highlight_after=' + urlOptions.highlight_after.toString() +
- ';highlight_before=' + urlOptions.highlight_before.toString();
- }
- if (urlOptions.theme !== null) {
- hash += ';theme=' + urlOptions.theme.toString();
- }
- if (urlOptions.help !== null) {
- hash += ';help=' + urlOptions.help.toString();
- }
- if (urlOptions.update_always === true) {
- hash += ';update_always=true';
- }
- if (forReload === true && urlOptions.server !== null) {
- hash += ';server=' + urlOptions.server.toString();
- }
- if (urlOptions.mode !== 'live') {
- hash += ';mode=' + urlOptions.mode;
- }
- return hash;
- },
- parseHash: function () {
- var variables = document.location.hash.split(';');
- var len = variables.length;
- while (len--) {
- if (len !== 0) {
- var p = variables[len].split('=');
- if (urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined') {
- urlOptions[p[0]] = decodeURIComponent(p[1]);
- }
- } else {
- if (variables[len].length > 0) {
- urlOptions.hash = variables[len];
- }
- }
- }
- var booleans = ['nowelcome', 'show_alarms', 'update_always'];
- len = booleans.length;
- while (len--) {
- if (urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1) {
- urlOptions[booleans[len]] = true;
- } else {
- urlOptions[booleans[len]] = false;
- }
- }
- var numeric = ['after', 'before', 'highlight_after', 'highlight_before', 'alarm_when'];
- len = numeric.length;
- while (len--) {
- if (typeof urlOptions[numeric[len]] === 'string') {
- try {
- urlOptions[numeric[len]] = parseInt(urlOptions[numeric[len]]);
- }
- catch (e) {
- console.log('failed to parse URL hash parameter ' + numeric[len]);
- urlOptions[numeric[len]] = 0;
- }
- }
- }
- if (urlOptions.alarm_when) {
- // if alarm_when exists, create after/before params
- // -/+ 2 minutes from the alarm, and reload the page
- const alarmTime = new Date(urlOptions.alarm_when * 1000).valueOf();
- const timeMarginMs = 120000; // 2 mins
- const after = alarmTime - timeMarginMs;
- const before = alarmTime + timeMarginMs;
- const newHash = document.location.hash.replace(
- /;alarm_when=[0-9]*/i,
- ";after=" + after + ";before=" + before,
- );
- history.replaceState(null, '', newHash);
- location.reload();
- }
- if (urlOptions.server !== null && urlOptions.server !== '') {
- netdataServerStatic = document.location.origin.toString() + document.location.pathname.toString();
- netdataServer = urlOptions.server;
- netdataCheckXSS = true;
- } else {
- urlOptions.server = null;
- }
- if (urlOptions.before > 0 && urlOptions.after > 0) {
- urlOptions.pan_and_zoom = true;
- urlOptions.nowelcome = true;
- } else {
- urlOptions.pan_and_zoom = false;
- }
- if (urlOptions.highlight_before > 0 && urlOptions.highlight_after > 0) {
- urlOptions.highlight = true;
- } else {
- urlOptions.highlight = false;
- }
- switch (urlOptions.mode) {
- case 'print':
- urlOptions.theme = 'white';
- urlOptions.welcome = false;
- urlOptions.help = false;
- urlOptions.show_alarms = false;
- if (urlOptions.pan_and_zoom === false) {
- urlOptions.pan_and_zoom = true;
- urlOptions.before = Date.now();
- urlOptions.after = urlOptions.before - 600000;
- }
- netdataShowAlarms = false;
- netdataRegistry = false;
- this_is_demo = false;
- break;
- case 'live':
- default:
- urlOptions.mode = 'live';
- break;
- }
- // console.log(urlOptions);
- },
- hashUpdate: function () {
- history.replaceState(null, '', urlOptions.genHash(true));
- },
- netdataPanAndZoomCallback: function (status, after, before) {
- //console.log(1);
- //console.log(new Error().stack);
- if (netdataSnapshotData === null) {
- urlOptions.pan_and_zoom = status;
- urlOptions.after = after;
- urlOptions.before = before;
- urlOptions.hashUpdate();
- }
- },
- netdataHighlightCallback: function (status, after, before) {
- //console.log(2);
- //console.log(new Error().stack);
- if (status === true && (after === null || before === null || after <= 0 || before <= 0 || after >= before)) {
- status = false;
- after = 0;
- before = 0;
- }
- if (netdataSnapshotData === null) {
- urlOptions.highlight = status;
- } else {
- urlOptions.highlight = false;
- }
- urlOptions.highlight_after = Math.round(after);
- urlOptions.highlight_before = Math.round(before);
- urlOptions.hashUpdate();
- var show_eye = NETDATA.globalChartUnderlay.hasViewport();
- if (status === true && after > 0 && before > 0 && after < before) {
- var d1 = NETDATA.dateTime.localeDateString(after);
- var d2 = NETDATA.dateTime.localeDateString(before);
- if (d1 === d2) {
- d2 = '';
- }
- document.getElementById('navbar-highlight-content').innerHTML =
- ((show_eye === true) ? '<span class="navbar-highlight-bar highlight-tooltip" onclick="urlOptions.showHighlight();" title="restore the highlighted view" data-toggle="tooltip" data-placement="bottom">' : '<span>').toString()
- + 'highlighted time-frame'
- + ' <b>' + d1 + ' <code>' + NETDATA.dateTime.localeTimeString(after) + '</code></b> to '
- + ' <b>' + d2 + ' <code>' + NETDATA.dateTime.localeTimeString(before) + '</code></b>, '
- + 'duration <b>' + NETDATA.seconds4human(Math.round((before - after) / 1000)) + '</b>'
- + '</span>'
- + '<span class="navbar-highlight-button-right highlight-tooltip" onclick="urlOptions.clearHighlight();" title="clear the highlighted time-frame" data-toggle="tooltip" data-placement="bottom"><i class="fas fa-times"></i></span>';
- $('.navbar-highlight').show();
- $('.highlight-tooltip').tooltip({
- html: true,
- delay: { show: 500, hide: 0 },
- container: 'body'
- });
- } else {
- $('.navbar-highlight').hide();
- }
- },
- clearHighlight: function () {
- NETDATA.globalChartUnderlay.clear();
- if (NETDATA.globalPanAndZoom.isActive() === true) {
- NETDATA.globalPanAndZoom.clearMaster();
- }
- },
- showHighlight: function () {
- NETDATA.globalChartUnderlay.focus();
- }
- };
- urlOptions.parseHash();
- // --------------------------------------------------------------------
- // check options that should be processed before loading netdata.js
- var localStorageTested = -1;
- function localStorageTest() {
- if (localStorageTested !== -1) {
- return localStorageTested;
- }
- if (typeof Storage !== "undefined" && typeof localStorage === 'object') {
- var test = 'test';
- try {
- localStorage.setItem(test, test);
- localStorage.removeItem(test);
- localStorageTested = true;
- }
- catch (e) {
- console.log(e);
- localStorageTested = false;
- }
- } else {
- localStorageTested = false;
- }
- return localStorageTested;
- }
- function loadLocalStorage(name) {
- var ret = null;
- try {
- if (localStorageTest() === true) {
- ret = localStorage.getItem(name);
- } else {
- console.log('localStorage is not available');
- }
- }
- catch (error) {
- console.log(error);
- return null;
- }
- if (typeof ret === 'undefined' || ret === null) {
- return null;
- }
- // console.log('loaded: ' + name.toString() + ' = ' + ret.toString());
- return ret;
- }
- function saveLocalStorage(name, value) {
- // console.log('saving: ' + name.toString() + ' = ' + value.toString());
- try {
- if (localStorageTest() === true) {
- localStorage.setItem(name, value.toString());
- return true;
- }
- }
- catch (error) {
- console.log(error);
- }
- return false;
- }
- function getTheme(def) {
- if (urlOptions.mode === 'print') {
- return 'white';
- }
- var ret = loadLocalStorage('netdataTheme');
- if (typeof ret === 'undefined' || ret === null || ret === 'undefined') {
- return def;
- } else {
- return ret;
- }
- }
- function setTheme(theme) {
- if (urlOptions.mode === 'print') {
- return false;
- }
- if (theme === netdataTheme) {
- return false;
- }
- return saveLocalStorage('netdataTheme', theme);
- }
- var netdataTheme = getTheme('slate');
- var netdataShowHelp = true;
- if (urlOptions.theme !== null) {
- setTheme(urlOptions.theme);
- netdataTheme = urlOptions.theme;
- } else {
- urlOptions.theme = netdataTheme;
- }
- if (urlOptions.help !== null) {
- saveLocalStorage('options.show_help', urlOptions.help);
- netdataShowHelp = urlOptions.help;
- } else {
- urlOptions.help = loadLocalStorage('options.show_help');
- }
- // --------------------------------------------------------------------
- // natural sorting
- // http://www.davekoelle.com/files/alphanum.js - LGPL
- function naturalSortChunkify(t) {
- var tz = [];
- var x = 0, y = -1, n = 0, i, j;
- while (i = (j = t.charAt(x++)).charCodeAt(0)) {
- var m = (i >= 48 && i <= 57);
- if (m !== n) {
- tz[++y] = "";
- n = m;
- }
- tz[y] += j;
- }
- return tz;
- }
- function naturalSortCompare(a, b) {
- var aa = naturalSortChunkify(a.toLowerCase());
- var bb = naturalSortChunkify(b.toLowerCase());
- for (var x = 0; aa[x] && bb[x]; x++) {
- if (aa[x] !== bb[x]) {
- var c = Number(aa[x]), d = Number(bb[x]);
- if (c.toString() === aa[x] && d.toString() === bb[x]) {
- return c - d;
- } else {
- return (aa[x] > bb[x]) ? 1 : -1;
- }
- }
- }
- return aa.length - bb.length;
- }
- // --------------------------------------------------------------------
- // saving files to client
- function saveTextToClient(data, filename) {
- var blob = new Blob([data], {
- type: 'application/octet-stream'
- });
- var url = URL.createObjectURL(blob);
- var link = document.createElement('a');
- link.setAttribute('href', url);
- link.setAttribute('download', filename);
- var el = document.getElementById('hiddenDownloadLinks');
- el.innerHTML = '';
- el.appendChild(link);
- setTimeout(function () {
- el.removeChild(link);
- URL.revokeObjectURL(url);
- }, 60);
- link.click();
- }
- function saveObjectToClient(data, filename) {
- saveTextToClient(JSON.stringify(data), filename);
- }
- // -----------------------------------------------------------------------------
- // registry call back to render my-netdata menu
- function toggleExpandIcon(svgEl) {
- if (svgEl.getAttribute('data-icon') === 'caret-down') {
- svgEl.setAttribute('data-icon', 'caret-up');
- } else {
- svgEl.setAttribute('data-icon', 'caret-down');
- }
- }
- function toggleAgentItem(e, guid) {
- e.stopPropagation();
- e.preventDefault();
- toggleExpandIcon(e.currentTarget.children[0]);
- const el = document.querySelector(`.agent-alternate-urls.agent-${guid}`);
- if (el) {
- el.classList.toggle('collapsed');
- }
- }
- // When you stream metrics from netdata to netdata, the receiving netdata now
- // has multiple host databases. It's own, and multiple mirrored. Mirrored databases
- // can be accessed with <http://localhost:19999/host/NAME/>
- const OLD_DASHBOARD_SUFFIX = "old"
- let isOldSuffix = true
- try {
- const currentScriptMainJs = document.currentScript;
- const mainJsSrc = currentScriptMainJs.getAttribute("src")
- isOldSuffix = mainJsSrc.startsWith("../main.js")
- } catch {
- console.warn("current script not detecting, assuming the dashboard is running with /old suffix")
- }
- function transformWithOldSuffix(url) {
- return isOldSuffix ? `../${url}` : url
- }
- function renderStreamedHosts(options) {
- let html = `<div class="info-item">Databases streamed to this agent</div>`;
- var base = document.location.origin.toString() +
- document.location.pathname.toString()
- .replace(isOldSuffix ? `/${OLD_DASHBOARD_SUFFIX}` : "", "");
- if (base.endsWith("/host/" + options.hostname + "/")) {
- base = base.substring(0, base.length - ("/host/" + options.hostname + "/").toString().length);
- }
- if (base.endsWith("/")) {
- base = base.substring(0, base.length - 1);
- }
- var master = options.hosts[0].hostname;
- // We sort a clone of options.hosts, to keep the master as the first element
- // for future calls.
- var sorted = options.hosts.slice(0).sort(function (a, b) {
- if (a.hostname === master) {
- return -1;
- }
- return naturalSortCompare(a.hostname, b.hostname);
- });
- let displayedDatabases = false;
- for (var s of sorted) {
- let url, icon;
- const hostname = s.hostname;
- if (myNetdataMenuFilterValue !== "") {
- if (!hostname.includes(myNetdataMenuFilterValue)) {
- continue;
- }
- }
- displayedDatabases = true;
- if (hostname === master) {
- url = isOldSuffix ? `${base}/${OLD_DASHBOARD_SUFFIX}/` : `${base}/`;
- icon = 'home';
- } else {
- url = isOldSuffix ? `${base}/host/${hostname}/${OLD_DASHBOARD_SUFFIX}/` : `${base}/host/${hostname}/`;
- icon = 'window-restore';
- }
- html += (
- `<div class="agent-item">
- <a class="registry_link" href="${url}#" onClick="return gotoHostedModalHandler('${url}');">
- <i class="fas fa-${icon}" style="color: #999;"></i>
- </a>
- <span class="__title" onClick="return gotoHostedModalHandler('${url}');">
- <a class="registry_link" href="${url}#">${hostname}</a>
- </span>
- <div></div>
- </div>`
- )
- }
- if (!displayedDatabases) {
- html += (
- `<div class="info-item">
- <i class="fas fa-filter"></i>
- <span style="margin-left: 8px">no databases match the filter criteria.<span>
- </div>`
- )
- }
- return html;
- }
- function renderMachines(machinesArray) {
- let html = `<div class="info-item">My nodes</div>`;
- if (machinesArray === null) {
- let ret = loadLocalStorage("registryCallback");
- if (ret) {
- machinesArray = JSON.parse(ret);
- console.log("failed to contact the registry - loaded registry data from browser local storage");
- }
- }
- let found = false;
- let displayedAgents = false;
- const maskedURL = NETDATA.registry.MASKED_DATA;
- if (machinesArray) {
- saveLocalStorage("registryCallback", JSON.stringify(machinesArray));
- var machines = machinesArray.sort(function (a, b) {
- return naturalSortCompare(a.name, b.name);
- });
- for (var machine of machines) {
- found = true;
- if (myNetdataMenuFilterValue !== "") {
- if (!machine.name.includes(myNetdataMenuFilterValue)) {
- continue;
- }
- }
- displayedAgents = true;
- const alternateUrlItems = (
- `<div class="agent-alternate-urls agent-${machine.guid} collapsed">
- ${machine.alternate_urls.reduce((str, url) => {
- if (url === maskedURL) {
- return str
- }
- return str + (
- `<div class="agent-item agent-item--alternate">
- <div></div>
- <a href="${url}" title="${url}">${truncateString(url, 64)}</a>
- <a href="#" onclick="deleteRegistryModalHandler('${machine.guid}', '${machine.name}', '${url}'); return false;">
- <i class="fas fa-trash" style="color: #777;"></i>
- </a>
- </div>`
- )
- },
- ''
- )}
- </div>`
- )
- html += (
- `<div class="agent-item agent-${machine.guid}">
- <i class="fas fa-chart-bar" color: #fff"></i>
- <span class="__title" onClick="return gotoServerModalHandler('${machine.guid}');">
- <a class="registry_link" href="${machine.url}#">${machine.name}</a>
- </span>
- <a href="#" onClick="toggleAgentItem(event, '${machine.guid}');">
- <i class="fas fa-caret-down" style="color: #999"></i>
- </a>
- </div>
- ${alternateUrlItems}`
- )
- }
- if (found && (!displayedAgents)) {
- html += (
- `<div class="info-item">
- <i class="fas fa-filter"></i>
- <span style="margin-left: 8px">zero nodes are matching the filter value.<span>
- </div>`
- )
- }
- }
- if (!found) {
- if (machines) {
- html += (
- `<div class="info-item">
- <a href="https://github.com/netdata/netdata/tree/master/registry#registry" target="_blank">Your nodes list is empty</a>
- </div>`
- )
- } else {
- html += (
- `<div class="info-item">
- <a href="https://github.com/netdata/netdata/tree/master/registry#registry" target="_blank">Failed to contact the registry</a>
- </div>`
- )
- }
- html += `<hr />`;
- html += `<div class="info-item">Demo netdata nodes</div>`;
- const demoServers = [
- { url: "//london.netdata.rocks/default.html", title: "UK - London (DigitalOcean.com)" },
- { url: "//newyork.netdata.rocks/default.html", title: "US - New York (DigitalOcean.com)" },
- { url: "//sanfrancisco.netdata.rocks/default.html", title: "US - San Francisco (DigitalOcean.com)" },
- { url: "//atlanta.netdata.rocks/default.html", title: "US - Atlanta (CDN77.com)" },
- { url: "//frankfurt.netdata.rocks/default.html", title: "Germany - Frankfurt (DigitalOcean.com)" },
- { url: "//toronto.netdata.rocks/default.html", title: "Canada - Toronto (DigitalOcean.com)" },
- { url: "//singapore.netdata.rocks/default.html", title: "Japan - Singapore (DigitalOcean.com)" },
- { url: "//bangalore.netdata.rocks/default.html", title: "India - Bangalore (DigitalOcean.com)" },
- ]
- for (var server of demoServers) {
- html += (
- `<div class="agent-item">
- <i class="fas fa-chart-bar" style="color: #fff"></i>
- <a href="${server.url}">${server.title}</a>
- <div></div>
- </div>
- `
- );
- }
- }
- return html;
- }
- function setMyNetdataMenu(html) {
- const el = document.getElementById('my-netdata-dropdown-content')
- el.innerHTML = html;
- }
- function clearMyNetdataMenu() {
- setMyNetdataMenu(`<div class="agent-item" style="white-space: nowrap">
- <i class="fas fa-hourglass-half"></i>
- Loading, please wait...
- <div></div>
- </div>`);
- }
- function errorMyNetdataMenu() {
- setMyNetdataMenu(`<div class="agent-item" style="padding: 0 8px">
- <i class="fas fa-exclamation-triangle" style="color: red"></i>
- Cannot load known Netdata agents from Netdata Cloud! Please make sure you have the latest version of Netdata.
- </div>`);
- }
- function restrictMyNetdataMenu() {
- setMyNetdataMenu(`<div class="info-item" style="white-space: nowrap">
- <span>Please <a href="#" onclick="signInDidClick(event); return false">sign in to netdata.cloud</a> to view your nodes!</span>
- <div></div>
- </div>`);
- }
- function openAuthenticatedUrl(url) {
- if (isSignedIn()) {
- window.open(url);
- } else {
- window.open(`${NETDATA.registry.cloudBaseURL}/account/sign-in-agent?id=${NETDATA.registry.machine_guid}&name=${encodeURIComponent(NETDATA.registry.hostname)}&origin=${encodeURIComponent(window.location.origin + "/")}&redirect_uri=${encodeURIComponent(window.location.origin + "/" + url)}`);
- }
- }
- function renderMyNetdataMenu(machinesArray) {
- const el = document.getElementById('my-netdata-dropdown-content');
- el.classList.add(`theme-${netdataTheme}`);
- if (machinesArray == registryAgents) {
- console.log("Rendering my-netdata menu from registry");
- } else {
- console.log("Rendering my-netdata menu from netdata.cloud", machinesArray);
- }
- let html = '';
- if (!isSignedIn()) {
- if (!NETDATA.registry.isRegistryEnabled()) {
- html += (
- `<div class="info-item" style="white-space: nowrap">
- <span>Please <a href="#" onclick="signInDidClick(event); return false">sign in to netdata.cloud</a> to view your nodes!</span>
- <div></div>
- </div>
- <hr />`
- );
- }
- }
- if (isSignedIn()) {
- html += (
- `<div class="filter-control">
- <input
- id="my-netdata-menu-filter-input"
- type="text"
- placeholder="filter nodes..."
- autofocus
- autocomplete="off"
- value="${myNetdataMenuFilterValue}"
- onkeydown="myNetdataFilterDidChange(event)"
- />
- <span class="filter-control__clear" onclick="myNetdataFilterClearDidClick(event)"><i class="fas fa-times"></i><span>
- </div>
- <hr />`
- );
- }
- // options.hosts = [
- // {
- // hostname: "streamed1",
- // },
- // {
- // hostname: "streamed2",
- // },
- // ]
- if (options.hosts.length > 1) {
- html += `<div id="my-netdata-menu-streamed">${renderStreamedHosts(options)}</div><hr />`;
- }
- if (isSignedIn() || NETDATA.registry.isRegistryEnabled()) {
- html += `<div id="my-netdata-menu-machines">${renderMachines(machinesArray)}</div><hr />`;
- }
- if (!isSignedIn()) {
- html += (
- `<div class="agent-item">
- <i class="fas fa-cog""></i>
- <a href="#" onclick="switchRegistryModalHandler(); return false;">Switch Identity</a>
- <div></div>
- </div>
- <div class="agent-item">
- <i class="fas fa-question-circle""></i>
- <a href="https://github.com/netdata/netdata/tree/master/registry#registry" target="_blank">What is this?</a>
- <div></div>
- </div>`
- )
- } else {
- html += (
- `<div class="agent-item">
- <i class="fas fa-tv"></i>
- <a onclick="openAuthenticatedUrl('console.html');" target="_blank">Nodes<sup class="beta"> beta</sup></a>
- <div></div>
- </div>
- <div class="agent-item">
- <i class="fas fa-sync"></i>
- <a href="#" onclick="showSyncModal(); return false">Synchronize with netdata.cloud</a>
- <div></div>
- </div>
- <div class="agent-item">
- <i class="fas fa-question-circle""></i>
- <a href="https://netdata.cloud/about" target="_blank">What is this?</a>
- <div></div>
- </div>`
- )
- }
- el.innerHTML = html;
- gotoServerInit();
- }
- function isdemo() {
- if (this_is_demo !== null) {
- return this_is_demo;
- }
- this_is_demo = false;
- try {
- if (typeof document.location.hostname === 'string') {
- if (document.location.hostname.endsWith('.my-netdata.io') ||
- document.location.hostname.endsWith('.mynetdata.io') ||
- document.location.hostname.endsWith('.netdata.rocks') ||
- document.location.hostname.endsWith('.netdata.ai') ||
- document.location.hostname.endsWith('.netdata.live') ||
- document.location.hostname.endsWith('.firehol.org') ||
- document.location.hostname.endsWith('.netdata.online') ||
- document.location.hostname.endsWith('.netdata.cloud')) {
- this_is_demo = true;
- }
- }
- }
- catch (error) {
- }
- return this_is_demo;
- }
- function netdataURL(url, forReload) {
- if (typeof url === 'undefined')
- // url = document.location.toString();
- {
- url = '';
- }
- if (url.indexOf('#') !== -1) {
- url = url.substring(0, url.indexOf('#'));
- }
- var hash = urlOptions.genHash(forReload);
- // console.log('netdataURL: ' + url + hash);
- return url + hash;
- }
- function netdataReload(url) {
- document.location = verifyURL(netdataURL(url, true));
- // since we play with hash
- // this is needed to reload the page
- location.reload();
- }
- function gotoHostedModalHandler(url) {
- document.location = verifyURL(url + urlOptions.genHash());
- return false;
- }
- var gotoServerValidateRemaining = 0;
- var gotoServerMiddleClick = false;
- var gotoServerStop = false;
- function gotoServerValidateUrl(id, guid, url) {
- var penalty = 0;
- var error = 'failed';
- if (document.location.toString().startsWith('http://') && url.toString().startsWith('https://'))
- // we penalize https only if the current url is http
- // to allow the user walk through all its servers.
- {
- penalty = 500;
- } else if (document.location.toString().startsWith('https://') && url.toString().startsWith('http://')) {
- error = 'can\'t check';
- }
- var finalURL = netdataURL(url);
- setTimeout(function () {
- document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + verifyURL(finalURL) + '" target="_blank">' + escapeUserInputHTML(url) + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>';
- NETDATA.registry.hello(url, function (data) {
- if (typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) {
- // console.log('OK ' + id + ' URL: ' + url);
- document.getElementById(guid + '-' + id + '-status').innerHTML = "OK";
- if (!gotoServerStop) {
- gotoServerStop = true;
- if (gotoServerMiddleClick) {
- window.open(verifyURL(finalURL), '_blank');
- gotoServerMiddleClick = false;
- document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + verifyURL(finalURL) + '">' + escapeUserInputHTML(url) + '</a></b><br/>(check your pop-up blocker if it fails)';
- } else {
- document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + escapeUserInputHTML(url) + '</small>';
- document.location = verifyURL(finalURL);
- $('#gotoServerModal').modal('hide');
- }
- }
- } else {
- if (typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid) {
- error = 'wrong machine';
- }
- document.getElementById(guid + '-' + id + '-status').innerHTML = error;
- gotoServerValidateRemaining--;
- if (gotoServerValidateRemaining <= 0) {
- gotoServerMiddleClick = false;
- document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
- }
- }
- });
- }, (id * 50) + penalty);
- }
- function gotoServerModalHandler(guid) {
- // console.log('goto server: ' + guid);
- gotoServerStop = false;
- var checked = {};
- var len = NETDATA.registry.machines[guid].alternate_urls.length;
- var count = 0;
- document.getElementById('gotoServerResponse').innerHTML = '';
- document.getElementById('gotoServerList').innerHTML = '';
- document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
- $('#gotoServerModal').modal('show');
- gotoServerValidateRemaining = len;
- while (len--) {
- var url = NETDATA.registry.machines[guid].alternate_urls[len];
- checked[url] = true;
- gotoServerValidateUrl(count++, guid, url);
- }
- if (!isSignedIn()) {
- // When the registry is enabled, if the user's known URLs are not working
- // we consult the registry to get additional URLs.
- setTimeout(function () {
- if (gotoServerStop === false) {
- document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
- NETDATA.registry.search(guid, function (data) {
- // console.log(data);
- len = data.urls.length;
- while (len--) {
- var url = data.urls[len][1];
- // console.log(url);
- if (typeof checked[url] === 'undefined') {
- gotoServerValidateRemaining++;
- checked[url] = true;
- gotoServerValidateUrl(count++, guid, url);
- }
- }
- });
- }
- }, 2000);
- }
- return false;
- }
- function gotoServerInit() {
- $(".registry_link").on('click', function (e) {
- if (e.which === 2) {
- e.preventDefault();
- gotoServerMiddleClick = true;
- } else {
- gotoServerMiddleClick = false;
- }
- return true;
- });
- }
- function switchRegistryModalHandler() {
- document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
- document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
- document.getElementById('switchRegistryResponse').innerHTML = '';
- $('#switchRegistryModal').modal('show');
- }
- function notifyForSwitchRegistry() {
- var n = document.getElementById('switchRegistryPersonGUID').value;
- if (n !== '' && n.length === 36) {
- NETDATA.registry.switch(n, function (result) {
- if (result !== null) {
- $('#switchRegistryModal').modal('hide');
- NETDATA.registry.init();
- } else {
- document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
- }
- });
- } else {
- document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
- }
- }
- var deleteRegistryGuid = null;
- var deleteRegistryUrl = null;
- function deleteRegistryModalHandler(guid, name, url) {
- // void (guid);
- deleteRegistryGuid = guid;
- deleteRegistryUrl = url;
- document.getElementById('deleteRegistryServerName').innerHTML = name;
- document.getElementById('deleteRegistryServerName2').innerHTML = name;
- document.getElementById('deleteRegistryServerURL').innerHTML = url;
- document.getElementById('deleteRegistryResponse').innerHTML = '';
- $('#deleteRegistryModal').modal('show');
- }
- function notifyForDeleteRegistry() {
- const responseEl = document.getElementById('deleteRegistryResponse');
- if (deleteRegistryUrl) {
- if (isSignedIn()) {
- deleteCloudAgentURL(deleteRegistryGuid, deleteRegistryUrl)
- .then((count) => {
- if (!count) {
- responseEl.innerHTML = "<b>Sorry, this command was rejected by netdata.cloud!</b>";
- return;
- }
- NETDATA.registry.delete(deleteRegistryUrl, function (result) {
- if (result === null) {
- console.log("Received error from registry", result);
- }
- deleteRegistryUrl = null;
- $('#deleteRegistryModal').modal('hide');
- NETDATA.registry.init();
- });
- });
- } else {
- NETDATA.registry.delete(deleteRegistryUrl, function (result) {
- if (result !== null) {
- deleteRegistryUrl = null;
- $('#deleteRegistryModal').modal('hide');
- NETDATA.registry.init();
- } else {
- responseEl.innerHTML = "<b>Sorry, this command was rejected by the registry server!</b>";
- }
- });
- }
- }
- }
- var options = {
- menus: {},
- submenu_names: {},
- data: null,
- hostname: 'netdata_server', // will be overwritten by the netdata server
- version: 'unknown',
- release_channel: 'unknown',
- hosts: [],
- duration: 0, // the default duration of the charts
- update_every: 1,
- chartsPerRow: 0,
- // chartsMinWidth: 1450,
- chartsHeight: 180,
- };
- function chartsPerRow(total) {
- void (total);
- if (options.chartsPerRow === 0) {
- return 1;
- //var width = Math.floor(total / options.chartsMinWidth);
- //if(width === 0) width = 1;
- //return width;
- } else {
- return options.chartsPerRow;
- }
- }
- function prioritySort(a, b) {
- if (a.priority < b.priority) {
- return -1;
- }
- if (a.priority > b.priority) {
- return 1;
- }
- return naturalSortCompare(a.name, b.name);
- }
- function sortObjectByPriority(object) {
- var idx = {};
- var sorted = [];
- for (var i in object) {
- if (!object.hasOwnProperty(i)) {
- continue;
- }
- if (typeof idx[i] === 'undefined') {
- idx[i] = object[i];
- sorted.push(i);
- }
- }
- sorted.sort(function (a, b) {
- if (idx[a].priority < idx[b].priority) {
- return -1;
- }
- if (idx[a].priority > idx[b].priority) {
- return 1;
- }
- return naturalSortCompare(a, b);
- });
- return sorted;
- }
- // ----------------------------------------------------------------------------
- // scroll to a section, without changing the browser history
- function scrollToId(hash) {
- if (hash && hash !== '' && document.getElementById(hash) !== null) {
- var offset = $('#' + hash).offset();
- if (typeof offset !== 'undefined') {
- //console.log('scrolling to ' + hash + ' at ' + offset.top.toString());
- $('html, body').animate({ scrollTop: offset.top - 30 }, 0);
- }
- }
- // we must return false to prevent the default action
- return false;
- }
- // ----------------------------------------------------------------------------
- // user editable information
- var customDashboard = {
- menu: {},
- submenu: {},
- context: {}
- };
- // netdata standard information
- var netdataDashboard = {
- sparklines_registry: {},
- os: 'unknown',
- menu: {},
- submenu: {},
- context: {},
- // generate a sparkline
- // used in the documentation
- sparkline: function (prefix, chart, dimension, units, suffix) {
- if (options.data === null || typeof options.data.charts === 'undefined') {
- return '';
- }
- if (typeof options.data.charts[chart] === 'undefined') {
- return '';
- }
- if (typeof options.data.charts[chart].dimensions === 'undefined') {
- return '';
- }
- if (typeof options.data.charts[chart].dimensions[dimension] === 'undefined') {
- return '';
- }
- var key = chart + '.' + dimension;
- if (typeof units === 'undefined') {
- units = '';
- }
- if (typeof this.sparklines_registry[key] === 'undefined') {
- this.sparklines_registry[key] = { count: 1 };
- } else {
- this.sparklines_registry[key].count++;
- }
- key = key + '.' + this.sparklines_registry[key].count;
- return prefix + '<div class="netdata-container" data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')' + suffix;
- },
- gaugeChart: function (title, width, dimensions, colors) {
- if (typeof colors === 'undefined') {
- colors = '';
- }
- if (typeof dimensions === 'undefined') {
- dimensions = '';
- }
- return '<div class="netdata-container" data-netdata="CHART_UNIQUE_ID"'
- + ' data-dimensions="' + dimensions + '"'
- + ' data-chart-library="gauge"'
- + ' data-gauge-adjust="width"'
- + ' data-title="' + title + '"'
- + ' data-width="' + width + '"'
- + ' data-before="0"'
- + ' data-after="-CHART_DURATION"'
- + ' data-points="CHART_DURATION"'
- + ' data-colors="' + colors + '"'
- + ' role="application"></div>';
- },
- anyAttribute: function (obj, attr, key, def) {
- if (typeof (obj[key]) !== 'undefined') {
- var x = obj[key][attr];
- if (typeof (x) === 'undefined') {
- return def;
- }
- if (typeof (x) === 'function') {
- return x(netdataDashboard.os);
- }
- return x;
- }
- return def;
- },
- menuTitle: function (chart) {
- if (typeof chart.menu_pattern !== 'undefined') {
- return (this.anyAttribute(this.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
- + ' ' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
- }
- return (this.anyAttribute(this.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
- },
- menuIcon: function (chart) {
- if (typeof chart.menu_pattern !== 'undefined') {
- return this.anyAttribute(this.menu, 'icon', chart.menu_pattern, '<i class="fas fa-puzzle-piece"></i>').toString();
- }
- return this.anyAttribute(this.menu, 'icon', chart.menu, '<i class="fas fa-puzzle-piece"></i>');
- },
- menuInfo: function (chart) {
- if (typeof chart.menu_pattern !== 'undefined') {
- return this.anyAttribute(this.menu, 'info', chart.menu_pattern, null);
- }
- return this.anyAttribute(this.menu, 'info', chart.menu, null);
- },
- menuHeight: function (chart) {
- if (typeof chart.menu_pattern !== 'undefined') {
- return this.anyAttribute(this.menu, 'height', chart.menu_pattern, 1.0);
- }
- return this.anyAttribute(this.menu, 'height', chart.menu, 1.0);
- },
- submenuTitle: function (menu, submenu) {
- var key = menu + '.' + submenu;
- // console.log(key);
- var title = this.anyAttribute(this.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');
- if (title.length > 28) {
- var a = title.substring(0, 13);
- var b = title.substring(title.length - 12, title.length);
- return a + '...' + b;
- }
- return title;
- },
- submenuInfo: function (menu, submenu) {
- var key = menu + '.' + submenu;
- return this.anyAttribute(this.submenu, 'info', key, null);
- },
- submenuHeight: function (menu, submenu, relative) {
- var key = menu + '.' + submenu;
- return this.anyAttribute(this.submenu, 'height', key, 1.0) * relative;
- },
- contextInfo: function (id) {
- var x = this.anyAttribute(this.context, 'info', id, null);
- if (x !== null) {
- return '<div class="shorten dashboard-context-info netdata-chart-alignment" role="document">' + x + '</div>';
- } else {
- return '';
- }
- },
- contextValueRange: function (id) {
- if (typeof this.context[id] !== 'undefined' && typeof this.context[id].valueRange !== 'undefined') {
- return this.context[id].valueRange;
- } else {
- return '[null, null]';
- }
- },
- contextHeight: function (id, def) {
- if (typeof this.context[id] !== 'undefined' && typeof this.context[id].height !== 'undefined') {
- return def * this.context[id].height;
- } else {
- return def;
- }
- },
- contextDecimalDigits: function (id, def) {
- if (typeof this.context[id] !== 'undefined' && typeof this.context[id].decimalDigits !== 'undefined') {
- return this.context[id].decimalDigits;
- } else {
- return def;
- }
- }
- };
- // ----------------------------------------------------------------------------
- // enrich the data structure returned by netdata
- // to reflect our menu system and content
- // TODO: this is a shame - we should fix charts naming (issue #807)
- function enrichChartData(chart) {
- var parts = chart.type.split('_');
- var tmp = parts[0];
- switch (tmp) {
- case 'ap':
- case 'net':
- case 'disk':
- case 'powersupply':
- case 'statsd':
- chart.menu = tmp;
- break;
- case 'apache':
- chart.menu = chart.type;
- if (parts.length > 2 && parts[1] === 'cache') {
- chart.menu_pattern = tmp + '_' + parts[1];
- } else if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- case 'bind':
- chart.menu = chart.type;
- if (parts.length > 2 && parts[1] === 'rndc') {
- chart.menu_pattern = tmp + '_' + parts[1];
- } else if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- case 'cgroup':
- chart.menu = chart.type;
- if (chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/)) {
- chart.menu_pattern = 'cgqemu';
- } else {
- chart.menu_pattern = 'cgroup';
- }
- break;
- case 'go':
- chart.menu = chart.type;
- if (parts.length > 2 && parts[1] === 'expvar') {
- chart.menu_pattern = tmp + '_' + parts[1];
- } else if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- case 'mount':
- if (parts.length > 2) {
- chart.menu = tmp + '_' + parts[1];
- } else {
- chart.menu = tmp;
- }
- break;
- case 'isc':
- chart.menu = chart.type;
- if (parts.length > 2 && parts[1] === 'dhcpd') {
- chart.menu_pattern = tmp + '_' + parts[1];
- } else if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- case 'ovpn':
- chart.menu = chart.type;
- if (parts.length > 3 && parts[1] === 'status' && parts[2] === 'log') {
- chart.menu_pattern = tmp + '_' + parts[1];
- } else if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- case 'smartd':
- case 'web':
- chart.menu = chart.type;
- if (parts.length > 2 && parts[1] === 'log') {
- chart.menu_pattern = tmp + '_' + parts[1];
- } else if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- case 'tc':
- chart.menu = tmp;
- // find a name for this device from fireqos info
- // we strip '_(in|out)' or '(in|out)_'
- if (chart.context === 'tc.qos' && (typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family)) {
- var n = chart.name.split('.')[1];
- if (n.endsWith('_in')) {
- options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
- } else if (n.endsWith('_out')) {
- options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
- } else if (n.startsWith('in_')) {
- options.submenu_names[chart.family] = n.slice(3, n.length);
- } else if (n.startsWith('out_')) {
- options.submenu_names[chart.family] = n.slice(4, n.length);
- } else {
- options.submenu_names[chart.family] = n;
- }
- }
- // increase the priority of IFB devices
- // to have inbound appear before outbound
- if (chart.id.match(/.*-ifb$/)) {
- chart.priority--;
- }
- break;
- default:
- chart.menu = chart.type;
- if (parts.length > 1) {
- chart.menu_pattern = tmp;
- }
- break;
- }
- chart.submenu = chart.family;
- }
- // ----------------------------------------------------------------------------
- function headMain(os, charts, duration) {
- void (os);
- if (urlOptions.mode === 'print') {
- return '';
- }
- var head = '';
- if (typeof charts['system.swap'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.swap"'
- + ' data-dimensions="used"'
- + ' data-append-options="percentage"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Used Swap"'
- + ' data-units="%"'
- + ' data-easypiechart-max-value="100"'
- + ' data-width="9%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-colors="#DD4400"'
- + ' role="application"></div>';
- }
- if (typeof charts['system.io'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.io"'
- + ' data-dimensions="in"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Disk Read"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.io.mainhead"'
- + ' role="application"></div>';
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.io"'
- + ' data-dimensions="out"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Disk Write"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.io.mainhead"'
- + ' role="application"></div>';
- }
- else if (typeof charts['system.pgpgio'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.pgpgio"'
- + ' data-dimensions="in"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Disk Read"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.pgpgio.mainhead"'
- + ' role="application"></div>';
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.pgpgio"'
- + ' data-dimensions="out"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Disk Write"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.pgpgio.mainhead"'
- + ' role="application"></div>';
- }
- if (typeof charts['system.cpu'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.cpu"'
- + ' data-chart-library="gauge"'
- + ' data-title="CPU"'
- + ' data-units="%"'
- + ' data-gauge-max-value="100"'
- + ' data-width="20%"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-colors="' + NETDATA.colors[12] + '"'
- + ' role="application"></div>';
- }
- if (typeof charts['system.net'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.net"'
- + ' data-dimensions="received"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Net Inbound"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.net.mainhead"'
- + ' role="application"></div>';
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.net"'
- + ' data-dimensions="sent"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Net Outbound"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.net.mainhead"'
- + ' role="application"></div>';
- }
- else if (typeof charts['system.ip'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ip"'
- + ' data-dimensions="received"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="IP Inbound"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.ip.mainhead"'
- + ' role="application"></div>';
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ip"'
- + ' data-dimensions="sent"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="IP Outbound"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.ip.mainhead"'
- + ' role="application"></div>';
- }
- else if (typeof charts['system.ipv4'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv4"'
- + ' data-dimensions="received"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="IPv4 Inbound"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.ipv4.mainhead"'
- + ' role="application"></div>';
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv4"'
- + ' data-dimensions="sent"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="IPv4 Outbound"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.ipv4.mainhead"'
- + ' role="application"></div>';
- }
- else if (typeof charts['system.ipv6'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv6"'
- + ' data-dimensions="received"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="IPv6 Inbound"'
- + ' data-units="kbps"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.ipv6.mainhead"'
- + ' role="application"></div>';
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ipv6"'
- + ' data-dimensions="sent"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="IPv6 Outbound"'
- + ' data-units="kbps"'
- + ' data-width="11%"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-common-units="system.ipv6.mainhead"'
- + ' role="application"></div>';
- }
- if (typeof charts['system.ram'] !== 'undefined') {
- head += '<div class="netdata-container" style="margin-right: 10px;" data-netdata="system.ram"'
- + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
- + ' data-append-options="percentage"'
- + ' data-chart-library="easypiechart"'
- + ' data-title="Used RAM"'
- + ' data-units="%"'
- + ' data-easypiechart-max-value="100"'
- + ' data-width="9%"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-points="' + duration.toString() + '"'
- + ' data-colors="' + NETDATA.colors[7] + '"'
- + ' role="application"></div>';
- }
- return head;
- }
- function generateHeadCharts(type, chart, duration) {
- if (urlOptions.mode === 'print') {
- return '';
- }
- var head = '';
- var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
- if (hcharts.length > 0) {
- var hi = 0, hlen = hcharts.length;
- while (hi < hlen) {
- if (typeof hcharts[hi] === 'function') {
- head += hcharts[hi](netdataDashboard.os, chart.id).replace(/CHART_DURATION/g, duration.toString()).replace(/CHART_UNIQUE_ID/g, chart.id);
- } else {
- head += hcharts[hi].replace(/CHART_DURATION/g, duration.toString()).replace(/CHART_UNIQUE_ID/g, chart.id);
- }
- hi++;
- }
- }
- return head;
- }
- function renderPage(menus, data) {
- var div = document.getElementById('charts_div');
- var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
- // find the proper duration for per-second updates
- var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
- options.duration = duration;
- options.update_every = data.update_every;
- var html = '';
- var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
- var mainhead = headMain(netdataDashboard.os, data.charts, duration);
- // sort the menus
- var main = sortObjectByPriority(menus);
- var i = 0, len = main.length;
- while (i < len) {
- var menu = main[i++];
- // generate an entry at the main menu
- var menuid = NETDATA.name2id('menu_' + menu);
- sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
- html += '<div role="section" class="dashboard-section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].icon + ' ' + menus[menu].title + '</h1></div><div role="section" class="dashboard-subsection">';
- if (menus[menu].info !== null) {
- html += menus[menu].info;
- }
- // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
- var shtml = '';
- var mhead = '<div class="netdata-chart-row">' + mainhead;
- mainhead = '';
- // sort the submenus of this menu
- var sub = sortObjectByPriority(menus[menu].submenus);
- var si = 0, slen = sub.length;
- while (si < slen) {
- var submenu = sub[si++];
- // generate an entry at the submenu
- var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
- sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
- shtml += '<div role="section" class="dashboard-section-container" id="' + submenuid + '"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
- if (menus[menu].submenus[submenu].info !== null) {
- shtml += '<div class="dashboard-submenu-info netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
- }
- var head = '<div class="netdata-chart-row">';
- var chtml = '';
- // console.log(' \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
- // sort the charts in this submenu of this menu
- menus[menu].submenus[submenu].charts.sort(prioritySort);
- var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
- while (ci < clen) {
- var chart = menus[menu].submenus[submenu].charts[ci++];
- // generate the submenu heading charts
- mhead += generateHeadCharts('mainheads', chart, duration);
- head += generateHeadCharts('heads', chart, duration);
- function chartCommonMin(family, context, units) {
- var x = netdataDashboard.anyAttribute(netdataDashboard.context, 'commonMin', context, undefined);
- if (typeof x !== 'undefined') {
- return ' data-common-min="' + family + '/' + context + '/' + units + '"';
- } else {
- return '';
- }
- }
- function chartCommonMax(family, context, units) {
- var x = netdataDashboard.anyAttribute(netdataDashboard.context, 'commonMax', context, undefined);
- if (typeof x !== 'undefined') {
- return ' data-common-max="' + family + '/' + context + '/' + units + '"';
- } else {
- return '';
- }
- }
- // generate the chart
- if (urlOptions.mode === 'print') {
- chtml += '<div role="row" class="dashboard-print-row">';
- }
- chtml += '<div class="netdata-chartblock-container" style="width: ' + pcent_width.toString() + '%;">' + netdataDashboard.contextInfo(chart.context) + '<div class="netdata-container" id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
- + ' data-width="100%"'
- + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
- + ' data-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"'
- + ' data-before="0"'
- + ' data-after="-' + duration.toString() + '"'
- + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
- + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
- + ' data-decimal-digits="' + netdataDashboard.contextDecimalDigits(chart.context, -1) + '"'
- + chartCommonMin(chart.family, chart.context, chart.units)
- + chartCommonMax(chart.family, chart.context, chart.units)
- + ' role="application"></div></div>';
- if (urlOptions.mode === 'print') {
- chtml += '</div>';
- }
- }
- head += '</div>';
- shtml += head + chtml + '</div>';
- }
- mhead += '</div>';
- sidebar += '</ul></li>';
- html += mhead + shtml + '</div></div><hr role="separator"/>';
- }
- const isMemoryModeDbEngine = data.memory_mode === "dbengine";
- sidebar += '<li class="" style="padding-top:15px;"><a href="https://learn.netdata.cloud/docs/agent/collectors/quickstart/" target="_blank"><i class="fas fa-plus"></i> Add more charts</a></li>';
- sidebar += '<li class=""><a href="https://learn.netdata.cloud/docs/agent/health/quickstart/" target="_blank"><i class="fas fa-plus"></i> Add more alarms</a></li>';
- sidebar += '<li class="" style="margin:20px;color:#666;"><small>Every ' +
- ((data.update_every === 1) ? 'second' : data.update_every.toString() + ' seconds') + ', ' +
- 'Netdata collects <strong>' + data.dimensions_count.toLocaleString() + '</strong> metrics on ' +
- data.hostname.toString() + ', presents them in <strong>' +
- data.charts_count.toLocaleString() + '</strong> charts' +
- (isMemoryModeDbEngine ? '' : ',') + // oxford comma
- ' and monitors them with <strong>' +
- data.alarms_count.toLocaleString() + '</strong> alarms.';
- if (!isMemoryModeDbEngine) {
- sidebar += '<br /> <br />Get more history by ' +
- '<a href="https://learn.netdata.cloud/guides/longer-metrics-storage#using-the-round-robin-database" target=_blank>configuring Netdata\'s <strong>history</strong></a> or using the <a href="https://learn.netdata.cloud/docs/agent/database/engine/" target=_blank>DB engine.</a>';
- }
- sidebar += '<br/> <br/><strong>netdata</strong><br/>' + data.version.toString() + '</small></li>';
- sidebar += '</ul>';
- div.innerHTML = html;
- document.getElementById('sidebar').innerHTML = sidebar;
- if (urlOptions.highlight === true) {
- NETDATA.globalChartUnderlay.init(null
- , urlOptions.highlight_after
- , urlOptions.highlight_before
- , (urlOptions.after > 0) ? urlOptions.after : null
- , (urlOptions.before > 0) ? urlOptions.before : null
- );
- } else {
- NETDATA.globalChartUnderlay.clear();
- }
- if (urlOptions.mode === 'print') {
- printPage();
- } else {
- finalizePage();
- }
- }
- function renderChartsAndMenu(data) {
- options.menus = {};
- options.submenu_names = {};
- var menus = options.menus;
- var charts = data.charts;
- var m, menu_key;
- for (var c in charts) {
- if (!charts.hasOwnProperty(c)) {
- continue;
- }
- var chart = charts[c];
- enrichChartData(chart);
- m = chart.menu;
- // create the menu
- if (typeof menus[m] === 'undefined') {
- menus[m] = {
- menu_pattern: chart.menu_pattern,
- priority: chart.priority,
- submenus: {},
- title: netdataDashboard.menuTitle(chart),
- icon: netdataDashboard.menuIcon(chart),
- info: netdataDashboard.menuInfo(chart),
- height: netdataDashboard.menuHeight(chart) * options.chartsHeight
- };
- } else {
- if (typeof (menus[m].menu_pattern) === 'undefined') {
- menus[m].menu_pattern = chart.menu_pattern;
- }
- if (chart.priority < menus[m].priority) {
- menus[m].priority = chart.priority;
- }
- }
- menu_key = (typeof (menus[m].menu_pattern) !== 'undefined') ? menus[m].menu_pattern : m;
- // create the submenu
- if (typeof menus[m].submenus[chart.submenu] === 'undefined') {
- menus[m].submenus[chart.submenu] = {
- priority: chart.priority,
- charts: [],
- title: null,
- info: netdataDashboard.submenuInfo(menu_key, chart.submenu),
- height: netdataDashboard.submenuHeight(menu_key, chart.submenu, menus[m].height)
- };
- } else {
- if (chart.priority < menus[m].submenus[chart.submenu].priority) {
- menus[m].submenus[chart.submenu].priority = chart.priority;
- }
- }
- // index the chart in the menu/submenu
- menus[m].submenus[chart.submenu].charts.push(chart);
- }
- // propagate the descriptive subname given to QoS
- // to all the other submenus with the same name
- for (var m in menus) {
- if (!menus.hasOwnProperty(m)) {
- continue;
- }
- for (var s in menus[m].submenus) {
- if (!menus[m].submenus.hasOwnProperty(s)) {
- continue;
- }
- // set the family using a name
- if (typeof options.submenu_names[s] !== 'undefined') {
- menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
- } else {
- menu_key = (typeof (menus[m].menu_pattern) !== 'undefined') ? menus[m].menu_pattern : m;
- menus[m].submenus[s].title = netdataDashboard.submenuTitle(menu_key, s);
- }
- }
- }
- renderPage(menus, data);
- }
- // ----------------------------------------------------------------------------
- function loadJs(url, callback) {
- $.ajax({
- url: url.startsWith("http") ? url : transformWithOldSuffix(url),
- cache: true,
- dataType: "script",
- xhrFields: { withCredentials: true } // required for the cookie
- })
- .fail(function () {
- alert('Cannot load required JS library: ' + url);
- })
- .always(function () {
- if (typeof callback === 'function') {
- callback();
- }
- })
- }
- var clipboardLoaded = false;
- function loadClipboard(callback) {
- if (clipboardLoaded === false) {
- clipboardLoaded = true;
- loadJs('lib/clipboard-polyfill-be05dad.js', callback);
- } else {
- callback();
- }
- }
- var bootstrapTableLoaded = false;
- function loadBootstrapTable(callback) {
- if (bootstrapTableLoaded === false) {
- bootstrapTableLoaded = true;
- loadJs('lib/bootstrap-table-1.11.0.min.js', function () {
- loadJs('lib/bootstrap-table-export-1.11.0.min.js', function () {
- loadJs('lib/tableExport-1.6.0.min.js', callback);
- })
- });
- } else {
- callback();
- }
- }
- var bootstrapSliderLoaded = false;
- function loadBootstrapSlider(callback) {
- if (bootstrapSliderLoaded === false) {
- bootstrapSliderLoaded = true;
- loadJs('lib/bootstrap-slider-10.0.0.min.js', function () {
- NETDATA._loadCSS(transformWithOldSuffix("css/bootstrap-slider-10.0.0.min.css"));
- callback();
- });
- } else {
- callback();
- }
- }
- var lzStringLoaded = false;
- function loadLzString(callback) {
- if (lzStringLoaded === false) {
- lzStringLoaded = true;
- loadJs('lib/lz-string-1.4.4.min.js', callback);
- } else {
- callback();
- }
- }
- var pakoLoaded = false;
- function loadPako(callback) {
- if (pakoLoaded === false) {
- pakoLoaded = true;
- loadJs('lib/pako-1.0.6.min.js', callback);
- } else {
- callback();
- }
- }
- // ----------------------------------------------------------------------------
- function clipboardCopy(text) {
- clipboard.writeText(text);
- }
- function clipboardCopyBadgeEmbed(url) {
- clipboard.writeText('<embed src="' + url + '" type="image/svg+xml" height="20"/>');
- }
- // ----------------------------------------------------------------------------
- function alarmsUpdateModal() {
- var active = '<h3>Raised Alarms</h3><table class="table">';
- var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
- var footer = '<hr/><a href="https://github.com/netdata/netdata/tree/master/web/api/badges#netdata-badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b> red </b></span> is critical, <span style="color:#fe7d37"><b> orange </b></span> is warning, <span style="color: #4c1"><b> bright green </b></span> is ok, <span style="color: #9f9f9f"><b> light grey </b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b> black </b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/netdata/netdata/blob/master/health/notifications/health_alarm_notify.conf" target="_blank">this configuration file</a> for more information.';
- loadClipboard(function () {
- });
- NETDATA.alarms.get('all', function (data) {
- options.alarm_families = [];
- alarmsCallback(data);
- if (data === null) {
- document.getElementById('alarms_active').innerHTML =
- document.getElementById('alarms_all').innerHTML =
- document.getElementById('alarms_log').innerHTML =
- 'failed to load alarm data!';
- return;
- }
- function alarmid4human(id) {
- if (id === 0) {
- return '-';
- }
- return id.toString();
- }
- function timestamp4human(timestamp, space) {
- if (timestamp === 0) {
- return '-';
- }
- if (typeof space === 'undefined') {
- space = ' ';
- }
- var t = new Date(timestamp * 1000);
- var now = new Date();
- if (t.toDateString() === now.toDateString()) {
- return t.toLocaleTimeString();
- }
- return t.toLocaleDateString() + space + t.toLocaleTimeString();
- }
- function alarm_lookup_explain(alarm, chart) {
- var dimensions = ' of all values ';
- if (chart.dimensions.length > 1) {
- dimensions = ' of the sum of all dimensions ';
- }
- if (typeof alarm.lookup_dimensions !== 'undefined') {
- var d = alarm.lookup_dimensions.replace(/|/g, ',');
- var x = d.split(',');
- if (x.length > 1) {
- dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
- } else {
- dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
- }
- }
- return '<code>' + alarm.lookup_method + '</code> '
- + dimensions + ', of chart <code>' + alarm.chart + '</code>'
- + ', starting <code>' + NETDATA.seconds4human(alarm.lookup_after + alarm.lookup_before, { space: ' ' }) + '</code> and up to <code>' + NETDATA.seconds4human(alarm.lookup_before, { space: ' ' }) + '</code>'
- + ((alarm.lookup_options) ? (', with options <code>' + alarm.lookup_options.replace(/ /g, ', ') + '</code>') : '')
- + '.';
- }
- function alarm_to_html(alarm, full) {
- var chart = options.data.charts[alarm.chart];
- if (typeof (chart) === 'undefined') {
- chart = options.data.charts_by_name[alarm.chart];
- if (typeof (chart) === 'undefined') {
- // this means the charts loaded are incomplete
- // probably netdata was restarted and more alarms
- // are now available.
- console.log('Cannot find chart ' + alarm.chart + ', you probably need to refresh the page.');
- return '';
- }
- }
- var has_alarm = (typeof alarm.warn !== 'undefined' || typeof alarm.crit !== 'undefined');
- var badge_url = NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto';
- var action_buttons = '<br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/>'
- + '<div class="action-button ripple" title="click to scroll the dashboard to the chart of this alarm" data-toggle="tooltip" data-placement="bottom" onClick="scrollToChartAfterHidingModal(\'' + alarm.chart + '\', ' + alarm.last_status_change * 1000 + ', \'' + alarm.status + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;"><i class="fab fa-periscope"></i></div>'
- + '<div class="action-button ripple" title="click to copy to the clipboard the URL of this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopy(\'' + badge_url + '\'); return false;"><i class="far fa-copy"></i></div>'
- + '<div class="action-button ripple" title="click to copy to the clipboard an auto-refreshing <code>embed</code> html element for this badge" data-toggle="tooltip" data-placement="bottom" onClick="clipboardCopyBadgeEmbed(\'' + badge_url + '\'); return false;"><i class="fas fa-copy"></i></div>';
- var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/> <br/><embed src="' + badge_url + '" type="image/svg+xml" height="20"/><br/> <br/><span style="font-size: 18px">' + alarm.info + '</span>' + action_buttons + '</td>'
- + '<td><table class="table">'
- + ((typeof alarm.warn !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">warning when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>') : '')
- + ((typeof alarm.crit !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">critical when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>') : '');
- if (full === true) {
- var units = chart.units;
- if (units === '%') {
- units = '%';
- }
- html += ((typeof alarm.lookup_after !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">db lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>') : '')
- + ((typeof alarm.calc !== 'undefined') ? ('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>') : '')
- + ((chart.green !== null) ? ('<tr><td width="10%" style="text-align:right">green threshold</td><td><code>' + chart.green + ' ' + units + '</code></td></tr>') : '')
- + ((chart.red !== null) ? ('<tr><td width="10%" style="text-align:right">red threshold</td><td><code>' + chart.red + ' ' + units + '</code></td></tr>') : '');
- }
- if (alarm.warn_repeat_every > 0) {
- html += '<tr><td width="10%" style="text-align:right">repeat warning</td><td>' + NETDATA.seconds4human(alarm.warn_repeat_every) + '</td></tr>';
- }
- if (alarm.crit_repeat_every > 0) {
- html += '<tr><td width="10%" style="text-align:right">repeat critical</td><td>' + NETDATA.seconds4human(alarm.crit_repeat_every) + '</td></tr>';
- }
- var delay = '';
- if ((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier !== 0 && alarm.delay_max_duration > 0) {
- if (alarm.delay_up_duration === alarm.delay_down_duration) {
- delay += '<small><br/>hysteresis ' + NETDATA.seconds4human(alarm.delay_up_duration, {
- space: ' ',
- negative_suffix: ''
- });
- } else {
- delay = '<small><br/>hysteresis ';
- if (alarm.delay_up_duration > 0) {
- delay += 'on escalation <code>' + NETDATA.seconds4human(alarm.delay_up_duration, {
- space: ' ',
- negative_suffix: ''
- }) + '</code>, ';
- }
- if (alarm.delay_down_duration > 0) {
- delay += 'on recovery <code>' + NETDATA.seconds4human(alarm.delay_down_duration, {
- space: ' ',
- negative_suffix: ''
- }) + '</code>, ';
- }
- }
- if (alarm.delay_multiplier !== 1.0) {
- delay += 'multiplied by <code>' + alarm.delay_multiplier.toString() + '</code>';
- delay += ', up to <code>' + NETDATA.seconds4human(alarm.delay_max_duration, {
- space: ' ',
- negative_suffix: ''
- }) + '</code>';
- }
- delay += '</small>';
- }
- html += '<tr><td width="10%" style="text-align:right">check every</td><td>' + NETDATA.seconds4human(alarm.update_every, {
- space: ' ',
- negative_suffix: ''
- }) + '</td></tr>'
- + ((has_alarm === true) ? ('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>') : '')
- + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
- + '</table></td></tr>';
- return html;
- }
- function alarm_family_show(id) {
- var html = '<table class="table">';
- var family = options.alarm_families[id];
- var len = family.arr.length;
- while (len--) {
- var alarm = family.arr[len];
- html += alarm_to_html(alarm, true);
- }
- html += '</table>';
- $('#alarm_all_' + id.toString()).html(html);
- enableTooltipsAndPopovers();
- }
- // find the proper family of each alarm
- var x, family, alarm;
- var count_active = 0;
- var count_all = 0;
- var families = {};
- var families_sort = [];
- for (x in data.alarms) {
- if (!data.alarms.hasOwnProperty(x)) {
- continue;
- }
- alarm = data.alarms[x];
- family = alarm.family;
- // find the chart
- var chart = options.data.charts[alarm.chart];
- if (typeof chart === 'undefined') {
- chart = options.data.charts_by_name[alarm.chart];
- }
- // not found - this should never happen!
- if (typeof chart === 'undefined') {
- console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
- chart = { priority: 9999999 };
- }
- else if (typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
- // the family based on the chart
- {
- family = chart.menu + ' - ' + chart.submenu;
- }
- if (typeof families[family] === 'undefined') {
- families[family] = {
- name: family,
- arr: [],
- priority: chart.priority
- };
- families_sort.push(families[family]);
- }
- if (chart.priority < families[family].priority) {
- families[family].priority = chart.priority;
- }
- families[family].arr.unshift(alarm);
- }
- // sort the families, like the dashboard menu does
- var families_sorted = families_sort.sort(function (a, b) {
- if (a.priority < b.priority) {
- return -1;
- }
- if (a.priority > b.priority) {
- return 1;
- }
- return naturalSortCompare(a.name, b.name);
- });
- var i = 0;
- var fc = 0;
- var len = families_sorted.length;
- while (len--) {
- family = families_sorted[i++].name;
- var active_family_added = false;
- var expanded = 'true';
- var collapsed = '';
- var cin = 'in';
- if (fc !== 0) {
- all += "</table></div></div></div>";
- expanded = 'false';
- collapsed = 'class="collapsed"';
- cin = '';
- }
- all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">';
- options.alarm_families[fc] = families[family];
- fc++;
- var arr = families[family].arr;
- var c = arr.length;
- while (c--) {
- alarm = arr[c];
- if (alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
- if (!active_family_added) {
- active_family_added = true;
- active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
- }
- count_active++;
- active += alarm_to_html(alarm, true);
- }
- count_all++;
- }
- }
- active += "</table>";
- if (families_sorted.length > 0) {
- all += "</div></div></div>";
- }
- all += "</div>";
- if (!count_active) {
- active += '<div style="width:100%; height: 100px; text-align: center;"><span style="font-size: 50px;"><i class="fas fa-thumbs-up"></i></span><br/>Everything is normal. No raised alarms.</div>';
- } else {
- active += footer;
- }
- if (!count_all) {
- all += "<h4>No alarms are running in this system.</h4>";
- } else {
- all += footer;
- }
- document.getElementById('alarms_active').innerHTML = active;
- document.getElementById('alarms_all').innerHTML = all;
- enableTooltipsAndPopovers();
- if (families_sorted.length > 0) {
- alarm_family_show(0);
- }
- // register bootstrap events
- var $accordion = $('#alarms_all_accordion');
- $accordion.on('show.bs.collapse', function (d) {
- var target = $(d.target);
- var id = $(target).data('alarm-id');
- alarm_family_show(id);
- });
- $accordion.on('hidden.bs.collapse', function (d) {
- var target = $(d.target);
- var id = $(target).data('alarm-id');
- $('#alarm_all_' + id.toString()).html('');
- });
- document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
- loadBootstrapTable(function () {
- $('#alarms_log_table').bootstrapTable({
- url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
- cache: false,
- pagination: true,
- pageSize: 10,
- showPaginationSwitch: false,
- search: true,
- searchTimeOut: 300,
- searchAlign: 'left',
- showColumns: true,
- showExport: true,
- exportDataType: 'basic',
- exportOptions: {
- fileName: 'netdata_alarm_log'
- },
- onClickRow: function (row, $element,field) {
- void (field);
- void ($element);
- let main_url;
- let common_url = "&host=" + encodeURIComponent(row['hostname']) + "&chart=" + encodeURIComponent(row['chart']) + "&family=" + encodeURIComponent(row['family']) + "&alarm=" + encodeURIComponent(row['name']) + "&alarm_unique_id=" + row['unique_id'] + "&alarm_id=" + row['alarm_id'] + "&alarm_event_id=" + row['alarm_event_id'] + "&alarm_when=" + row['when'];
- if (NETDATA.registry.isUsingGlobalRegistry() && NETDATA.registry.machine_guid != null) {
- main_url = "https://netdata.cloud/alarms/redirect?agentID=" + NETDATA.registry.machine_guid + common_url;
- } else {
- main_url = NETDATA.registry.server + "/goto-host-from-alarm.html?" + common_url ;
- }
- window.open(main_url,"_blank");
- },
- rowStyle: function (row, index) {
- void (index);
- switch (row.status) {
- case 'CRITICAL':
- return { classes: 'danger' };
- break;
- case 'WARNING':
- return { classes: 'warning' };
- break;
- case 'UNDEFINED':
- return { classes: 'info' };
- break;
- case 'CLEAR':
- return { classes: 'success' };
- break;
- }
- return {};
- },
- showFooter: false,
- showHeader: true,
- showRefresh: true,
- showToggle: false,
- sortable: true,
- silentSort: false,
- columns: [
- {
- field: 'when',
- title: 'Event Date',
- valign: 'middle',
- titleTooltip: 'The date and time the even took place',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return timestamp4human(value, ' ');
- },
- align: 'center',
- switchable: false,
- sortable: true
- },
- {
- field: 'hostname',
- title: 'Host',
- valign: 'middle',
- titleTooltip: 'The host that generated this event',
- align: 'center',
- visible: false,
- sortable: true
- },
- {
- field: 'unique_id',
- title: 'Unique ID',
- titleTooltip: 'The host unique ID for this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return alarmid4human(value);
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'alarm_id',
- title: 'Alarm ID',
- titleTooltip: 'The ID of the alarm that generated this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return alarmid4human(value);
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'alarm_event_id',
- title: 'Alarm Event ID',
- titleTooltip: 'The incremental ID of this event for the given alarm',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return alarmid4human(value);
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'chart',
- title: 'Chart',
- titleTooltip: 'The chart the alarm is attached to',
- align: 'center',
- valign: 'middle',
- switchable: false,
- sortable: true
- },
- {
- field: 'family',
- title: 'Family',
- titleTooltip: 'The family of the chart the alarm is attached to',
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'name',
- title: 'Alarm',
- titleTooltip: 'The alarm name that generated this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return value.toString().replace(/_/g, ' ');
- },
- align: 'center',
- valign: 'middle',
- switchable: false,
- sortable: true
- },
- {
- field: 'value_string',
- title: 'Friendly Value',
- titleTooltip: 'The value of the alarm, that triggered this event',
- align: 'right',
- valign: 'middle',
- sortable: true
- },
- {
- field: 'old_value_string',
- title: 'Friendly Old Value',
- titleTooltip: 'The value of the alarm, just before this event',
- align: 'right',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'old_value',
- title: 'Old Value',
- titleTooltip: 'The value of the alarm, just before this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return ((value !== null) ? Math.round(value * 100) / 100 : 'NaN').toString();
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'value',
- title: 'Value',
- titleTooltip: 'The value of the alarm, that triggered this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return ((value !== null) ? Math.round(value * 100) / 100 : 'NaN').toString();
- },
- align: 'right',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'units',
- title: 'Units',
- titleTooltip: 'The units of the value of the alarm',
- align: 'left',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'old_status',
- title: 'Old Status',
- titleTooltip: 'The status of the alarm, just before this event',
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'status',
- title: 'Status',
- titleTooltip: 'The status of the alarm, that was set due to this event',
- align: 'center',
- valign: 'middle',
- switchable: false,
- sortable: true
- },
- {
- field: 'duration',
- title: 'Last Duration',
- titleTooltip: 'The duration the alarm was at its previous state, just before this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'non_clear_duration',
- title: 'Raised Duration',
- titleTooltip: 'The duration the alarm was raised, just before this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'recipient',
- title: 'Recipient',
- titleTooltip: 'The recipient of this event',
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'processed',
- title: 'Processed Status',
- titleTooltip: 'True when this event is processed',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- if (value === true) {
- return 'DONE';
- } else {
- return 'PENDING';
- }
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'updated',
- title: 'Updated Status',
- titleTooltip: 'True when this event has been updated by another event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- if (value === true) {
- return 'UPDATED';
- } else {
- return 'CURRENT';
- }
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'updated_by_id',
- title: 'Updated By ID',
- titleTooltip: 'The unique ID of the event that obsoleted this one',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return alarmid4human(value);
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'updates_id',
- title: 'Updates ID',
- titleTooltip: 'The unique ID of the event obsoleted because of this event',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return alarmid4human(value);
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'exec',
- title: 'Script',
- titleTooltip: 'The script to handle the event notification',
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'exec_run',
- title: 'Script Run At',
- titleTooltip: 'The date and time the script has been ran',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return timestamp4human(value, ' ');
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'exec_code',
- title: 'Script Return Value',
- titleTooltip: 'The return code of the script',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- if (value === 0) {
- return 'OK (returned 0)';
- } else {
- return 'FAILED (with code ' + value.toString() + ')';
- }
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'delay',
- title: 'Script Delay',
- titleTooltip: 'The hysteresis of the notification',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'delay_up_to_timestamp',
- title: 'Script Delay Run At',
- titleTooltip: 'The date and time the script should be run, after hysteresis',
- formatter: function (value, row, index) {
- void (row);
- void (index);
- return timestamp4human(value, ' ');
- },
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'info',
- title: 'Description',
- titleTooltip: 'A short description of the alarm',
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- },
- {
- field: 'source',
- title: 'Alarm Source',
- titleTooltip: 'The source of configuration of the alarm',
- align: 'center',
- valign: 'middle',
- visible: false,
- sortable: true
- }
- ]
- });
- // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
- });
- });
- }
- function alarmsCallback(data) {
- var count = 0, x;
- for (x in data.alarms) {
- if (!data.alarms.hasOwnProperty(x)) {
- continue;
- }
- var alarm = data.alarms[x];
- if (alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
- count++;
- }
- }
- if (count > 0) {
- document.getElementById('alarms_count_badge').innerHTML = count.toString();
- } else {
- document.getElementById('alarms_count_badge').innerHTML = '';
- }
- }
- function initializeDynamicDashboardWithData(data) {
- if (data !== null) {
- options.hostname = data.hostname;
- options.data = data;
- options.version = data.version;
- options.release_channel = data.release_channel;
- netdataDashboard.os = data.os;
- if (typeof data.hosts !== 'undefined') {
- options.hosts = data.hosts;
- }
- // update the dashboard hostname
- document.getElementById('hostname').innerHTML = '<span id="hostnametext">' + options.hostname + ((netdataSnapshotData !== null) ? ' (snap)' : '').toString() + '</span> <strong class="caret">';
- document.getElementById('hostname').href = NETDATA.serverDefault;
- document.getElementById('netdataVersion').innerHTML = options.version;
- if (netdataSnapshotData !== null) {
- $('#alarmsButton').hide();
- $('#updateButton').hide();
- // $('#loadButton').hide();
- $('#saveButton').hide();
- $('#printButton').hide();
- }
- // update the dashboard title
- document.title = options.hostname + ' netdata dashboard';
- // close the splash screen
- $("#loadOverlay").css("display", "none");
- // create a chart_by_name index
- data.charts_by_name = {};
- var charts = data.charts;
- var x;
- for (x in charts) {
- if (!charts.hasOwnProperty(x)) {
- continue;
- }
- var chart = charts[x];
- data.charts_by_name[chart.name] = chart;
- }
- // render all charts
- renderChartsAndMenu(data);
- // Ensure MyNetdata menu is rendered with latest host info #5370
- renderMyNetdataMenu(isSignedIn() ? cloudAgents : registryAgents);
- }
- }
- // an object to keep initialization configuration
- // needed due to the async nature of the XSS modal
- var initializeConfig = {
- url: null,
- custom_info: true,
- };
- function loadCustomDashboardInfo(url, callback) {
- loadJs(url, function () {
- $.extend(true, netdataDashboard, customDashboard);
- callback();
- });
- }
- function initializeChartsAndCustomInfo() {
- NETDATA.alarms.callback = alarmsCallback;
- // download all the charts the server knows
- NETDATA.chartRegistry.downloadAll(initializeConfig.url, function (data) {
- if (data !== null) {
- if (initializeConfig.custom_info === true && typeof data.custom_info !== 'undefined' && data.custom_info !== "" && netdataSnapshotData === null) {
- //console.log('loading custom dashboard decorations from server ' + initializeConfig.url);
- loadCustomDashboardInfo(NETDATA.serverDefault + data.custom_info, function () {
- initializeDynamicDashboardWithData(data);
- });
- } else {
- //console.log('not loading custom dashboard decorations from server ' + initializeConfig.url);
- initializeDynamicDashboardWithData(data);
- }
- }
- });
- }
- function xssModalDisableXss() {
- //console.log('disabling xss checks');
- NETDATA.xss.enabled = false;
- NETDATA.xss.enabled_for_data = false;
- initializeConfig.custom_info = true;
- initializeChartsAndCustomInfo();
- return false;
- }
- function xssModalKeepXss() {
- //console.log('keeping xss checks');
- NETDATA.xss.enabled = true;
- NETDATA.xss.enabled_for_data = true;
- initializeConfig.custom_info = false;
- initializeChartsAndCustomInfo();
- return false;
- }
- function initializeDynamicDashboard(netdata_url) {
- if (typeof netdata_url === 'undefined' || netdata_url === null) {
- netdata_url = NETDATA.serverDefault;
- }
- initializeConfig.url = netdata_url;
- // initialize clickable alarms
- NETDATA.alarms.chart_div_offset = -50;
- NETDATA.alarms.chart_div_id_prefix = 'chart_';
- NETDATA.alarms.chart_div_animation_duration = 0;
- NETDATA.pause(function () {
- if (typeof netdataCheckXSS !== 'undefined' && netdataCheckXSS === true) {
- //$("#loadOverlay").css("display","none");
- document.getElementById('netdataXssModalServer').innerText = initializeConfig.url;
- $('#xssModal').modal('show');
- } else {
- initializeChartsAndCustomInfo();
- }
- });
- }
- // ----------------------------------------------------------------------------
- function versionLog(msg) {
- document.getElementById('versionCheckLog').innerHTML = msg;
- }
- // New way of checking for updates, based only on versions
- function versionsMatch(v1, v2) {
- if (v1 == v2) {
- return true;
- } else {
- let s1 = v1.split('.');
- let s2 = v2.split('.');
- // Check major version
- let n1 = parseInt(s1[0].substring(1, 2), 10);
- let n2 = parseInt(s2[0].substring(1, 2), 10);
- if (n1 < n2) return false;
- else if (n1 > n2) return true;
- // Check minor version
- n1 = parseInt(s1[1], 10);
- n2 = parseInt(s2[1], 10);
- if (n1 < n2) return false;
- else if (n1 > n2) return true;
- // Split patch: format could be e.g. 0-22-nightly
- s1 = s1[2].split('-');
- s2 = s2[2].split('-');
- n1 = parseInt(s1[0], 10);
- n2 = parseInt(s2[0], 10);
- if (n1 < n2) return false;
- else if (n1 > n2) return true;
- n1 = (s1.length > 1) ? parseInt(s1[1], 10) : 0;
- n2 = (s2.length > 1) ? parseInt(s2[1], 10) : 0;
- if (n1 < n2) return false;
- else return true;
- }
- }
- function getGithubLatestVersion(callback) {
- versionLog('Downloading latest version id from github...');
- $.ajax({
- url: 'https://api.github.com/repos/netdata/netdata/releases/latest',
- async: true,
- cache: false
- })
- .done(function (data) {
- data = data.tag_name.replace(/(\r\n|\n|\r| |\t)/gm, "");
- versionLog('Latest stable version from github is ' + data);
- callback(data);
- })
- .fail(function () {
- versionLog('Failed to download the latest stable version id from github!');
- callback(null);
- });
- }
- function getGCSLatestVersion(callback) {
- versionLog('Downloading latest version id from GCS...');
- $.ajax({
- url: "https://www.googleapis.com/storage/v1/b/netdata-nightlies/o/latest-version.txt",
- async: true,
- cache: false
- })
- .done(function (response) {
- $.ajax({
- url: response.mediaLink,
- async: true,
- cache: false
- })
- .done(function (data) {
- data = data.replace(/(\r\n|\n|\r| |\t)/gm, "");
- versionLog('Latest nightly version from GCS is ' + data);
- callback(data);
- })
- .fail(function (xhr, textStatus, errorThrown) {
- versionLog('Failed to download the latest nightly version id from GCS!');
- callback(null);
- });
- })
- .fail(function (xhr, textStatus, errorThrown) {
- versionLog('Failed to download the latest nightly version from GCS!');
- callback(null);
- });
- }
- function checkForUpdateByVersion(force, callback) {
- if (options.release_channel === 'stable') {
- getGithubLatestVersion(function (sha2) {
- callback(options.version, sha2);
- });
- } else {
- getGCSLatestVersion(function (sha2) {
- callback(options.version, sha2);
- });
- }
- return null;
- }
- function notifyForUpdate(force) {
- versionLog('<p>checking for updates...</p>');
- var now = Date.now();
- if (typeof force === 'undefined' || force !== true) {
- var last = loadLocalStorage('last_update_check');
- if (typeof last === 'string') {
- last = parseInt(last);
- } else {
- last = 0;
- }
- if (now - last < 3600000 * 8) {
- // no need to check it - too soon
- return;
- }
- }
- checkForUpdateByVersion(force, function (sha1, sha2) {
- var save = false;
- if (sha1 === null) {
- save = false;
- versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest netdata from <a href="https://github.com/netdata/netdata" target="_blank">its github page</a>.</p>');
- } else if (sha2 === null) {
- save = false;
- versionLog('<p><big>Failed to get the latest netdata version.</big></p><p>You can always get the latest netdata from <a href="https://github.com/netdata/netdata" target="_blank">its github page</a>.</p>');
- } else if (versionsMatch(sha1, sha2)) {
- save = true;
- versionLog('<p><big>You already have the latest netdata!</big></p><p>No update yet?<br/>We probably need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/netdata/netdata" target="_blank">give netdata a <b><i class="fas fa-star"></i></b> at its github page</a>.</p>');
- } else {
- save = true;
- var compare = 'https://learn.netdata.cloud/docs/agent/changelog/';
- versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: <b><code>' + sha2 + '</code></b></p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> and<br/><a href="https://github.com/netdata/netdata/tree/master/packaging/installer/UPDATE.md" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated is generally a good idea.</p>');
- document.getElementById('update_badge').innerHTML = '!';
- }
- if (save) {
- saveLocalStorage('last_update_check', now.toString());
- }
- });
- }
- // ----------------------------------------------------------------------------
- // printing dashboards
- function showPageFooter() {
- document.getElementById('footer').style.display = 'block';
- }
- function printPreflight() {
- var url = document.location.origin.toString() + document.location.pathname.toString() + document.location.search.toString() + urlOptions.genHash() + ';mode=print';
- var width = 990;
- var height = screen.height * 90 / 100;
- //console.log(url);
- //console.log(document.location);
- window.open(url, '', 'width=' + width.toString() + ',height=' + height.toString() + ',menubar=no,toolbar=no,personalbar=no,location=no,resizable=no,scrollbars=yes,status=no,chrome=yes,centerscreen=yes,attention=yes,dialog=yes');
- $('#printPreflightModal').modal('hide');
- }
- function printPage() {
- var print_is_rendering = true;
- $('#printModal').on('hide.bs.modal', function (e) {
- if (print_is_rendering === true) {
- e.preventDefault();
- return false;
- }
- return true;
- });
- $('#printModal').on('show.bs.modal', function () {
- var print_options = {
- stop_updates_when_focus_is_lost: false,
- update_only_visible: false,
- sync_selection: false,
- eliminate_zero_dimensions: false,
- pan_and_zoom_data_padding: false,
- show_help: false,
- legend_toolbox: false,
- resize_charts: false,
- pixels_per_point: 1
- };
- var x;
- for (x in print_options) {
- if (print_options.hasOwnProperty(x)) {
- NETDATA.options.current[x] = print_options[x];
- }
- }
- NETDATA.parseDom();
- showPageFooter();
- NETDATA.globalSelectionSync.stop();
- NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
- // NETDATA.onresize();
- var el = document.getElementById('printModalProgressBar');
- var eltxt = document.getElementById('printModalProgressBarText');
- function update_chart(idx) {
- var state = NETDATA.options.targets[--idx];
- var pcent = (NETDATA.options.targets.length - idx) * 100 / NETDATA.options.targets.length;
- $(el).css('width', pcent + '%').attr('aria-valuenow', pcent);
- eltxt.innerText = Math.round(pcent).toString() + '%, ' + state.id;
- setTimeout(function () {
- state.updateChart(function () {
- NETDATA.options.targets[idx].resizeForPrint();
- if (idx > 0) {
- update_chart(idx);
- } else {
- print_is_rendering = false;
- $('#printModal').modal('hide');
- window.print();
- window.close();
- }
- })
- }, 0);
- }
- print_is_rendering = true;
- update_chart(NETDATA.options.targets.length);
- });
- $('#printModal').modal('show');
- }
- // --------------------------------------------------------------------
- function jsonStringifyFn(obj) {
- return JSON.stringify(obj, function (key, value) {
- return (typeof value === 'function') ? value.toString() : value;
- });
- }
- function jsonParseFn(str) {
- return JSON.parse(str, function (key, value) {
- if (typeof value != 'string') {
- return value;
- }
- return (value.substring(0, 8) == 'function') ? eval('(' + value + ')') : value;
- });
- }
- // --------------------------------------------------------------------
- var snapshotOptions = {
- bytes_per_chart: 2048,
- compressionDefault: 'pako.deflate.base64',
- compressions: {
- 'none': {
- bytes_per_point_memory: 5.2,
- bytes_per_point_disk: 5.6,
- compress: function (s) {
- return s;
- },
- compressed_length: function (s) {
- return s.length;
- },
- uncompress: function (s) {
- return s;
- }
- },
- 'pako.deflate.base64': {
- bytes_per_point_memory: 1.8,
- bytes_per_point_disk: 1.9,
- compress: function (s) {
- return btoa(pako.deflate(s, { to: 'string' }));
- },
- compressed_length: function (s) {
- return s.length;
- },
- uncompress: function (s) {
- return pako.inflate(atob(s), { to: 'string' });
- }
- },
- 'pako.deflate': {
- bytes_per_point_memory: 1.4,
- bytes_per_point_disk: 3.2,
- compress: function (s) {
- return pako.deflate(s, { to: 'string' });
- },
- compressed_length: function (s) {
- return s.length;
- },
- uncompress: function (s) {
- return pako.inflate(s, { to: 'string' });
- }
- },
- 'lzstring.utf16': {
- bytes_per_point_memory: 1.7,
- bytes_per_point_disk: 2.6,
- compress: function (s) {
- return LZString.compressToUTF16(s);
- },
- compressed_length: function (s) {
- return s.length * 2;
- },
- uncompress: function (s) {
- return LZString.decompressFromUTF16(s);
- }
- },
- 'lzstring.base64': {
- bytes_per_point_memory: 2.1,
- bytes_per_point_disk: 2.3,
- compress: function (s) {
- return LZString.compressToBase64(s);
- },
- compressed_length: function (s) {
- return s.length;
- },
- uncompress: function (s) {
- return LZString.decompressFromBase64(s);
- }
- },
- 'lzstring.uri': {
- bytes_per_point_memory: 2.1,
- bytes_per_point_disk: 2.3,
- compress: function (s) {
- return LZString.compressToEncodedURIComponent(s);
- },
- compressed_length: function (s) {
- return s.length;
- },
- uncompress: function (s) {
- return LZString.decompressFromEncodedURIComponent(s);
- }
- }
- }
- };
- // --------------------------------------------------------------------
- // loading snapshots
- function loadSnapshotModalLog(priority, msg) {
- document.getElementById('loadSnapshotStatus').className = "alert alert-" + priority;
- document.getElementById('loadSnapshotStatus').innerHTML = msg;
- }
- var tmpSnapshotData = null;
- function loadSnapshot() {
- $('#loadSnapshotImport').addClass('disabled');
- if (tmpSnapshotData === null) {
- loadSnapshotPreflightEmpty();
- loadSnapshotModalLog('danger', 'no data have been loaded');
- return;
- }
- loadPako(function () {
- loadLzString(function () {
- loadSnapshotModalLog('info', 'Please wait, activating snapshot...');
- $('#loadSnapshotModal').modal('hide');
- netdataShowAlarms = false;
- netdataRegistry = false;
- netdataServer = tmpSnapshotData.server;
- NETDATA.serverDefault = netdataServer;
- document.getElementById('charts_div').innerHTML = '';
- document.getElementById('sidebar').innerHTML = '';
- NETDATA.globalReset();
- if (typeof tmpSnapshotData.hash !== 'undefined') {
- urlOptions.hash = tmpSnapshotData.hash;
- } else {
- urlOptions.hash = '#';
- }
- if (typeof tmpSnapshotData.info !== 'undefined') {
- var info = jsonParseFn(tmpSnapshotData.info);
- if (typeof info.menu !== 'undefined') {
- netdataDashboard.menu = info.menu;
- }
- if (typeof info.submenu !== 'undefined') {
- netdataDashboard.submenu = info.submenu;
- }
- if (typeof info.context !== 'undefined') {
- netdataDashboard.context = info.context;
- }
- }
- if (typeof tmpSnapshotData.compression !== 'string') {
- tmpSnapshotData.compression = 'none';
- }
- if (typeof snapshotOptions.compressions[tmpSnapshotData.compression] === 'undefined') {
- alert('unknown compression method: ' + tmpSnapshotData.compression);
- tmpSnapshotData.compression = 'none';
- }
- tmpSnapshotData.uncompress = snapshotOptions.compressions[tmpSnapshotData.compression].uncompress;
- netdataSnapshotData = tmpSnapshotData;
- urlOptions.after = tmpSnapshotData.after_ms;
- urlOptions.before = tmpSnapshotData.before_ms;
- if (typeof tmpSnapshotData.highlight_after_ms !== 'undefined'
- && tmpSnapshotData.highlight_after_ms !== null
- && tmpSnapshotData.highlight_after_ms > 0
- && typeof tmpSnapshotData.highlight_before_ms !== 'undefined'
- && tmpSnapshotData.highlight_before_ms !== null
- && tmpSnapshotData.highlight_before_ms > 0
- ) {
- urlOptions.highlight_after = tmpSnapshotData.highlight_after_ms;
- urlOptions.highlight_before = tmpSnapshotData.highlight_before_ms;
- urlOptions.highlight = true;
- } else {
- urlOptions.highlight_after = 0;
- urlOptions.highlight_before = 0;
- urlOptions.highlight = false;
- }
- netdataCheckXSS = false; // disable the modal - this does not affect XSS checks, since dashboard.js is already loaded
- NETDATA.xss.enabled = true; // we should not do any remote requests, but if we do, check them
- NETDATA.xss.enabled_for_data = true; // check also snapshot data - that have been excluded from the initial check, due to compression
- loadSnapshotPreflightEmpty();
- initializeDynamicDashboard();
- });
- });
- };
- function loadSnapshotPreflightFile(file) {
- var filename = NETDATA.xss.string(file.name);
- var fr = new FileReader();
- fr.onload = function (e) {
- document.getElementById('loadSnapshotFilename').innerHTML = filename;
- var result = null;
- try {
- result = NETDATA.xss.checkAlways('snapshot', JSON.parse(e.target.result), /^(snapshot\.info|snapshot\.data)$/);
- //console.log(result);
- var date_after = new Date(result.after_ms);
- var date_before = new Date(result.before_ms);
- if (typeof result.charts_ok === 'undefined') {
- result.charts_ok = 'unknown';
- }
- if (typeof result.charts_failed === 'undefined') {
- result.charts_failed = 0;
- }
- if (typeof result.compression === 'undefined') {
- result.compression = 'none';
- }
- if (typeof result.data_size === 'undefined') {
- result.data_size = 0;
- }
- document.getElementById('loadSnapshotFilename').innerHTML = '<code>' + filename + '</code>';
- document.getElementById('loadSnapshotHostname').innerHTML = '<b>' + result.hostname + '</b>, netdata version: <b>' + result.netdata_version.toString() + '</b>';
- document.getElementById('loadSnapshotURL').innerHTML = result.url;
- document.getElementById('loadSnapshotCharts').innerHTML = result.charts.charts_count.toString() + ' charts, ' + result.charts.dimensions_count.toString() + ' dimensions, ' + result.data_points.toString() + ' points per dimension, ' + Math.round(result.duration_ms / result.data_points).toString() + ' ms per point';
- document.getElementById('loadSnapshotInfo').innerHTML = 'version: <b>' + result.snapshot_version.toString() + '</b>, includes <b>' + result.charts_ok.toString() + '</b> unique chart data queries ' + ((result.charts_failed > 0) ? ('<b>' + result.charts_failed.toString() + '</b> failed') : '').toString() + ', compressed with <code>' + result.compression.toString() + '</code>, data size ' + (Math.round(result.data_size * 100 / 1024 / 1024) / 100).toString() + ' MB';
- document.getElementById('loadSnapshotTimeRange').innerHTML = '<b>' + NETDATA.dateTime.localeDateString(date_after) + ' ' + NETDATA.dateTime.localeTimeString(date_after) + '</b> to <b>' + NETDATA.dateTime.localeDateString(date_before) + ' ' + NETDATA.dateTime.localeTimeString(date_before) + '</b>';
- document.getElementById('loadSnapshotComments').innerHTML = ((result.comments) ? result.comments : '').toString();
- loadSnapshotModalLog('success', 'File loaded, click <b>Import</b> to render it!');
- $('#loadSnapshotImport').removeClass('disabled');
- tmpSnapshotData = result;
- }
- catch (e) {
- console.log(e);
- document.getElementById('loadSnapshotStatus').className = "alert alert-danger";
- document.getElementById('loadSnapshotStatus').innerHTML = "Failed to parse this file!";
- $('#loadSnapshotImport').addClass('disabled');
- }
- }
- //console.log(file);
- fr.readAsText(file);
- };
- function loadSnapshotPreflightEmpty() {
- document.getElementById('loadSnapshotFilename').innerHTML = '';
- document.getElementById('loadSnapshotHostname').innerHTML = '';
- document.getElementById('loadSnapshotURL').innerHTML = '';
- document.getElementById('loadSnapshotCharts').innerHTML = '';
- document.getElementById('loadSnapshotInfo').innerHTML = '';
- document.getElementById('loadSnapshotTimeRange').innerHTML = '';
- document.getElementById('loadSnapshotComments').innerHTML = '';
- loadSnapshotModalLog('success', 'Browse for a snapshot file (or drag it and drop it here), then click <b>Import</b> to render it.');
- $('#loadSnapshotImport').addClass('disabled');
- };
- var loadSnapshotDragAndDropInitialized = false;
- function loadSnapshotDragAndDropSetup() {
- if (loadSnapshotDragAndDropInitialized === false) {
- loadSnapshotDragAndDropInitialized = true;
- $('#loadSnapshotDragAndDrop')
- .on('drag dragstart dragend dragover dragenter dragleave drop', function (e) {
- e.preventDefault();
- e.stopPropagation();
- })
- .on('drop', function (e) {
- if (e.originalEvent.dataTransfer.files.length) {
- loadSnapshotPreflightFile(e.originalEvent.dataTransfer.files.item(0));
- } else {
- loadSnapshotPreflightEmpty();
- loadSnapshotModalLog('danger', 'No file selected');
- }
- });
- }
- };
- function loadSnapshotPreflight() {
- var files = document.getElementById('loadSnapshotSelectFiles').files;
- if (files.length <= 0) {
- loadSnapshotPreflightEmpty();
- loadSnapshotModalLog('danger', 'No file selected');
- return;
- }
- loadSnapshotModalLog('info', 'Loading file...');
- loadSnapshotPreflightFile(files.item(0));
- }
- // --------------------------------------------------------------------
- // saving snapshots
- var saveSnapshotStop = false;
- function saveSnapshotCancel() {
- saveSnapshotStop = true;
- }
- var saveSnapshotModalInitialized = false;
- function saveSnapshotModalSetup() {
- if (saveSnapshotModalInitialized === false) {
- saveSnapshotModalInitialized = true;
- $('#saveSnapshotModal')
- .on('hide.bs.modal', saveSnapshotCancel)
- .on('show.bs.modal', saveSnapshotModalInit)
- .on('shown.bs.modal', function () {
- $('#saveSnapshotResolutionSlider').find(".slider-handle:first").attr("tabindex", 1);
- document.getElementById('saveSnapshotComments').focus();
- });
- }
- };
- function saveSnapshotModalLog(priority, msg) {
- document.getElementById('saveSnapshotStatus').className = "alert alert-" + priority;
- document.getElementById('saveSnapshotStatus').innerHTML = msg;
- }
- function saveSnapshotModalShowExpectedSize() {
- var points = Math.round(saveSnapshotViewDuration / saveSnapshotSelectedSecondsPerPoint);
- var priority = 'info';
- var msg = 'A moderate snapshot.';
- var sizemb = Math.round(
- (options.data.charts_count * snapshotOptions.bytes_per_chart
- + options.data.dimensions_count * points * snapshotOptions.compressions[saveSnapshotCompression].bytes_per_point_disk)
- * 10 / 1024 / 1024) / 10;
- var memmb = Math.round(
- (options.data.charts_count * snapshotOptions.bytes_per_chart
- + options.data.dimensions_count * points * snapshotOptions.compressions[saveSnapshotCompression].bytes_per_point_memory)
- * 10 / 1024 / 1024) / 10;
- if (sizemb < 10) {
- priority = 'success';
- msg = 'A nice small snapshot!';
- }
- if (sizemb > 50) {
- priority = 'warning';
- msg = 'Will stress your browser...';
- }
- if (sizemb > 100) {
- priority = 'danger';
- msg = 'Hm... good luck...';
- }
- saveSnapshotModalLog(priority, 'The snapshot will have ' + points.toString() + ' points per dimension. Expected size on disk ' + sizemb + ' MB, at browser memory ' + memmb + ' MB.<br/>' + msg);
- }
- var saveSnapshotCompression = snapshotOptions.compressionDefault;
- function saveSnapshotSetCompression(name) {
- saveSnapshotCompression = name;
- document.getElementById('saveSnapshotCompressionName').innerHTML = saveSnapshotCompression;
- saveSnapshotModalShowExpectedSize();
- }
- var saveSnapshotSlider = null;
- var saveSnapshotSelectedSecondsPerPoint = 1;
- var saveSnapshotViewDuration = 1;
- function saveSnapshotModalInit() {
- $('#saveSnapshotModalProgressSection').hide();
- $('#saveSnapshotResolutionRadio').show();
- saveSnapshotModalLog('info', 'Select resolution and click <b>Save</b>');
- $('#saveSnapshotExport').removeClass('disabled');
- loadBootstrapSlider(function () {
- saveSnapshotViewDuration = options.duration;
- var start_ms = Math.round(Date.now() - saveSnapshotViewDuration * 1000);
- if (NETDATA.globalPanAndZoom.isActive() === true) {
- saveSnapshotViewDuration = Math.round((NETDATA.globalPanAndZoom.force_before_ms - NETDATA.globalPanAndZoom.force_after_ms) / 1000);
- start_ms = NETDATA.globalPanAndZoom.force_after_ms;
- }
- var start_date = new Date(start_ms);
- var yyyymmddhhssmm = start_date.getFullYear() + NETDATA.zeropad(start_date.getMonth() + 1) + NETDATA.zeropad(start_date.getDate()) + '-' + NETDATA.zeropad(start_date.getHours()) + NETDATA.zeropad(start_date.getMinutes()) + NETDATA.zeropad(start_date.getSeconds());
- document.getElementById('saveSnapshotFilename').value = 'netdata-' + options.hostname.toString() + '-' + yyyymmddhhssmm.toString() + '-' + saveSnapshotViewDuration.toString() + '.snapshot';
- saveSnapshotSetCompression(saveSnapshotCompression);
- var min = options.update_every;
- var max = Math.round(saveSnapshotViewDuration / 100);
- if (NETDATA.globalPanAndZoom.isActive() === false) {
- max = Math.round(saveSnapshotViewDuration / 50);
- }
- var view = Math.round(saveSnapshotViewDuration / Math.round($(document.getElementById('charts_div')).width() / 2));
- // console.log('view duration: ' + saveSnapshotViewDuration + ', min: ' + min + ', max: ' + max + ', view: ' + view);
- if (max < 10) {
- max = 10;
- }
- if (max < min) {
- max = min;
- }
- if (view < min) {
- view = min;
- }
- if (view > max) {
- view = max;
- }
- if (saveSnapshotSlider !== null) {
- saveSnapshotSlider.destroy();
- }
- saveSnapshotSlider = new Slider('#saveSnapshotResolutionSlider', {
- ticks: [min, view, max],
- min: min,
- max: max,
- step: options.update_every,
- value: view,
- scale: (max > 100) ? 'logarithmic' : 'linear',
- tooltip: 'always',
- formatter: function (value) {
- if (value < 1) {
- value = 1;
- }
- if (value < options.data.update_every) {
- value = options.data.update_every;
- }
- saveSnapshotSelectedSecondsPerPoint = value;
- saveSnapshotModalShowExpectedSize();
- var seconds = ' seconds ';
- if (value === 1) {
- seconds = ' second ';
- }
- return value + seconds + 'per point' + ((value === options.data.update_every) ? ', server default' : '').toString();
- }
- });
- });
- }
- function saveSnapshot() {
- loadPako(function () {
- loadLzString(function () {
- saveSnapshotStop = false;
- $('#saveSnapshotModalProgressSection').show();
- $('#saveSnapshotResolutionRadio').hide();
- $('#saveSnapshotExport').addClass('disabled');
- var filename = document.getElementById('saveSnapshotFilename').value;
- // console.log(filename);
- saveSnapshotModalLog('info', 'Generating snapshot as <code>' + filename.toString() + '</code>');
- var save_options = {
- stop_updates_when_focus_is_lost: false,
- update_only_visible: false,
- sync_selection: false,
- eliminate_zero_dimensions: true,
- pan_and_zoom_data_padding: false,
- show_help: false,
- legend_toolbox: false,
- resize_charts: false,
- pixels_per_point: 1
- };
- var backedup_options = {};
- var x;
- for (x in save_options) {
- if (save_options.hasOwnProperty(x)) {
- backedup_options[x] = NETDATA.options.current[x];
- NETDATA.options.current[x] = save_options[x];
- }
- }
- var el = document.getElementById('saveSnapshotModalProgressBar');
- var eltxt = document.getElementById('saveSnapshotModalProgressBarText');
- options.data.charts_by_name = null;
- var saveData = {
- hostname: options.hostname,
- server: NETDATA.serverDefault,
- netdata_version: options.data.version,
- snapshot_version: 1,
- after_ms: Date.now() - options.duration * 1000,
- before_ms: Date.now(),
- highlight_after_ms: urlOptions.highlight_after,
- highlight_before_ms: urlOptions.highlight_before,
- duration_ms: options.duration * 1000,
- update_every_ms: options.update_every * 1000,
- data_points: 0,
- url: ((urlOptions.server !== null) ? urlOptions.server : document.location.origin.toString() + document.location.pathname.toString() + document.location.search.toString()).toString(),
- comments: document.getElementById('saveSnapshotComments').value.toString(),
- hash: urlOptions.hash,
- charts: options.data,
- info: jsonStringifyFn({
- menu: netdataDashboard.menu,
- submenu: netdataDashboard.submenu,
- context: netdataDashboard.context
- }),
- charts_ok: 0,
- charts_failed: 0,
- compression: saveSnapshotCompression,
- data_size: 0,
- data: {}
- };
- if (typeof snapshotOptions.compressions[saveData.compression] === 'undefined') {
- alert('unknown compression method: ' + saveData.compression);
- saveData.compression = 'none';
- }
- var compress = snapshotOptions.compressions[saveData.compression].compress;
- var compressed_length = snapshotOptions.compressions[saveData.compression].compressed_length;
- function pack_api1_v1_chart_data(state) {
- if (state.library_name === null || state.data === null) {
- return;
- }
- var data = state.data;
- state.data = null;
- data.state = null;
- var str = JSON.stringify(data);
- if (typeof str === 'string') {
- var cstr = compress(str);
- saveData.data[state.chartDataUniqueID()] = cstr;
- return compressed_length(cstr);
- } else {
- return 0;
- }
- }
- var clearPanAndZoom = false;
- if (NETDATA.globalPanAndZoom.isActive() === false) {
- NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], saveData.after_ms, saveData.before_ms);
- clearPanAndZoom = true;
- }
- saveData.after_ms = NETDATA.globalPanAndZoom.force_after_ms;
- saveData.before_ms = NETDATA.globalPanAndZoom.force_before_ms;
- saveData.duration_ms = saveData.before_ms - saveData.after_ms;
- saveData.data_points = Math.round((saveData.before_ms - saveData.after_ms) / (saveSnapshotSelectedSecondsPerPoint * 1000));
- saveSnapshotModalLog('info', 'Generating snapshot with ' + saveData.data_points.toString() + ' data points per dimension...');
- var charts_count = 0;
- var charts_ok = 0;
- var charts_failed = 0;
- function saveSnapshotRestore() {
- $('#saveSnapshotModal').modal('hide');
- // restore the options
- var x;
- for (x in backedup_options) {
- if (backedup_options.hasOwnProperty(x)) {
- NETDATA.options.current[x] = backedup_options[x];
- }
- }
- $(el).css('width', '0%').attr('aria-valuenow', 0);
- eltxt.innerText = '0%';
- if (clearPanAndZoom) {
- NETDATA.globalPanAndZoom.clearMaster();
- }
- NETDATA.options.force_data_points = 0;
- NETDATA.options.fake_chart_rendering = false;
- NETDATA.onscroll_updater_enabled = true;
- NETDATA.onresize();
- NETDATA.unpause();
- $('#saveSnapshotExport').removeClass('disabled');
- }
- NETDATA.globalSelectionSync.stop();
- NETDATA.options.force_data_points = saveData.data_points;
- NETDATA.options.fake_chart_rendering = true;
- NETDATA.onscroll_updater_enabled = false;
- NETDATA.abortAllRefreshes();
- var size = 0;
- var info = ' Resolution: <b>' + saveSnapshotSelectedSecondsPerPoint.toString() + ((saveSnapshotSelectedSecondsPerPoint === 1) ? ' second ' : ' seconds ').toString() + 'per point</b>.';
- function update_chart(idx) {
- if (saveSnapshotStop === true) {
- saveSnapshotModalLog('info', 'Cancelled!');
- saveSnapshotRestore();
- return;
- }
- var state = NETDATA.options.targets[--idx];
- var pcent = (NETDATA.options.targets.length - idx) * 100 / NETDATA.options.targets.length;
- $(el).css('width', pcent + '%').attr('aria-valuenow', pcent);
- eltxt.innerText = Math.round(pcent).toString() + '%, ' + state.id;
- setTimeout(function () {
- charts_count++;
- state.isVisible(true);
- state.current.force_after_ms = saveData.after_ms;
- state.current.force_before_ms = saveData.before_ms;
- state.updateChart(function (status, reason) {
- state.current.force_after_ms = null;
- state.current.force_before_ms = null;
- if (status === true) {
- charts_ok++;
- // state.log('ok');
- size += pack_api1_v1_chart_data(state);
- } else {
- charts_failed++;
- state.log('failed to be updated: ' + reason);
- }
- saveSnapshotModalLog((charts_failed) ? 'danger' : 'info', 'Generated snapshot data size <b>' + (Math.round(size * 100 / 1024 / 1024) / 100).toString() + ' MB</b>. ' + ((charts_failed) ? (charts_failed.toString() + ' charts have failed to be downloaded') : '').toString() + info);
- if (idx > 0) {
- update_chart(idx);
- } else {
- saveData.charts_ok = charts_ok;
- saveData.charts_failed = charts_failed;
- saveData.data_size = size;
- // console.log(saveData.compression + ': ' + (size / (options.data.dimensions_count * Math.round(saveSnapshotViewDuration / saveSnapshotSelectedSecondsPerPoint))).toString());
- // save it
- // console.log(saveData);
- saveObjectToClient(saveData, filename);
- if (charts_failed > 0) {
- alert(charts_failed.toString() + ' failed to be downloaded');
- }
- saveSnapshotRestore();
- saveData = null;
- }
- })
- }, 0);
- }
- update_chart(NETDATA.options.targets.length);
- });
- });
- }
- // --------------------------------------------------------------------
- // activate netdata on the page
- function dashboardSettingsSetup() {
- var update_options_modal = function () {
- // console.log('update_options_modal');
- var sync_option = function (option) {
- var self = $('#' + option);
- if (self.prop('checked') !== NETDATA.getOption(option)) {
- // console.log('switching ' + option.toString());
- self.bootstrapToggle(NETDATA.getOption(option) ? 'on' : 'off');
- }
- };
- var theme_sync_option = function (option) {
- var self = $('#' + option);
- self.bootstrapToggle(netdataTheme === 'slate' ? 'on' : 'off');
- };
- var units_sync_option = function (option) {
- var self = $('#' + option);
- if (self.prop('checked') !== (NETDATA.getOption('units') === 'auto')) {
- self.bootstrapToggle(NETDATA.getOption('units') === 'auto' ? 'on' : 'off');
- }
- if (self.prop('checked') === true) {
- $('#settingsLocaleTempRow').show();
- $('#settingsLocaleTimeRow').show();
- } else {
- $('#settingsLocaleTempRow').hide();
- $('#settingsLocaleTimeRow').hide();
- }
- };
- var temp_sync_option = function (option) {
- var self = $('#' + option);
- if (self.prop('checked') !== (NETDATA.getOption('temperature') === 'celsius')) {
- self.bootstrapToggle(NETDATA.getOption('temperature') === 'celsius' ? 'on' : 'off');
- }
- };
- var timezone_sync_option = function (option) {
- var self = $('#' + option);
- document.getElementById('browser_timezone').innerText = NETDATA.options.browser_timezone;
- document.getElementById('server_timezone').innerText = NETDATA.options.server_timezone;
- document.getElementById('current_timezone').innerText = (NETDATA.options.current.timezone === 'default') ? 'unset, using browser default' : NETDATA.options.current.timezone;
- if (self.prop('checked') === NETDATA.dateTime.using_timezone) {
- self.bootstrapToggle(NETDATA.dateTime.using_timezone ? 'off' : 'on');
- }
- };
- sync_option('eliminate_zero_dimensions');
- sync_option('destroy_on_hide');
- sync_option('async_on_scroll');
- sync_option('parallel_refresher');
- sync_option('concurrent_refreshes');
- sync_option('sync_selection');
- sync_option('sync_pan_and_zoom');
- sync_option('stop_updates_when_focus_is_lost');
- sync_option('smooth_plot');
- sync_option('pan_and_zoom_data_padding');
- sync_option('show_help');
- sync_option('seconds_as_time');
- theme_sync_option('netdata_theme_control');
- units_sync_option('units_conversion');
- temp_sync_option('units_temp');
- timezone_sync_option('local_timezone');
- if (NETDATA.getOption('parallel_refresher') === false) {
- $('#concurrent_refreshes_row').hide();
- } else {
- $('#concurrent_refreshes_row').show();
- }
- };
- NETDATA.setOption('setOptionCallback', update_options_modal);
- // handle options changes
- $('#eliminate_zero_dimensions').change(function () {
- NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked'));
- });
- $('#destroy_on_hide').change(function () {
- NETDATA.setOption('destroy_on_hide', $(this).prop('checked'));
- });
- $('#async_on_scroll').change(function () {
- NETDATA.setOption('async_on_scroll', $(this).prop('checked'));
- });
- $('#parallel_refresher').change(function () {
- NETDATA.setOption('parallel_refresher', $(this).prop('checked'));
- });
- $('#concurrent_refreshes').change(function () {
- NETDATA.setOption('concurrent_refreshes', $(this).prop('checked'));
- });
- $('#sync_selection').change(function () {
- NETDATA.setOption('sync_selection', $(this).prop('checked'));
- });
- $('#sync_pan_and_zoom').change(function () {
- NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked'));
- });
- $('#stop_updates_when_focus_is_lost').change(function () {
- urlOptions.update_always = !$(this).prop('checked');
- urlOptions.hashUpdate();
- NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
- });
- $('#smooth_plot').change(function () {
- NETDATA.setOption('smooth_plot', $(this).prop('checked'));
- });
- $('#pan_and_zoom_data_padding').change(function () {
- NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked'));
- });
- $('#seconds_as_time').change(function () {
- NETDATA.setOption('seconds_as_time', $(this).prop('checked'));
- });
- $('#local_timezone').change(function () {
- if ($(this).prop('checked')) {
- selected_server_timezone('default', true);
- } else {
- selected_server_timezone('default', false);
- }
- });
- $('#units_conversion').change(function () {
- NETDATA.setOption('units', $(this).prop('checked') ? 'auto' : 'original');
- });
- $('#units_temp').change(function () {
- NETDATA.setOption('temperature', $(this).prop('checked') ? 'celsius' : 'fahrenheit');
- });
- $('#show_help').change(function () {
- urlOptions.help = $(this).prop('checked');
- urlOptions.hashUpdate();
- NETDATA.setOption('show_help', urlOptions.help);
- netdataReload();
- });
- // this has to be the last
- // it reloads the page
- $('#netdata_theme_control').change(function () {
- urlOptions.theme = $(this).prop('checked') ? 'slate' : 'white';
- urlOptions.hashUpdate();
- if (setTheme(urlOptions.theme)) {
- netdataReload();
- }
- });
- }
- function scrollDashboardTo() {
- if (netdataSnapshotData !== null && typeof netdataSnapshotData.hash !== 'undefined') {
- //console.log(netdataSnapshotData.hash);
- scrollToId(netdataSnapshotData.hash.replace('#', ''));
- } else {
- // check if we have to jump to a specific section
- scrollToId(urlOptions.hash.replace('#', ''));
- if (urlOptions.chart !== null) {
- NETDATA.alarms.scrollToChart(urlOptions.chart);
- //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
- //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
- //console.log('hash = ' + urlOptions.hash);
- }
- }
- }
- var modalHiddenCallback = null;
- function scrollToChartAfterHidingModal(chart, alarmDate, alarmStatus) {
- modalHiddenCallback = function () {
- NETDATA.alarms.scrollToChart(chart, alarmDate);
- if (['WARNING', 'CRITICAL'].includes(alarmStatus)) {
- const currentChartState = NETDATA.options.targets.find(
- (chartState) => chartState.id === chart,
- )
- const twoMinutes = 2 * 60 * 1000
- NETDATA.globalPanAndZoom.setMaster(
- currentChartState,
- alarmDate - twoMinutes,
- alarmDate + twoMinutes,
- )
- }
- };
- }
- // ----------------------------------------------------------------------------
- function enableTooltipsAndPopovers() {
- $('[data-toggle="tooltip"]').tooltip({
- animated: 'fade',
- trigger: 'hover',
- html: true,
- delay: { show: 500, hide: 0 },
- container: 'body'
- });
- $('[data-toggle="popover"]').popover();
- }
- // ----------------------------------------------------------------------------
- var runOnceOnDashboardLastRun = 0;
- function runOnceOnDashboardWithjQuery() {
- if (runOnceOnDashboardLastRun !== 0) {
- scrollDashboardTo();
- // restore the scrollspy at the proper position
- $(document.body).scrollspy('refresh');
- $(document.body).scrollspy('process');
- return;
- }
- runOnceOnDashboardLastRun = Date.now();
- // ------------------------------------------------------------------------
- // bootstrap modals
- // prevent bootstrap modals from scrolling the page
- // maintains the current scroll position
- // https://stackoverflow.com/a/34754029/4525767
- var scrollPos = 0;
- var modal_depth = 0; // how many modals are currently open
- var modal_shown = false; // set to true, if a modal is shown
- var netdata_paused_on_modal = false; // set to true, if the modal paused netdata
- var scrollspyOffset = $(window).height() / 3; // will be updated below - the offset of scrollspy to select an item
- $('.modal')
- .on('show.bs.modal', function () {
- if (modal_depth === 0) {
- scrollPos = window.scrollY;
- $('body').css({
- overflow: 'hidden',
- position: 'fixed',
- top: -scrollPos
- });
- modal_shown = true;
- if (NETDATA.options.pauseCallback === null) {
- NETDATA.pause(function () {
- });
- netdata_paused_on_modal = true;
- } else {
- netdata_paused_on_modal = false;
- }
- }
- modal_depth++;
- //console.log(urlOptions.after);
- })
- .on('hide.bs.modal', function () {
- modal_depth--;
- if (modal_depth <= 0) {
- modal_depth = 0;
- $('body')
- .css({
- overflow: '',
- position: '',
- top: ''
- });
- // scroll to the position we had open before the modal
- $('html, body')
- .animate({ scrollTop: scrollPos }, 0);
- // unpause netdata, if we paused it
- if (netdata_paused_on_modal === true) {
- NETDATA.unpause();
- netdata_paused_on_modal = false;
- }
- // restore the scrollspy at the proper position
- $(document.body).scrollspy('process');
- }
- //console.log(urlOptions.after);
- })
- .on('hidden.bs.modal', function () {
- if (modal_depth === 0) {
- modal_shown = false;
- }
- if (typeof modalHiddenCallback === 'function') {
- modalHiddenCallback();
- }
- modalHiddenCallback = null;
- //console.log(urlOptions.after);
- });
- // ------------------------------------------------------------------------
- // sidebar / affix
- if (shouldShowSignInBanner()) {
- const el = document.getElementById("sign-in-banner");
- if (el) {
- el.style.display = "initial";
- el.classList.add(`theme-${netdataTheme}`);
- }
- }
- $('#sidebar')
- .affix({
- offset: {
- top: (isdemo()) ? 150 : 0,
- bottom: 0
- }
- })
- .on('affixed.bs.affix', function () {
- // fix scrolling of very long affix lists
- // http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
- $(this).removeAttr('style');
- })
- .on('affix-top.bs.affix', function () {
- // fix bootstrap affix click bug
- // https://stackoverflow.com/a/37847981/4525767
- if (modal_shown) {
- return false;
- }
- })
- .on('activate.bs.scrollspy', function (e) {
- // change the URL based on the current position of the screen
- if (modal_shown === false) {
- var el = $(e.target);
- var hash = el.find('a').attr('href');
- if (typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
- urlOptions.hash = hash;
- urlOptions.hashUpdate();
- }
- }
- });
- Ps.initialize(document.getElementById('sidebar'), {
- wheelSpeed: 0.5,
- wheelPropagation: true,
- swipePropagation: true,
- minScrollbarLength: null,
- maxScrollbarLength: null,
- useBothWheelAxes: false,
- suppressScrollX: true,
- suppressScrollY: false,
- scrollXMarginOffset: 0,
- scrollYMarginOffset: 0,
- theme: 'default'
- });
- // ------------------------------------------------------------------------
- // scrollspy
- if (scrollspyOffset > 250) {
- scrollspyOffset = 250;
- }
- if (scrollspyOffset < 75) {
- scrollspyOffset = 75;
- }
- document.body.setAttribute('data-offset', scrollspyOffset);
- // scroll the dashboard, before activating the scrollspy, so that our
- // hash will not be updated before we got the chance to scroll to it
- scrollDashboardTo();
- $(document.body).scrollspy({
- target: '#sidebar',
- offset: scrollspyOffset // controls the diff of the <hX> element to the top, to select it
- });
- // ------------------------------------------------------------------------
- // my-netdata menu
- Ps.initialize(document.getElementById('my-netdata-dropdown-content'), {
- wheelSpeed: 1,
- wheelPropagation: false,
- swipePropagation: false,
- minScrollbarLength: null,
- maxScrollbarLength: null,
- useBothWheelAxes: false,
- suppressScrollX: true,
- suppressScrollY: false,
- scrollXMarginOffset: 0,
- scrollYMarginOffset: 0,
- theme: 'default'
- });
- $('#myNetdataDropdownParent')
- .on('show.bs.dropdown', function () {
- var hash = urlOptions.genHash();
- $('.registry_link').each(function (idx) {
- this.setAttribute('href', this.getAttribute("href").replace(/#.*$/, hash));
- });
- NETDATA.pause(function () {
- });
- })
- .on('shown.bs.dropdown', function () {
- Ps.update(document.getElementById('my-netdata-dropdown-content'));
- myNetdataMenuDidShow();
- })
- .on('hidden.bs.dropdown', function () {
- NETDATA.unpause();
- });
- $('#deleteRegistryModal')
- .on('hidden.bs.modal', function () {
- deleteRegistryGuid = null;
- });
- // ------------------------------------------------------------------------
- // update modal
- $('#updateModal')
- .on('show.bs.modal', function () {
- versionLog('checking, please wait...');
- })
- .on('shown.bs.modal', function () {
- notifyForUpdate(true);
- });
- // ------------------------------------------------------------------------
- // alarms modal
- $('#alarmsModal')
- .on('shown.bs.modal', function () {
- alarmsUpdateModal();
- })
- .on('hidden.bs.modal', function () {
- document.getElementById('alarms_active').innerHTML =
- document.getElementById('alarms_all').innerHTML =
- document.getElementById('alarms_log').innerHTML =
- 'loading...';
- });
- // ------------------------------------------------------------------------
- dashboardSettingsSetup();
- loadSnapshotDragAndDropSetup();
- saveSnapshotModalSetup();
- showPageFooter();
- // ------------------------------------------------------------------------
- // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
- $.fn.shorten = function (settings) {
- "use strict";
- var config = {
- showChars: 750,
- minHideChars: 10,
- ellipsesText: "...",
- moreText: '<i class="fas fa-expand"></i> show more information',
- lessText: '<i class="fas fa-compress"></i> show less information',
- onLess: function () {
- NETDATA.onscroll();
- },
- onMore: function () {
- NETDATA.onscroll();
- },
- errMsg: null,
- force: false
- };
- if (settings) {
- $.extend(config, settings);
- }
- if ($(this).data('jquery.shorten') && !config.force) {
- return false;
- }
- $(this).data('jquery.shorten', true);
- $(document).off("click", '.morelink');
- $(document).on({
- click: function () {
- var $this = $(this);
- if ($this.hasClass('less')) {
- $this.removeClass('less');
- $this.html(config.moreText);
- $this.parent().prev().animate({ 'height': '0' + '%' }, 0, function () {
- $this.parent().prev().prev().show();
- }).hide(0, function () {
- config.onLess();
- });
- } else {
- $this.addClass('less');
- $this.html(config.lessText);
- $this.parent().prev().animate({ 'height': '100' + '%' }, 0, function () {
- $this.parent().prev().prev().hide();
- }).show(0, function () {
- config.onMore();
- });
- }
- return false;
- }
- }, '.morelink');
- return this.each(function () {
- var $this = $(this);
- var content = $this.html();
- var contentlen = $this.text().length;
- if (contentlen > config.showChars + config.minHideChars) {
- var c = content.substr(0, config.showChars);
- if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
- {
- var inTag = false; // I'm in a tag?
- var bag = ''; // Put the characters to be shown here
- var countChars = 0; // Current bag size
- var openTags = []; // Stack for opened tags, so I can close them later
- var tagName = null;
- for (var i = 0, r = 0; r <= config.showChars; i++) {
- if (content[i] === '<' && !inTag) {
- inTag = true;
- // This could be "tag" or "/tag"
- tagName = content.substring(i + 1, content.indexOf('>', i));
- // If its a closing tag
- if (tagName[0] === '/') {
- if (tagName !== ('/' + openTags[0])) {
- config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
- } else {
- openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
- }
- } else {
- // There are some nasty tags that don't have a close tag like <br/>
- if (tagName.toLowerCase() !== 'br') {
- openTags.unshift(tagName); // Add to start the name of the tag that opens
- }
- }
- }
- if (inTag && content[i] === '>') {
- inTag = false;
- }
- if (inTag) {
- bag += content.charAt(i);
- } else {
- // Add tag name chars to the result
- r++;
- if (countChars <= config.showChars) {
- bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
- countChars++;
- } else {
- // Now I have the characters needed
- if (openTags.length > 0) {
- // I have unclosed tags
- //console.log('They were open tags');
- //console.log(openTags);
- for (var j = 0; j < openTags.length; j++) {
- //console.log('Cierro tag ' + openTags[j]);
- bag += '</' + openTags[j] + '>'; // Close all tags that were opened
- // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags
- }
- break;
- }
- }
- }
- }
- c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
- } else {
- c += config.ellipsesText;
- }
- var html = '<div class="shortcontent">' + c +
- '</div><div class="allcontent">' + content +
- '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
- $this.html(html);
- $this.find(".allcontent").hide(); // Hide all text
- $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
- }
- });
- };
- }
- function finalizePage() {
- // resize all charts - without starting the background thread
- // this has to be done while NETDATA is paused
- // if we omit this, the affix menu will be wrong, since all
- // the Dom elements are initially zero-sized
- NETDATA.parseDom();
- // ------------------------------------------------------------------------
- NETDATA.globalPanAndZoom.callback = null;
- NETDATA.globalChartUnderlay.callback = null;
- if (urlOptions.pan_and_zoom === true && NETDATA.options.targets.length > 0) {
- NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
- }
- // callback for us to track PanAndZoom operations
- NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback;
- NETDATA.globalChartUnderlay.callback = urlOptions.netdataHighlightCallback;
- // ------------------------------------------------------------------------
- // let it run (update the charts)
- NETDATA.unpause();
- runOnceOnDashboardWithjQuery();
- $(".shorten").shorten();
- enableTooltipsAndPopovers();
- if (isdemo()) {
- // do not to give errors on netdata demo servers for 60 seconds
- NETDATA.options.current.retries_on_data_failures = 60;
- // google analytics when this is used for the home page of the demo sites
- // this does not run on user's installations
- setTimeout(function () {
- (function (i, s, o, g, r, a, m) {
- i['GoogleAnalyticsObject'] = r;
- i[r] = i[r] || function () {
- (i[r].q = i[r].q || []).push(arguments)
- }, i[r].l = 1 * new Date();
- a = s.createElement(o),
- m = s.getElementsByTagName(o)[0];
- a.async = 1;
- a.src = g;
- m.parentNode.insertBefore(a, m)
- })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
- ga('create', 'UA-64295674-3', 'auto');
- ga('send', 'pageview', '/demosite/' + window.location.host);
- }, 2000);
- } else {
- notifyForUpdate();
- }
- if (urlOptions.show_alarms === true) {
- setTimeout(function () {
- $('#alarmsModal').modal('show');
- }, 1000);
- }
- NETDATA.onresizeCallback = function () {
- Ps.update(document.getElementById('sidebar'));
- Ps.update(document.getElementById('my-netdata-dropdown-content'));
- };
- NETDATA.onresizeCallback();
- if (netdataSnapshotData !== null) {
- NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], netdataSnapshotData.after_ms, netdataSnapshotData.before_ms);
- }
- //if (urlOptions.nowelcome !== true) {
- // setTimeout(function () {
- // $('#welcomeModal').modal();
- // }, 2000);
- //}
- // var netdataEnded = performance.now();
- // console.log('start up time: ' + (netdataEnded - netdataStarted).toString() + ' ms');
- }
- function resetDashboardOptions() {
- var help = NETDATA.options.current.show_help;
- NETDATA.resetOptions();
- if (setTheme('slate')) {
- netdataReload();
- }
- if (help !== NETDATA.options.current.show_help) {
- netdataReload();
- }
- }
- // callback to add the dashboard info to the
- // parallel javascript downloader in netdata
- var netdataPrepCallback = function () {
- NETDATA.requiredCSS.push({
- url: NETDATA.serverStatic + 'css/bootstrap-toggle-2.2.2.min.css',
- isAlreadyLoaded: function () {
- return false;
- }
- });
- NETDATA.requiredJs.push({
- url: NETDATA.serverStatic + 'lib/bootstrap-toggle-2.2.2.min.js',
- isAlreadyLoaded: function () {
- return false;
- }
- });
- NETDATA.requiredJs.push({
- url: NETDATA.serverStatic + 'dashboard_info.js?v20181019-1',
- async: false,
- isAlreadyLoaded: function () {
- return false;
- }
- });
- if (isdemo()) {
- document.getElementById('masthead').style.display = 'block';
- } else {
- if (urlOptions.update_always === true) {
- NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
- }
- }
- };
- var selected_server_timezone = function (timezone, status) {
- //console.log('called with timezone: ' + timezone + ", status: " + ((typeof status === 'undefined')?'undefined':status).toString());
- // clear the error
- document.getElementById('timezone_error_message').innerHTML = '';
- if (typeof status === 'undefined') {
- // the user selected a timezone from the menu
- NETDATA.setOption('user_set_server_timezone', timezone);
- if (NETDATA.dateTime.init(timezone) === false) {
- NETDATA.dateTime.init();
- if (!$('#local_timezone').prop('checked')) {
- $('#local_timezone').bootstrapToggle('on');
- }
- document.getElementById('timezone_error_message').innerHTML = 'Ooops! That timezone was not accepted by your browser. Please open a github issue to help us fix it.';
- NETDATA.setOption('user_set_server_timezone', NETDATA.options.server_timezone);
- } else {
- if ($('#local_timezone').prop('checked')) {
- $('#local_timezone').bootstrapToggle('off');
- }
- }
- } else if (status === true) {
- // the user wants the browser default timezone to be activated
- NETDATA.dateTime.init();
- } else {
- // the user wants the server default timezone to be activated
- //console.log('found ' + NETDATA.options.current.user_set_server_timezone);
- if (NETDATA.options.current.user_set_server_timezone === 'default') {
- NETDATA.options.current.user_set_server_timezone = NETDATA.options.server_timezone;
- }
- timezone = NETDATA.options.current.user_set_server_timezone;
- if (NETDATA.dateTime.init(timezone) === false) {
- NETDATA.dateTime.init();
- if (!$('#local_timezone').prop('checked')) {
- $('#local_timezone').bootstrapToggle('on');
- }
- document.getElementById('timezone_error_message').innerHTML = 'Sorry. The timezone "' + timezone.toString() + '" is not accepted by your browser. Please select one from the list.';
- NETDATA.setOption('user_set_server_timezone', NETDATA.options.server_timezone);
- }
- }
- document.getElementById('current_timezone').innerText = (NETDATA.options.current.timezone === 'default') ? 'unset, using browser default' : NETDATA.options.current.timezone;
- return false;
- };
- // our entry point
- // var netdataStarted = performance.now();
- var netdataCallback = initializeDynamicDashboard;
- // =================================================================================================
- // netdata.cloud
- let registryAgents = [];
- let cloudAgents = [];
- let myNetdataMenuFilterValue = "";
- let cloudAccountID = null;
- let cloudAccountName = null;
- let cloudToken = null;
- /// Enforces a maximum string length while retaining the prefix and the postfix of
- /// the string.
- function truncateString(str, maxLength) {
- if (str.length <= maxLength) {
- return str;
- }
- const spanLength = Math.floor((maxLength - 3) / 2);
- return `${str.substring(0, spanLength)}...${str.substring(str.length - spanLength)}`;
- }
- // -------------------------------------------------------------------------------------------------
- // netdata.cloud API Client
- // -------------------------------------------------------------------------------------------------
- function isValidAgent(a) {
- return a.urls != null && a.urls.length > 0;
- }
- // https://github.com/netdata/hub/issues/146
- function getCloudAccountAgents() {
- if (!isSignedIn()) {
- return [];
- }
- return fetch(
- `${NETDATA.registry.cloudBaseURL}/api/v1/accounts/${cloudAccountID}/agents`,
- {
- method: "GET",
- mode: "cors",
- headers: {
- "Authorization": `Bearer ${cloudToken}`
- }
- }
- ).then((response) => {
- if (!response.ok) {
- throw Error("Cannot fetch known accounts");
- }
- return response.json();
- }).then((payload) => {
- const agents = payload.result ? payload.result.agents : null;
- if (!agents) {
- return [];
- }
- return agents.filter((a) => isValidAgent(a)).map((a) => {
- return {
- "guid": a.id,
- "name": a.name,
- "url": a.urls[0],
- "alternate_urls": a.urls
- }
- })
- }).catch(function (error) {
- console.log(error);
- return null;
- });
- }
- /** Updates the lastAccessTime and accessCount properties of the agent for the account. */
- function touchAgent() {
- if (!isSignedIn()) {
- return [];
- }
- const touchUrl = `${NETDATA.registry.cloudBaseURL}/api/v1/agents/${NETDATA.registry.machine_guid}/touch?account_id=${cloudAccountID}`;
- return fetch(
- touchUrl,
- {
- method: "post",
- body: "",
- mode: "cors",
- headers: {
- "Authorization": `Bearer ${cloudToken}`
- }
- }
- ).then((response) => {
- if (!response.ok) {
- throw Error("Cannot touch agent" + JSON.stringify(response));
- }
- return response.json();
- }).then((payload) => {
- }).catch(function (error) {
- console.log(error);
- return null;
- });
- }
- // https://github.com/netdata/hub/issues/128
- function postCloudAccountAgents(agentsToSync) {
- if (!isSignedIn()) {
- return [];
- }
- const maskedURL = NETDATA.registry.MASKED_DATA;
- const agents = agentsToSync.map((a) => {
- const urls = a.alternate_urls.filter((url) => url != maskedURL);
- return {
- "id": a.guid,
- "name": a.name,
- "urls": urls
- }
- }).filter((a) => isValidAgent(a))
- const payload = {
- "accountID": cloudAccountID,
- "agents": agents,
- "merge": false,
- };
- return fetch(
- `${NETDATA.registry.cloudBaseURL}/api/v1/accounts/${cloudAccountID}/agents`,
- {
- method: "POST",
- mode: "cors",
- headers: {
- "Content-Type": "application/json; charset=utf-8",
- "Authorization": `Bearer ${cloudToken}`
- },
- body: JSON.stringify(payload)
- }
- ).then((response) => {
- return response.json();
- }).then((payload) => {
- const agents = payload.result ? payload.result.agents : null;
- if (!agents) {
- return [];
- }
- return agents.filter((a) => isValidAgent(a)).map((a) => {
- return {
- "guid": a.id,
- "name": a.name,
- "url": a.urls[0],
- "alternate_urls": a.urls
- }
- })
- });
- }
- function deleteCloudAgentURL(agentID, url) {
- if (!isSignedIn()) {
- return [];
- }
- return fetch(
- `${NETDATA.registry.cloudBaseURL}/api/v1/accounts/${cloudAccountID}/agents/${agentID}/url?value=${encodeURIComponent(url)}`,
- {
- method: "DELETE",
- mode: "cors",
- headers: {
- "Content-Type": "application/json; charset=utf-8",
- "Authorization": `Bearer ${cloudToken}`
- },
- }
- ).then((response) => {
- return response.json();
- }).then((payload) => {
- const count = payload.result ? payload.result.count : 0;
- return count;
- });
- }
- // -------------------------------------------------------------------------------------------------
- function signInDidClick(e) {
- e.preventDefault();
- e.stopPropagation();
- if (!NETDATA.registry.isUsingGlobalRegistry()) {
- // If user is using a private registry, request his consent for
- // synchronizing with cloud.
- showSignInModal();
- return;
- }
- signIn();
- }
- function shouldShowSignInBanner() {
- return false;
- }
- function closeSignInBanner() {
- localStorage.setItem("signInBannerClosed", "true");
- const el = document.getElementById("sign-in-banner");
- if (el) {
- el.style.display = "none";
- }
- }
- function closeSignInBannerDidClick(e) {
- closeSignInBanner();
- }
- function signOutDidClick(e) {
- e.preventDefault();
- e.stopPropagation();
- signOut();
- }
- // -------------------------------------------------------------------------------------------------
- function updateMyNetdataAfterFilterChange() {
- const machinesEl = document.getElementById("my-netdata-menu-machines")
- machinesEl.innerHTML = renderMachines(cloudAgents);
- if (options.hosts.length > 1) {
- const streamedEl = document.getElementById("my-netdata-menu-streamed")
- streamedEl.innerHTML = renderStreamedHosts(options);
- }
- }
- function myNetdataMenuDidShow() {
- const filterEl = document.getElementById("my-netdata-menu-filter-input");
- if (filterEl) {
- filterEl.focus();
- }
- }
- function myNetdataFilterDidChange(e) {
- const inputEl = e.target;
- setTimeout(() => {
- myNetdataMenuFilterValue = inputEl.value;
- updateMyNetdataAfterFilterChange();
- }, 1);
- }
- function myNetdataFilterClearDidClick(e) {
- e.preventDefault();
- e.stopPropagation();
- const inputEl = document.getElementById("my-netdata-menu-filter-input");
- inputEl.value = "";
- myNetdataMenuFilterValue = "";
- updateMyNetdataAfterFilterChange();
- inputEl.focus();
- }
- // -------------------------------------------------------------------------------------------------
- function clearCloudVariables() {
- cloudAccountID = null;
- cloudAccountName = null;
- cloudToken = null;
- }
- function clearCloudLocalStorageItems() {
- localStorage.removeItem("cloud.baseURL");
- localStorage.removeItem("cloud.agentID");
- localStorage.removeItem("cloud.sync");
- }
- function signIn() {
- const url = `${NETDATA.registry.cloudBaseURL}/account/sign-in-agent?id=${NETDATA.registry.machine_guid}&name=${encodeURIComponent(NETDATA.registry.hostname)}&origin=${encodeURIComponent(window.location.origin + "/")}`;
- window.open(url);
- }
- function signOut() {
- cloudSSOSignOut();
- }
- function handleMessage(e) {
- switch (e.data.type) {
- case "sign-in":
- handleSignInMessage(e);
- break;
- case "sign-out":
- handleSignOutMessage(e);
- break;
- default:
- return;
- }
- }
- function handleSignInMessage(e) {
- closeSignInBanner();
- localStorage.setItem("cloud.baseURL", NETDATA.registry.cloudBaseURL);
- cloudAccountID = e.data.accountID;
- cloudAccountName = e.data.accountName;
- cloudToken = e.data.token;
- netdataRegistryCallback(registryAgents);
- if (e.data.redirectURI && !window.location.href.includes(e.data.redirectURI)) {
- // lgtm false-positive - redirectURI does not come from user input, but from iframe callback
- window.location.replace(e.data.redirectURI); // lgtm[js/client-side-unvalidated-url-redirection]
- }
- }
- function handleSignOutMessage(e) {
- clearCloudVariables();
- renderMyNetdataMenu(registryAgents);
- }
- function isSignedIn() {
- return cloudToken != null && cloudAccountID != null;
- }
- function sortedArraysEqual(a, b) {
- if (a.length != b.length) return false;
- for (var i = 0; i < a.length; ++i) {
- if (a[i] !== b[i]) return false;
- }
- return true;
- }
- // If merging is needed returns the merged agents set, otherwise returns null.
- function mergeAgents(cloud, local) {
- let dirty = false;
- const union = new Map();
- for (const cagent of cloud) {
- union.set(cagent.guid, cagent);
- }
- for (const lagent of local) {
- const cagent = union.get(lagent.guid);
- if (cagent) {
- for (const u of lagent.alternate_urls) {
- if (u === NETDATA.registry.MASKED_DATA) { // TODO: temp until registry is updated.
- continue;
- }
- if (!cagent.alternate_urls.includes(u)) {
- dirty = true;
- cagent.alternate_urls.push(u);
- }
- }
- } else {
- dirty = true;
- union.set(lagent.guid, lagent);
- }
- }
- if (dirty) {
- return Array.from(union.values());
- }
- return null;
- }
- function showSignInModal() {
- document.getElementById("sim-registry").innerHTML = NETDATA.registry.server;
- $("#signInModal").modal("show");
- }
- function explicitlySignIn() {
- $("#signInModal").modal("hide");
- signIn();
- }
- function showSyncModal() {
- document.getElementById("sync-registry-modal-registry").innerHTML = NETDATA.registry.server;
- $("#syncRegistryModal").modal("show");
- }
- function explicitlySyncAgents() {
- $("#syncRegistryModal").modal("hide");
- const json = localStorage.getItem("cloud.sync");
- const sync = json ? JSON.parse(json) : {};
- delete sync[cloudAccountID];
- localStorage.setItem("cloud.sync", JSON.stringify(sync));
- NETDATA.registry.init();
- }
- function syncAgents(callback) {
- const json = localStorage.getItem("cloud.sync");
- const sync = json ? JSON.parse(json) : {};
- const currentAgent = {
- guid: NETDATA.registry.machine_guid,
- name: NETDATA.registry.hostname,
- url: NETDATA.serverDefault,
- alternate_urls: [NETDATA.serverDefault],
- }
- const localAgents = sync[cloudAccountID]
- ? [currentAgent]
- : registryAgents.concat([currentAgent]);
- console.log("Checking if sync is needed.", localAgents);
- const agentsToSync = mergeAgents(cloudAgents, localAgents);
- if ((!sync[cloudAccountID]) || agentsToSync) {
- sync[cloudAccountID] = new Date().getTime();
- localStorage.setItem("cloud.sync", JSON.stringify(sync));
- }
- if (agentsToSync) {
- console.log("Synchronizing with netdata.cloud.");
- postCloudAccountAgents(agentsToSync).then((agents) => {
- // TODO: clear syncTime on error!
- cloudAgents = agents;
- callback(cloudAgents);
- });
- return
- }
- callback(cloudAgents);
- }
- let isCloudSSOInitialized = false;
- function cloudSSOInit() {
- const iframeEl = document.getElementById("ssoifrm");
- const url = `${NETDATA.registry.cloudBaseURL}/account/sso-agent?id=${NETDATA.registry.machine_guid}`;
- iframeEl.src = url;
- isCloudSSOInitialized = true;
- }
- function cloudSSOSignOut() {
- const iframe = document.getElementById("ssoifrm");
- const url = `${NETDATA.registry.cloudBaseURL}/account/sign-out-agent`;
- iframe.src = url;
- }
- function initCloud() {
- if (!NETDATA.registry.isCloudEnabled) {
- clearCloudVariables();
- clearCloudLocalStorageItems();
- return;
- }
- if (NETDATA.registry.cloudBaseURL != localStorage.getItem("cloud.baseURL")) {
- clearCloudVariables();
- clearCloudLocalStorageItems();
- if (NETDATA.registry.cloudBaseURL) {
- localStorage.setItem("cloud.baseURL", NETDATA.registry.cloudBaseURL);
- }
- }
- if (!isCloudSSOInitialized) {
- cloudSSOInit();
- }
- touchAgent();
- }
- // This callback is called after NETDATA.registry is initialized.
- function netdataRegistryCallback(machinesArray) {
- localStorage.setItem("cloud.agentID", NETDATA.registry.machine_guid);
- initCloud();
- registryAgents = machinesArray;
- if (isSignedIn()) {
- // We call getCloudAccountAgents() here because it requires that
- // NETDATA.registry is initialized.
- clearMyNetdataMenu();
- getCloudAccountAgents().then((agents) => {
- if (!agents) {
- errorMyNetdataMenu();
- return;
- }
- cloudAgents = agents;
- syncAgents((agents) => {
- const agentsMap = {}
- for (const agent of agents) {
- agentsMap[agent.guid] = agent;
- }
- NETDATA.registry.machines = agentsMap;
- NETDATA.registry.machines_array = agents;
- renderMyNetdataMenu(agents);
- });
- });
- } else {
- renderMyNetdataMenu(machinesArray)
- }
- };
- // If we know the cloudBaseURL and agentID from local storage render (eagerly)
- // the account ui before receiving the definitive response from the web server.
- // This improves the perceived performance.
- function tryFastInitCloud() {
- const baseURL = localStorage.getItem("cloud.baseURL");
- const agentID = localStorage.getItem("cloud.agentID");
- if (baseURL && agentID) {
- NETDATA.registry.cloudBaseURL = baseURL;
- NETDATA.registry.machine_guid = agentID;
- NETDATA.registry.isCloudEnabled = true;
- initCloud();
- }
- }
- function initializeApp() {
- window.addEventListener("message", handleMessage, false);
- // tryFastInitCloud();
- }
- if (document.readyState === "complete") {
- initializeApp();
- } else {
- document.addEventListener("readystatechange", () => {
- if (document.readyState === "complete") {
- initializeApp();
- }
- });
- }
|