From 9648a92a81f5cf0b1e4979c16534072fd6deb405 Mon Sep 17 00:00:00 2001 From: Ilia Ross Date: Thu, 4 Jul 2024 13:59:29 +0300 Subject: [PATCH] Add ability to return full stats for unpaused connections to have perfect sync --- extensions/stats/stats.min.js | 2 +- extensions/stats/stats.min.js.gz | Bin 2884 -> 3062 bytes extensions/stats/stats.src.js | 48 ++++++++++++++++++++-------- stats-lib-funcs.pl | 6 ++-- stats.pl | 44 +++++++++++++++++++++++-- theme.info | 2 +- unauthenticated/js/bundle.min.js.gz | Bin 510024 -> 510024 bytes 7 files changed, 83 insertions(+), 19 deletions(-) diff --git a/extensions/stats/stats.min.js b/extensions/stats/stats.min.js index 6700bbd2a..db8b7b5a0 100644 --- a/extensions/stats/stats.min.js +++ b/extensions/stats/stats.min.js @@ -1 +1 @@ -"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _slicedToArray=function(){function sliceIterator(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"])_i["return"]();}finally{if(_d)throw _e;}}return _arr;}return function(arr,i){if(Array.isArray(arr)){return arr;}else if(Symbol.iterator in Object(arr)){return sliceIterator(arr,i);}else{throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var stats={sys:{error:0,activating:0,requery:null,socket:null,_:{prefix:v___location_prefix,error:connection_error,language:theme_language,convert:{size:Convert.nice_size},chart:Chartist,dayjs:dayjs,locale:{time:config_portable_theme_locale_format_time,offset:function offset(){return get_utc_offset();}},blocked:theme_updating,getHistoryData:function getHistoryData(data){return vars.stats.history;}},selector:{chart:{container:{parent:"live_stats",data:"data-chart"},loader:"data-charts-loader"},collapse:"collapse",dashboard:"system-status",slider:"info-container",piechart:"piechart"},getSocketDefs:function getSocketDefs(){return{session:session.server.data("session-hash"),paused:!this.runRender()?1:0,interval:this.getInterval(),disable:!this.isEnabled()?1:0,shutdown:settings_sysinfo_real_time_shutdown_on_last?1:0};},updateSocket:function updateSocket(){if(this.isEnabled()&&this.socket){var socketData=this.getSocketDefs();this.socket.send(JSON.stringify(socketData));}},graphsCanPreRender:function graphsCanPreRender(){return document.querySelector("["+this.selector.chart.loader+"]")?1:0;},getInterval:function getInterval(){return settings_sysinfo_real_time_run_rate/1000;},getStoredDuration:function getStoredDuration(){return settings_sysinfo_real_time_stored_duration;},runRender:function runRender(){return theme.visibility.get();},isEnabled:function isEnabled(){return settings_sysinfo_real_time_status?1:0;},restart:function restart(){var _this=this;this.shutdown();setTimeout(function(){_this.enable();},this.getInterval()*1000*3);},disable:function disable(){if(this.socket){var socketData=this.getSocketDefs();socketData.paused=1;this.socket.send(JSON.stringify(socketData));}},enable:function enable(){if(this.isEnabled()){if(this.graphsCanPreRender()){this.preRender();}if(this.socket){this.socket.send(JSON.stringify(this.getSocketDefs()));}else{this.activate();}}},shutdown:function shutdown(){if(this.socket){var socketData=this.getSocketDefs();socketData.disable=1;this.socket.send(JSON.stringify(socketData));}},activate:function activate(){if(this.activating++||this._.blocked()||this.socket){return;}$.ajax({context:this,url:this._.prefix+"/stats.cgi",error:function error(){var _this2=this;this.activating=0;if(this.error++>3){return;}!this.requery&&(this.requery=setTimeout(function(){_this2.requery=null;_this2.activate();},this.getInterval()*1000));},success:function success(data){var _this3=this;if(data.success){console.warn("WebSocket connection opened",data);this.socket=new WebSocket(data.socket);this.socket.onopen=function(){_this3.activating=0;console.log("WebSocket connection established",_this3.getSocketDefs());_this3.socket.send(JSON.stringify(_this3.getSocketDefs()));};this.socket.onmessage=function(event){var message=JSON.parse(event.data);_this3.render(message);console.log("Received stats:",message);if(_this3.runRender.last!=_this3.runRender()){_this3.runRender.last=_this3.runRender();_this3.updateSocket();}};this.socket.onclose=function(){console.warn("WebSocket connection closed");setTimeout(function(){_this3.socket=null;_this3.activating=0;_this3.enable();},_this3.getInterval());};}else{this.activating=0;}this.error=0;},dataType:"json"});},preRender:function preRender(){this.render(this._.getHistoryData(),2);},render:function render(data,graphs){var _this4=this;Object.entries(data).map(function(_ref){var _ref2=_slicedToArray(_ref,2),target=_ref2[0],data=_ref2[1];var v=parseInt(data),vo=(typeof data==="undefined"?"undefined":_typeof(data))==="object"?data[data.length-1]:false,vt=vo?vo:v,$pc=$("#"+_this4.selector.dashboard+" ."+_this4.selector.piechart+"[data-charts*=\""+target+"\"]"),$lc=$("."+_this4.selector.slider+" ."+target+"_percent"),$od=$("#"+_this4.selector.dashboard+" span[data-id=\"sysinfo_"+target+"\"], \n ."+_this4.selector.slider+" span[data-data=\""+target+"\"]"),cached=target==="graphs"?graphs?2:_this4.graphsCanPreRender()?2:1:0;if(Number.isInteger(v)){if($pc.length){var piechart=$pc.data("easyPieChart");piechart&&piechart.update(v);}if($lc.length){$lc.find(".bar").attr("style","width:"+v+"%");var $dp=$lc.find(".description"),$lb=$dp.text().split(":")[0];$dp.attr("title",vo).text($lb+": "+v+"% ("+vo+")");}if($od.length){if($od.find("a").length){$od.find("a").text(vt);}else{$od.text(vt);}}}if(cached){var lds=_this4.selector.chart.container.parent+"-"+_this4.selector.collapse,ld=$("#"+lds).find("["+_this4.selector.chart.loader+"]");Object.entries(data).map(function(_ref3){var _ref4=_slicedToArray(_ref3,2),_type=_ref4[0],array=_ref4[1];var options={chart:{type:function type(){return _type==="proc"||_type==="disk"||_type==="net";},bandwidth:function bandwidth(){return _type==="disk"||_type==="net";},fill:function fill(){return this.type()?false:true;},high:function high(){return this.type()?undefined:100;},threshold:function threshold(){return this.type()?-1:50;},height:"100px"}},lg=_this4._.language(_this4.selector.chart.container.parent+"_"+_type),tg=$("#"+lds).find("["+_this4.selector.chart.container.data+"="+_type+"]"),sr=[{name:"series-"+_type,data:array}];if(!tg.length){return;}if(array[0]&&_typeof(array[0].y)==="object"){sr=[];array[0].y.forEach(function(x,i){var data=[];array.forEach(function(n){data.push({data:{x:n.x,y:n.y[i]}});});sr.push({name:"series-"+_type+"-"+i,data:data});});}if(tg[0]&&tg[0].textContent){if(cached===1){var lf=parseInt(_this4.getStoredDuration());if(lf<300||lf>3600){lf=600;}var tdata=sr,cdata=_this4["chart_"+_type].data.series,cdata_start=void 0,cdata_end=void 0,cdata_ready=new Promise(function(resolve){tdata.forEach(function(d,i,a){cdata_start=cdata[i].data[0].x||cdata[i].data[0].data.x;cdata_end=cdata[i].data[cdata[i].data.length-1].x||cdata[i].data[cdata[i].data.length-1].data.x;cdata[i].data.push(d.data[0]);if(cdata_end-cdata_start>lf){cdata[i].data.shift();}if(i===a.length-1){resolve();}});});cdata_ready.then(function(){_this4["chart_"+_type].update({series:cdata});});}}else if(cached===2){_this4["chart_"+_type]=new _this4._.chart.Line(tg[0],{series:sr},{axisX:{type:_this4._.chart.FixedScaleAxis,divisor:12,labelInterpolationFnc:function labelInterpolationFnc(value){return _this4._.dayjs(value*1000).utcOffset(_this4._.locale.offset()).format(_this4._.locale.time);}},height:options.chart.height,showArea:options.chart.fill(),showPoint:!options.chart.fill(),high:options.chart.high(),low:0,fullWidth:true,chartPadding:{left:25},axisY:{onlyInteger:true,labelInterpolationFnc:function labelInterpolationFnc(value){if(options.chart.fill()){return value?value+"%":value;}else if(options.chart.bandwidth(value)){if(_type==="net"){return value?_this4._.convert.size(value,{fixed:0,bits:1,round:1}):value;}return value?_this4._.convert.size(value*1000,{fixed:0,round:1}):value;}else{return value;}}},plugins:[_this4._.chart.plugins.ctAxisTitle({axisY:{axisTitle:lg,axisClass:"ct-axis-title",offset:{x:0,y:9},flipTitle:true}}),_this4._.chart.plugins.ctThreshold({threshold:options.chart.threshold()})]});_this4["chart_"+_type].on("created",function(){return ld.remove();});}});}});}}}; +"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj;}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};var _slicedToArray=function(){function sliceIterator(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"])_i["return"]();}finally{if(_d)throw _e;}}return _arr;}return function(arr,i){if(Array.isArray(arr)){return arr;}else if(Symbol.iterator in Object(arr)){return sliceIterator(arr,i);}else{throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var stats={sys:{error:0,activating:0,requery:null,socket:null,_:{prefix:v___location_prefix,error:connection_error,language:theme_language,convert:{size:Convert.nice_size},chart:Chartist,dayjs:dayjs,locale:{time:config_portable_theme_locale_format_time,offset:function offset(){return get_utc_offset();}},blocked:theme_updating,getHistoryData:function getHistoryData(data){return vars.stats.history;}},selector:{chart:{container:{parent:"live_stats",data:"data-chart"},loader:"data-charts-loader"},collapse:"collapse",dashboard:"system-status",slider:"info-container",piechart:"piechart"},getSocketDefs:function getSocketDefs(){return{session:session.server.data("session-hash"),paused:!this.canRender()?1:0,interval:this.getInterval(),disable:!this.isEnabled()?1:0,shutdown:settings_sysinfo_real_time_shutdown_on_last?1:0};},updateSocket:function updateSocket(){if(this.isEnabled()&&this.socket){var socketData=this.getSocketDefs();this.socket.send(JSON.stringify(socketData));}},graphsCanPreRender:function graphsCanPreRender(){return document.querySelector("["+this.selector.chart.loader+"]")?1:0;},getInterval:function getInterval(){return settings_sysinfo_real_time_run_rate/1000;},getStoredDuration:function getStoredDuration(){return settings_sysinfo_real_time_stored_duration;},getRenderType:function getRenderType(graphs){graphs=graphs.graphs;var hasMultipleDatasets=false;for(var key in graphs){if(graphs.hasOwnProperty(key)&&Array.isArray(graphs[key])){if(graphs[key].length>1){hasMultipleDatasets=true;break;}}}return hasMultipleDatasets?3:null;},canRender:function canRender(){return theme.visibility.get();},isEnabled:function isEnabled(){return settings_sysinfo_real_time_status?1:0;},restart:function restart(){var _this=this;this.shutdown();setTimeout(function(){_this.enable();},this.getInterval()*1000*3);},disable:function disable(){if(this.socket){var socketData=this.getSocketDefs();socketData.paused=1;this.socket.send(JSON.stringify(socketData));}},enable:function enable(){if(this.isEnabled()){if(this.graphsCanPreRender()){this.preRender();}if(this.socket){this.socket.send(JSON.stringify(this.getSocketDefs()));}else{this.activate();}}},shutdown:function shutdown(){if(this.socket){var socketData=this.getSocketDefs();socketData.disable=1;this.socket.send(JSON.stringify(socketData));}},activate:function activate(){if(this.activating++||this._.blocked()||this.socket){return;}$.ajax({context:this,url:this._.prefix+"/stats.cgi",error:function error(){var _this2=this;this.activating=0;if(this.error++>3){return;}!this.requery&&(this.requery=setTimeout(function(){_this2.requery=null;_this2.activate();},this.getInterval()*1000));},success:function success(data){var _this3=this;if(data.success){console.warn("WebSocket connection opened",data);this.socket=new WebSocket(data.socket);this.socket.onopen=function(){_this3.activating=0;console.log("WebSocket connection established",_this3.getSocketDefs());_this3.socket.send(JSON.stringify(_this3.getSocketDefs()));};this.socket.onmessage=function(event){var message=JSON.parse(event.data),renderType=_this3.getRenderType(message);if(_this3.canRender.last!=_this3.canRender()){console.log("Visibility changed",_this3.canRender());_this3.canRender.last=_this3.canRender();_this3.updateSocket();}console.log("Received stats",renderType,message);_this3.render(message,renderType);};this.socket.onclose=function(){console.warn("WebSocket connection closed");setTimeout(function(){_this3.socket=null;_this3.activating=0;_this3.enable();},_this3.getInterval());};}else{this.activating=0;}this.error=0;},dataType:"json"});},preRender:function preRender(){this.render(this._.getHistoryData(),2);},render:function render(data,graphs){var _this4=this;Object.entries(data).map(function(_ref){var _ref2=_slicedToArray(_ref,2),target=_ref2[0],data=_ref2[1];var v=parseInt(data),vo=(typeof data==="undefined"?"undefined":_typeof(data))==="object"?data[data.length-1]:false,vt=vo?vo:v,$pc=$("#"+_this4.selector.dashboard+" ."+_this4.selector.piechart+"[data-charts*=\""+target+"\"]"),$lc=$("."+_this4.selector.slider+" ."+target+"_percent"),$od=$("#"+_this4.selector.dashboard+" span[data-id=\"sysinfo_"+target+"\"], \n ."+_this4.selector.slider+" span[data-data=\""+target+"\"]"),cached=target==="graphs"?graphs?graphs===3?3:2:_this4.graphsCanPreRender()?2:1:0;console.log('Mode',cached);if(Number.isInteger(v)){if($pc.length){var piechart=$pc.data("easyPieChart");piechart&&piechart.update(v);}if($lc.length){$lc.find(".bar").attr("style","width:"+v+"%");var $dp=$lc.find(".description"),$lb=$dp.text().split(":")[0];$dp.attr("title",vo).text($lb+": "+v+"% ("+vo+")");}if($od.length){if($od.find("a").length){$od.find("a").text(vt);}else{$od.text(vt);}}}if(cached){var lds=_this4.selector.chart.container.parent+"-"+_this4.selector.collapse,ld=$("#"+lds).find("["+_this4.selector.chart.loader+"]");Object.entries(data).map(function(_ref3){var _ref4=_slicedToArray(_ref3,2),_type=_ref4[0],array=_ref4[1];var options={chart:{type:function type(){return _type==="proc"||_type==="disk"||_type==="net";},bandwidth:function bandwidth(){return _type==="disk"||_type==="net";},fill:function fill(){return this.type()?false:true;},high:function high(){return this.type()?undefined:100;},threshold:function threshold(){return this.type()?-1:50;},height:"100px"}},lg=_this4._.language(_this4.selector.chart.container.parent+"_"+_type),tg=$("#"+lds).find("["+_this4.selector.chart.container.data+"="+_type+"]"),sr=[{name:"series-"+_type,data:array}];if(!tg.length){return;}if(array[0]&&_typeof(array[0].y)==="object"){sr=[];array[0].y.forEach(function(x,i){var data=[];array.forEach(function(n){data.push({data:{x:n.x,y:n.y[i]}});});sr.push({name:"series-"+_type+"-"+i,data:data});});}if(tg[0]&&tg[0].textContent&&cached!==3){if(cached===1){var lf=parseInt(_this4.getStoredDuration());if(lf<300||lf>3600){lf=600;}var tdata=sr,cdata=_this4["chart_"+_type].data.series,cdata_start=void 0,cdata_end=void 0,cdata_ready=new Promise(function(resolve){tdata.forEach(function(d,i,a){cdata_start=cdata[i].data[0].x||cdata[i].data[0].data.x;cdata_end=cdata[i].data[cdata[i].data.length-1].x||cdata[i].data[cdata[i].data.length-1].data.x;cdata[i].data.push(d.data[0]);if(cdata_end-cdata_start>lf){cdata[i].data.shift();}if(i===a.length-1){resolve();}});});cdata_ready.then(function(){_this4["chart_"+_type].update({series:cdata});});}}else if(cached===2||cached===3){console.warn("Re-drawing chart",_type);_this4["chart_"+_type]=new _this4._.chart.Line(tg[0],{series:sr},{axisX:{type:_this4._.chart.FixedScaleAxis,divisor:12,labelInterpolationFnc:function labelInterpolationFnc(value){return _this4._.dayjs(value*1000).utcOffset(_this4._.locale.offset()).format(_this4._.locale.time);}},height:options.chart.height,showArea:options.chart.fill(),showPoint:!options.chart.fill(),high:options.chart.high(),low:0,fullWidth:true,chartPadding:{left:25},axisY:{onlyInteger:true,labelInterpolationFnc:function labelInterpolationFnc(value){if(options.chart.fill()){return value?value+"%":value;}else if(options.chart.bandwidth(value)){if(_type==="net"){return value?_this4._.convert.size(value,{fixed:0,bits:1,round:1}):value;}return value?_this4._.convert.size(value*1000,{fixed:0,round:1}):value;}else{return value;}}},plugins:[_this4._.chart.plugins.ctAxisTitle({axisY:{axisTitle:lg,axisClass:"ct-axis-title",offset:{x:0,y:9},flipTitle:true}}),_this4._.chart.plugins.ctThreshold({threshold:options.chart.threshold()})]});_this4["chart_"+_type].on("created",function(){return ld.remove();});}});}});}}}; diff --git a/extensions/stats/stats.min.js.gz b/extensions/stats/stats.min.js.gz index cf68adf61c52edbc31df6d17f140d9c048eb7a96..39827dbb50ce1062965455549d9da8ac3771e3b7 100644 GIT binary patch literal 3062 zcmVKlRa{#3oYmei$@q2%Tm%VPJSXTCN2~fGZ zMQ};b6ix1McW7ET3xSqsn|E4K6>0CfTL1UX3`t3T>~+&Du$DNS8P1C{LyE1n7-`eU z+_33}H>1pKYoQjYeT?33@8+sZ)08dNRc@rJ*!lV1Tr7=fxKRxvX#%kuj~uA^$FOaL zSvS?lkpXDBOHN|I`vLcZl>s5nRRsdCbGxKPqnR^5it9!hg?w(jM9FY*tEetzE{YH8 z+os{$w38=n{p*M@est;uylEmCwnPi>>Fn0>sZx+e*!Ln`@KU>hNY_;%7P1n>)HK_6 z0ZeE@ra(VCFyCzuMwyMG%3QQxzc_a9z>28;Eldl5NG(cQfaX~s5Pj?_5FUxI<0s@n>tO7Q2#;ix! zZ8#hRVNU?aSrM95qwYafSj71dWtjRwXH{oBAR=?eQqvRRVds9L6kxv*;2oG}B&*Sz z`A3nPeVS7~vP@blTP5yCAHezFHw_@LA1kn!EJoZIaaWs>QKLfGcv?4NRH z0s@U!xnRI?H{F5u=stiMowj=<>G^o;T4?7MzS1g6e)+Wz99E=vtOVqz`!msOsj1&RtUqL95tT_;DK}sgq+}7YOc?%7h=A?D8oU7X z0Z>mY3?_3`mb}&?Vg3zy=+#{Drbr;YXo#Z;GG7CCh(=;1tA(0$lCY?j!ivZI8?Xjt z-&1saCl-3o20gg5ZmWgXFrBz(tVIJJk5TA=IpAaklCdzVIi&R>IWu6WIOo+n0g0#y z!kbG7Pgy~H!zM^*7FPSw0U!YtQezA_N~yoEa9B7>y;_?>-J=W!-KaBAA63mD&y*A- zna9Z>fJ?3o62jhz$o0Z1*6TWi29zES7lwL(5W9_R_OnpeOojhKRyyDi(N|)gbw0Gw_!fry@>fo{t!?hhX$C+RJ3kfy~<+S zE{)k&win2klDXcg_b~N(gLuCh1bi=4dNK8q62*A@>bjT1)z=&;Q5CXC4>iBux2>0?RLds>!NfE#rCy;lj>X~Dm^%1p zV)F?~u;zi(cVHptoqNH>2I{vps-Gj?&^c;hXQ{&qA*=ezmiEgH%AF&plbA#3NcYBMz6S;u?xEQ$xxmPsmbaH&` zlvj0td2H#tR9XxJM2>s0yvi6*O{b>)>b;Mpq#f>wPAU2A7O{-_vdRmv+nBV=!n48$h_c z5a02-Hx{%83r7cUSLyy;2TjBB5p)G0RZ2Lsi(69EjV|rw#wMkm0Cuy>L>rX`?ka__ z)0B0W9PDQBp16x7OBW)dBDvWOLS~d(Y#%ncyiKU_i#8_RsGE&SHqnbZPhSM=k8EsJ z@4M;l^fhLq_;}hMu*PgQIM98W{>q>&CxyrCS8T$g7bPumf`>iES^l0TgI+TSnfL!RB(9IKKEv72*rG2Bp29*LQPBMpEN8TLRg}wo~9r=V=?0-a{!)*z>F4 zdiz!ix~zZ%;4#k6{hP~Sz>+#Ha9zg|-y!A-@Z_8~ER4A^a0=6ATf$kL-OIwP5;oq9 z*`Jub!Ff^C>42&bI&Wl6SBw}H^Ar$bLzi!{t|1=>EMXz+kSR`B_C^|HzfqyZ1hO$p zMs}T108ce$A#>uYq7&B*?b;l~?ey4#64Qzg-#FS#M-U9goy2J z$e2xzL&{%mM5PaGU>G`SW+(6u546wBN!NW+dU+}-U1L_F#6fB3B_<_K*Ryu$vXUZS z>C|8On7v~tj`~xRBA_C{Y_)=+`!5(P_P?_%{sRCd zT#tN=SA{LrH@c*!*Q9+&s`w$=!tZt_Z+F;5K&Rs_@=t0=TUA;;@yC+TfpbX;(Sy>$ zYdkAekS}dgID?coQZ^|9kzv2CsI zl6(+--S?R;w64Gk{{8x}(SIiY4&a(kD7Y<~DV{{xaAQ;|Gjy0VyivMrze0mse5A=c1%zK&?s&_aCaf&zmQw1N)7w z&;4#K`j%oR?eRTcoBWOa_|a!k`i>I&Zz5rAzo;A`;5{B)thk))YMfKZ0wYN2_uqmi z4`ywBq1m@eRwg++IZyTFfG-u9s8sjKMYMn;)h|@~uprs*M{jvi;8(4-6bqAFeZ7m& z?EgwyRh3)U=UMdMV_68NQxXq8{Q%kx{bCoF&|CkhaG$m>*Ooi6-z(4ueEZ;WAJOpp znI(?e1%?tBXD*FSE~7?4^-V5!p_k#goG3zic1L`u%NsJIyT7_zFJ+~Z*+GCic$^yy z@DJFF2Cef9_mHGqlDA%$Ts;N}Jg7?-P?i1+JxeKTONai13=NE^KD7-S}Ain4%X^qsQ#%%wE?-%bDUUuKlRa{#3oYj51R@q2&8noSKUtJV3DJD}Ps zMv&yt6vZXD1h^KCA!sG;E)!YQk=(Vn^8WYE3@K6jaO(5|#1@A$!+CKYG+Svt(ng8G zu<1Hiqs(j?F6XKJHTt-@oyjUqQ#N1Kg%Pr5r>8r6u`pcaMk++o1Y%bmav*14!d7v! zQuWA@0cg5Sj$**~9{0VI0U<7A4FazUd!$99os(`AH%c0be6Bi)lHuW2QC*3Gm!IS- zrSeVM%M-TU=ZG-gIrV~EsYrw^(ZY9nePj95DM-WZcbU%fO1lM5S9QtfqUPn)s7*Tu zCbS_^pugTT-%SuknVy~mz%a;knu)mP_a+F#xRf;yr|zJz#naJ#Q6|qn0AZas?K;oMCOi#rr!t;d-oG12m6fxZ_hjTEXqO4b#6qxfQ90}uejPI^{T2OEsL+**zYW9 z8wCMzpRBVit0cGuY?E17WO+e!*PLvY5g@Aada=qEJTXgt%d>770pgk~leAj=hbOP? zDz3pA8A7&EvCLunHU1RZL}kADq7(WV;n5XOS|e^bo;VkatdYu~)|oqpP%?$bxaO-4j@ggcx@6^i8UAnDOrRp6NW!0M8LLSjl2Z( z0Z>mY3^of{Re7U%!n!Zyp_en6t1^M~q9KkZ$b1FdAsUI5sONIhOTwZ?a4R0`zJN6- z`;nsK4WH{B8+dSU-Bxq0VLNfZW6c$KJVv1d=75tWNXEjb$sw(m$%z3&#cEam${`V{ zAiO$<@Dw$~H(Y{*cHy*l4gd+L6dGf|Q40OG#%1X!^>SrOd51C>bfeBdeN;7rJX2AS zWF1Zh0bJ$UAR*kHh+NODVqVuFG@$gbe=yVogxG6jv#FgLsWH1@WX&lBKxg|M_j`x*S?+OzgL^Ybe*A~?vopu^BOJ=hH!DT?WjC^Rww`o= zCX%dlG;l;8QJ(c6$og`RS3X_~EoPz;W`lmhq!9Jq_2dJGKS?6IZO(`avNzr=FNy^O zu2iEdC{A2lxcCG~;Dk@WPOeNasQyF{a}tNdJ-jB*(bUf`akINH{pk)c2cQ{+oy+oZV$8MJg9t-rarLD$8rrUk3{+D#e)C_%vhD}#H$=I0CyCmb=u-;{V z)TYik|A$dKA-z;y>|QG01&qfJ4+P3$R{?|2K|0ZGm`}IQ;`~c~A5h(bevh(pv{EiT zXR+-L#_R`M`ig~Mu2t|Jrq*T{3GdO2LNu)WLaX)s)--?%Cl zJredfQwJM5^|2d-mW}kPD4=)^ylnxl_V+4XT9rTn+=v}kh-TBW;_+Rs>VW;mXV&*4 z-$#vP!=VMYrGKY7q}UtwB#yCl&rX2I8d;?KnqThPwv(iii$?^(#5AjfUZOOP#s1Zp zI`}tY^ASq0=AP8IU?FG~z2JNe<;ohh+auo4C~0nYV{0XMhO+nGA&0v<{>lpuomFW& z;)F##8qNleL01=IYz9u!eK01Oqo_wPJE3-)25ilD)h;Tj`OsTWh!LVG**A;AWgj+u zpzno%gAIy@_mvNRbkt$~vmCbmdg6*=7N?hlebF!hZ;@wn*rp6pbn7lIty~V-YpcWP zBBaW>SHmq09_f0b!Toz-@1GsPKtqT|?k;J3n>XHAP^agP4!$nZ-8q}K;rIwjG)R>a z&h^<1De6||cCcQj6qaB&drY*JY2e0q!cJ4x57_K#@SV6v3`-Xxq9nQ56+*7*qT4Zf za(tGoe1dGc$!jZuDB<+3h1!uK8hx%u-}?70;rs#Q zibDm9ynr;9IyZv{Y(%ju`}^u5alDT;942)_x=^B_XDjsfECqzv(1T8_8|a4vmaq^ae~KHHy%7f4 zuVrX4fo#l@kv(S=z;8KbA#>u&vKQAa?b$hq+v~9dC8lfBbzivYL0e>My=F~Xl{($` zzqMOG*v59k9<#||sC46URCNIh3_~Z)^%4C2A?b;^=F%sd7sry#C1x8+2$Wu4V6w^S z$MgD6k@}((AU) zZ=tGcjF2~O`n%LM$^a$|2&B`~uF`ancrz?FVXNt#*zd-3sougR z^D%tiJt|Wo?T`=g>aeA{MGwF9nY8yw9p6VA__?_jH(Trupo4Lb!$&owt17IX_`{OW zRJS07=oh7h*Eo=1yV&Oi(CpmhhPf}!T^>JtT%bmO zLq3L-)+#D&{U=t}jGWlH{wB7KIq6{$Gn(+BUW;;c=0H$7b^(g#<%U}P4@%w&XmER5 zLLkd(&7oH!)(5sOBN4&yF+7XD!N?>Gn&|%F;Q&V5?x$X$U5uTTZ$J)NJ%%{s-*1z% z%T5Nec`v|Zpu)>)?o{eY^-|1@o9YF4*Pn&qPBx+jn}TFu)z~a~eb65tI?ff?*7`0f z1`*f4^Y@{3@faKOVV^?m1^*{pZX2>u$6c#!)aLg>|I20XJ(8crJug4vtM)5Eib}B- z8m8#;i>S(HyrTZRkrl=6&voGw-_h;B{^7+ZZ+8|wu-i>L>m|AS!xIH_641+X&76@1&J=wQ-G_MgJp~h1fVI@!;+MXL7y`I~ktJ zi6X?aJK#fY+K?H&kTun6A!?mm?*+Jn$A!TF|AftC&^piL9VDq1n8fcya73d6%f(} iA4&#k#+jljVZObUHaWTcME|$bKm8YEONnUF9smHETcz#* diff --git a/extensions/stats/stats.src.js b/extensions/stats/stats.src.js index 9748d573b..26c2c2ca3 100644 --- a/extensions/stats/stats.src.js +++ b/extensions/stats/stats.src.js @@ -58,7 +58,7 @@ const stats = { getSocketDefs: function () { return { session: session.server.data("session-hash"), - paused: !this.runRender() ? 1 : 0, + paused: !this.canRender() ? 1 : 0, interval: this.getInterval(), disable: !this.isEnabled() ? 1 : 0, shutdown: settings_sysinfo_real_time_shutdown_on_last ? 1 : 0, @@ -84,8 +84,24 @@ const stats = { getStoredDuration: function () { return settings_sysinfo_real_time_stored_duration; }, + // Check if the received data has multiple datasets + getRenderType: function(graphs) { + graphs = graphs.graphs; + let hasMultipleDatasets = false; + for (const key in graphs) { + if (graphs.hasOwnProperty(key) && Array.isArray(graphs[key])) { + if (graphs[key].length > 1) { + hasMultipleDatasets = true; + break; + } + } + } + // Received graphs stats have history + // data (3) or a single slice (null) + return hasMultipleDatasets ? 3 : null; + }, // Can we update the stats in the UI? - runRender: function() { + canRender: function() { return theme.visibility.get(); }, // Check if the stats are enabled @@ -172,15 +188,17 @@ const stats = { }; // On socket message this.socket.onmessage = (event) => { - const message = JSON.parse(event.data); - this.render(message); - console.log("Received stats:", message); + const message = JSON.parse(event.data), + renderType = this.getRenderType(message); // Pause stats broadcast for this client // if the tab is not visible - if (this.runRender.last != this.runRender()) { - this.runRender.last = this.runRender(); - this.updateSocket(); + if (this.canRender.last != this.canRender()) { + console.log("Visibility changed", this.canRender()); + this.canRender.last = this.canRender(); + this.updateSocket(); } + console.log("Received stats", renderType, message); + this.render(message, renderType); }; // On socket close this.socket.onclose = () => { @@ -220,7 +238,8 @@ const stats = { $lc = $(`.${this.selector.slider} .${target}_percent`), $od = $(`#${this.selector.dashboard} span[data-id="sysinfo_${target}"], .${this.selector.slider} span[data-data="${target}"]`), - cached = target === "graphs" ? (graphs ? 2 : this.graphsCanPreRender() ? 2 : 1) : 0; + cached = target === "graphs" ? (graphs ? (graphs === 3 ? 3 : 2) : (this.graphsCanPreRender() ? 2 : 1)) : 0; + console.log('Mode', cached); if (Number.isInteger(v)) { // Update pie-charts if ($pc.length) { @@ -309,8 +328,9 @@ const stats = { }); } - // Update series if chart already exist - if (tg[0] && tg[0].textContent) { + // Update series if chart already + // exist unless it's a re-draw + if (tg[0] && tg[0].textContent && cached !== 3) { if (cached === 1) { let lf = parseInt(this.getStoredDuration()); if (lf < 300 || lf > 3600) { @@ -344,8 +364,10 @@ const stats = { } } - // Initialize chart the first time - else if (cached === 2) { + // Initialize chart the first time (2) or fully + // update (3) the chart if it's already drawn + else if (cached === 2 || cached === 3) { + console.warn("Re-drawing chart", type); this[`chart_${type}`] = new this._.chart.Line( tg[0], { diff --git a/stats-lib-funcs.pl b/stats-lib-funcs.pl index 7b3b9f164..16f74d7d7 100644 --- a/stats-lib-funcs.pl +++ b/stats-lib-funcs.pl @@ -144,13 +144,14 @@ sub get_stats_now sub get_stats_history { + my ($noempty) = @_; my $file = "$var_directory/modules/$current_theme". "/real-time-monitoring.json"; my $graphs = jsonify(read_file_contents($file)); # No data yet if (!keys %{$graphs}) { unlink($file); - return get_stats_empty(); + return $noempty ? undef : get_stats_empty(); } # Check if data is right foreach my $k (keys %{$graphs}) { @@ -174,7 +175,8 @@ sub get_stats_history trim_stats_history($graphs); # No data is available anymore if (!keys %{$graphs}) { - return get_stats_empty(); + unlink($file); + return $noempty ? undef : get_stats_empty(); } # Return data return { graphs => $graphs }; diff --git a/stats.pl b/stats.pl index e3e76c22e..6d8177854 100755 --- a/stats.pl +++ b/stats.pl @@ -46,21 +46,60 @@ $serv->shutdown(); return; } + # Has any connection been unpaused? + my $unpaused = grep { + $serv->{'conns'}->{$_}->{'conn'}->{'pausing'} && + !$serv->{'conns'}->{$_}->{'conn'}->{'paused'} } + keys %{$serv->{'conns'}}; + my $stats_history; + # Return full stats for the given user who was unpaused + # to make sure graphs are updated with most recent data + $stats_history = get_stats_history(1) if ($unpaused); # Collect current stats and send them to all connected # clients unless paused for some client my $stats_now = get_stats_now(); + my $stats_now_graphs = $stats_now->{'graphs'}; my $stats_now_json = encode_json($stats_now); foreach my $conn_id (keys %{$serv->{'conns'}}) { my $conn = $serv->{'conns'}->{$conn_id}->{'conn'}; if ($conn->{'verified'} && !$conn->{'paused'}) { + # Unpaused connection needs full stats + if ($conn->{'pausing'}) { + $conn->{'pausing'} = 0; + my $stats_updated; + # Merge stats from both disk data + # and currently cached data + if ($stats_history && $serv->{'stats'}) { + $stats_now->{'graphs'} = + merge_stats($stats_history->{'graphs'}, + $serv->{'stats'}); + $stats_updated++; + # If no cached data then use history + } elsif ($stats_history) { + $stats_now->{'graphs'} = $stats_history->{'graphs'}; + $stats_updated++; + # If no history then use cached data + } elsif ($serv->{'stats'}) { + $stats_updated++; + $stats_now->{'graphs'} = $serv->{'stats'}; + } + # If stats were updated then merge + # them with latest (now) data + if ($stats_updated) { + $stats_now->{'graphs'} = + merge_stats($stats_now->{'graphs'}, + $stats_now_graphs); + } + $stats_now_json = encode_json($stats_now); + } $conn->send_utf8($stats_now_json); } } # Cache stats to server if (!defined($serv->{'stats'})) { - $serv->{'stats'} = $stats_now->{'graphs'}; + $serv->{'stats'} = $stats_now_graphs; } else { - $serv->{'stats'} = merge_stats($serv->{'stats'}, $stats_now->{'graphs'}); + $serv->{'stats'} = merge_stats($serv->{'stats'}, $stats_now_graphs); } # Save stats to history and reset cache if ($serv->{'ticked'}++ % 15 == 0) { @@ -110,6 +149,7 @@ } } # Update connection variables + $conn->{'pausing'} = $conn->{'paused'} // 0; $conn->{'paused'} = $data->{'paused'} // 0; # Update WebSocket server variables $serv->{'interval'} = $data->{'interval'} // 1; diff --git a/theme.info b/theme.info index 958b6111c..8032a92d9 100644 --- a/theme.info +++ b/theme.info @@ -4,7 +4,7 @@ bootstrap=3 spa=1 nomodcall=xnavigation=1 version=21.20-RC4 -mversion=00 +mversion=01 bversion=00 webmin=1 usermin=1 diff --git a/unauthenticated/js/bundle.min.js.gz b/unauthenticated/js/bundle.min.js.gz index 8081a0b5e791c457fc62c58b180d3e644a035c19..5a303e2dd3acbfbb674eec696147688fe347806e 100644 GIT binary patch delta 39 vcmX>xLH@)9d3O134vq~CZH?@$?2N7KOs(w9t?VqV?5wTqY+Kpc9ZvuN_!bKn delta 39 vcmX>xLH@)9d3O134vzV~t&Qxh?2N7KOs(w9t?VqV?5wTqY+Kpc9ZvuN_kRl#