Added cpu/memory realtime graph.
Ylian Saint-Hilaire committed
Nov 15, 2020 at 23:52 UTC
5c9ac190b56179b8fa329633d03f3a88667e95a3
8 files changed
+128
-6
agents/meshcore.js
+7
@@ -952,6 +952,13 @@ function createMeshCore(agent) {
952
p.then(function (u) { mesh.SendCommand({ action: 'msg', type: 'userSessions', sessionid: data.sessionid, data: u, tag: data.tag }); });
953
break;
954
}
955
+ case 'cpuinfo':
956
+ // CPU & memory utilization
957
+ var cpuuse = require('sysinfo').cpuUtilization();
958
+ cpuuse.sessionid = data.sessionid;
959
+ cpuuse.tag = data.tag;
960
+ cpuuse.then(function (data) { mesh.SendCommand(JSON.stringify({ action: 'msg', type: 'cpuinfo', cpu: data, memory: require('sysinfo').memUtilization(), sessionid: this.sessionid, tag: this.tag })); }, function (ex) { });
961
+ break;
962
default:
963
// Unknown action, ignore it.
964
break;
meshuser.js
+3
@@ -3899,6 +3899,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3899
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
3900
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != SITERIGHT_ADMIN))) return;
3901
3902
+ // TODO: If we have peer servers, inform...
3903
+ //if (parent.parent.multiServer != null) { parent.parent.multiServer.DispatchMessage({ action: 'uploadagentcore', sessionid: ws.sessionId }); }
3904
+
3905
if (command.type == 'default') {
3906
// Send the default core to the agent
3907
parent.parent.updateMeshCore(function () { parent.sendMeshAgentCore(user, domain, node._id, 'default'); });
public/images/details/graph32.png
Binary files /dev/null and b/public/images/details/graph32.png differ
public/images/details/graph64.png
Binary files /dev/null and b/public/images/details/graph64.png differ
public/images/views.png
Binary files a/public/images/views.png and b/public/images/views.png differ
public/styles/style.css
+12
@@ -692,6 +692,10 @@ body {
692
float: right;
693
}
694
695
+#devListToolbarViewIcons3 {
696
+ float: right;
697
+}
698
+
699
#devListToolbarSpan {
700
width: 100%;
701
height: 24px;
@@ -2803,6 +2807,14 @@ a {
2807
width: 28px;
2808
}
2809
2810
+.viewSelector6 {
2811
+ margin-left: 2px;
2812
+ margin-top: 2px;
2813
+ background: url(../images/views.png) -336px 0px;
2814
+ height: 28px;
2815
+ width: 28px;
2816
+}
2817
+
2818
.fulldesk .viewSelector5 {
2819
background: url(../images/views.png) -252px 0px;
2820
}
translate/translate.json
+13
-1
@@ -11062,7 +11062,7 @@
11062
"zh-chs": "细节 -",
11063
"zh-cht": "細節 -",
11064
"xloc": [
11065
- "default.handlebars->container->column_l->p17->p17title->3"
11065
+ "default.handlebars->container->column_l->p17->p17title->5"
11066
]
11067
},
11068
{
@@ -21114,6 +21114,12 @@
21114
"default.handlebars->29->1161"
21115
]
21116
},
21117
+ {
21118
+ "en": "Live Graph",
21119
+ "xloc": [
21120
+ "default.handlebars->container->column_l->p17->p17info->p17graph->1->1->0->3->1->0"
21121
+ ]
21122
+ },
21123
{
21124
"cs": "Načítání…",
21125
"de": "Laden...",
@@ -32945,6 +32951,12 @@
32951
"default.handlebars->29->1420"
32952
]
32953
},
32954
+ {
32955
+ "en": "Show device CPU and memory usage.",
32956
+ "xloc": [
32957
+ "default.handlebars->container->column_l->p17->p17title->devListToolbarViewIcons3"
32958
+ ]
32959
+ },
32960
{
32961
"cs": "Zobrazit informace o umístění zařízení",
32962
"de": "Geräte-Standortinformationen anzeigen",
views/default.handlebars
+93
-5
@@ -875,9 +875,27 @@
875
<div id=p17 style="display:none;margin-left:-18px">
876
<div id="p17title" style="margin-left:18px">
877
<div id="p17BackButton" style="float:left"><div class="backButton" tabindex=0 onclick=goBack() title="Back" onkeypress="if (event.key == 'Enter') goBack()"><div class="backButtonEx"></div></div></div>
878
+ <div id="devListToolbarViewIcons3"><div class="viewSelector" onclick=deskToggleCpuGraph(event) title="Show device CPU and memory usage."><div class="viewSelector6"></div></div></div>
879
<h1>Details - <span id=p17deviceName></span></h1>
880
</div>
880
- <div id=p17info style="overflow-y:auto"></div>
881
+ <div id=p17info style="overflow-y:auto">
882
+ <div id=p17graph style="width:100%">
883
+ <table style=width:100%>
884
+ <tr>
885
+ <td style=width:64px;vertical-align:top>
886
+ <img src=images/details/graph64.png border=0 width=64 />
887
+ </td>
888
+ <td>
889
+ <div class=DevSt style=margin-bottom:3px;margin-left:16px><b>Live Graph</b></div>
890
+ <div style="margin-bottom:10px;margin-left:16px;height:240px;width:calc(100% - 16px);position:relative">
891
+ <canvas id=deviceDetailsStats style="position:absolute;top:0;left:0;right:0;bottom:0"></canvas>
892
+ </div>
893
+ </td>
894
+ </tr>
895
+ </table>
896
+ </div>
897
+ <div id=p17info2></div>
898
+ </div>
899
</div>
900
<div id=p19 style="display:none">
901
<div id="p19title">
@@ -2153,7 +2171,14 @@
2171
if (nodes != null) { for (var i in nodes) { if (nodes[i]._id == message.nodeid) { index = i; break; } } }
2172
if (index != -1) {
2173
// Node was found, dispatch the message
2156
- if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
2174
+ if ((message.type == 'cpuinfo') && (currentNode != null) && (currentNode._id == message.nodeid)) {
2175
+ var now = (Date.now() / 1000), cpu = 0, memory = 0;
2176
+ if (typeof message.cpu.total == 'number') { cpu = message.cpu.total; }
2177
+ if (typeof message.memory.percentConsumed == 'number') { memory = message.memory.percentConsumed; }
2178
+ console.log(message.cpu);
2179
+ deviceDetailsStatsData.push([now, cpu, memory]);
2180
+ deviceDetailsStatsDraw();
2181
+ } else if (message.type == 'console') { p15consoleReceive(nodes[index], message.value, message.source); } // This is a console message.
2182
else if (message.type == 'notify') { // This is a notification message.
2183
var n = getstore('notifications', 0);
2184
if (((n & 8) == 0) && (message.amtMessage != null)) { break; } // Intel AMT desktop & terminal messages should be ignored.
@@ -5583,6 +5608,7 @@
5608
//disconnectAllKvmFunction();
5609
var node = getNodeFromId(nodeid);
5610
if (node == null) return;
5611
+ if ((currentNode == null) || (currentNode._id != node._id) || ((node.conn & 1) == 0)) { deviceDetailsStatsClear(); } // Hide the list cpu/memory graph
5612
var mesh = meshes[node.meshid];
5613
var meshrights = GetNodeRights(node);
5614
var deviceSwitch = ((currentNode == null) || (currentNode._id != nodeid));
@@ -5921,7 +5947,7 @@
5947
meshserver.send({ action: 'lastconnect', nodeid: currentNode._id });
5948
meshserver.send({ action: 'getsysinfo', nodeid: currentNode._id });
5949
meshserver.send({ action: 'getnetworkinfo', nodeid: currentNode._id });
5924
- QH('p17info', '');
5950
+ QH('p17info2', '');
5951
}
5952
5953
// Request device sharing
@@ -8602,6 +8628,67 @@
8628
// DEVICE DETAILS
8629
//
8630
8631
+ var deviceDetailsStats = null;
8632
+ var deviceDetailsStatsTimer = null;
8633
+ var deviceDetailsStatsData = [];
8634
+ var deviceDetailsConfig = {
8635
+ type: 'line',
8636
+ data: {
8637
+ labels: [],
8638
+ datasets: [
8639
+ { label: 'CPU', backgroundColor: 'rgba(134, 16, 158, .5)', borderColor: 'rgb(134, 16, 158)', data: [], fill: true },
8640
+ { label: 'Memory', backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }
8641
+ ] },
8642
+ options: {
8643
+ animation: false,
8644
+ responsive: true,
8645
+ maintainAspectRatio: false,
8646
+ tooltips: { enabled: false },
8647
+ elements: { line: { cubicInterpolationMode: 'monotone' } },
8648
+ scales: {
8649
+ xAxes: [{ type: 'linear', display: true, scaleLabel: { display: false, labelString: '' }, ticks: { min: 0, max: 100 } }],
8650
+ yAxes: [{ type: 'linear', display: true, scaleLabel: { display: false, labelString: '' }, ticks: { min: 0, max: 100 } }]
8651
+ }
8652
+ }
8653
+ };
8654
+
8655
+ function deskToggleCpuGraph() {
8656
+ var visible = (QS('p17graph').display == 'none');
8657
+ if (visible) {
8658
+ QV('p17graph', true);
8659
+ window.deviceDetailsStatsChart = new Chart(document.getElementById('deviceDetailsStats').getContext('2d'), deviceDetailsConfig);
8660
+ deviceDetailsStatsTimer = setInterval(deviceDetailsStatsTimerFunc, 2000);
8661
+ deviceDetailsStatsTimerFunc();
8662
+ } else deviceDetailsStatsClear();
8663
+ }
8664
+
8665
+ function deviceDetailsStatsClear() {
8666
+ QV('p17graph', false);
8667
+ if (window.deviceDetailsStatsChart != null) { delete window.deviceDetailsStatsChart; }
8668
+ if (deviceDetailsStatsTimer != null) { clearInterval(deviceDetailsStatsTimer); deviceDetailsStatsTimer = null; }
8669
+ deviceDetailsStatsData = [];
8670
+ }
8671
+
8672
+ function deviceDetailsStatsTimerFunc() {
8673
+ if (currentNode != null) { meshserver.send({ action: 'msg', type: 'cpuinfo', nodeid: currentNode._id }); }
8674
+ }
8675
+
8676
+ function deviceDetailsStatsDraw() {
8677
+ var now = Date.now() / 1000, oldLimit = (now - 100);
8678
+ while (deviceDetailsStatsData[0][0] < (oldLimit - 5)) { deviceDetailsStatsData.shift(); }
8679
+
8680
+ var cpu = [], memory = [];
8681
+ for (var i in deviceDetailsStatsData) {
8682
+ var d = deviceDetailsStatsData[i];
8683
+ cpu.push({ x: 100 - (d[0] - oldLimit), y: d[1] });
8684
+ memory.push({ x: 100 - (d[0] - oldLimit), y: d[2] });
8685
+ }
8686
+
8687
+ deviceDetailsConfig.data.datasets[0].data = cpu;
8688
+ deviceDetailsConfig.data.datasets[1].data = memory;
8689
+ window.deviceDetailsStatsChart.update();
8690
+ }
8691
+
8692
var DeviceDetailsHardware = null;
8693
var DeviceDetailsNetwork = null;
8694
var DeviceDetailsNodeId = null;
@@ -8842,9 +8929,9 @@
8929
}
8930
8931
if (x == '') {
8845
- QH('p17info', "No information for this device.");
8932
+ QH('p17info2', "No information for this device.");
8933
} else {
8847
- QH('p17info', x);
8934
+ QH('p17info2', x);
8935
}
8936
}
8937
@@ -8932,6 +9019,7 @@
9019
QE('p15uploadCore', false);
9020
QV('p15outputselecttd', false);
9021
}
9022
+ QV('devListToolbarViewIcons3', ((consoleNode.conn & 1) != 0));
9023
}
9024
}
9025