From 12a5ec279bbb798b87184d051ba8043c557753d6 Mon Sep 17 00:00:00 2001 From: alexfriesen Date: Sun, 23 Apr 2017 21:28:37 +0200 Subject: [PATCH 1/2] add performance graphs to serverinfo move serverinfo-bar to seperate file add serverinfo fps chart add network i/o chart --- html/header.html | 40 ++++++++++++ html/serverInfo.html | 53 ++++------------ index.html | 57 +---------------- js/serverInfo.js | 143 +++++++++++++++++++++++++++++++++++++++---- rcon.css | 2 +- 5 files changed, 183 insertions(+), 112 deletions(-) create mode 100644 html/header.html diff --git a/html/header.html b/html/header.html new file mode 100644 index 0000000..d6825a1 --- /dev/null +++ b/html/header.html @@ -0,0 +1,40 @@ + diff --git a/html/serverInfo.html b/html/serverInfo.html index 86da37c..52c4180 100644 --- a/html/serverInfo.html +++ b/html/serverInfo.html @@ -1,57 +1,26 @@ -
-

- {{info.Hostname}} -

+

{{serverinfo.Hostname}}

-
-

{{key}}: {{value}}

+
+

+ {{key}}: + {{value}} +

- -
diff --git a/index.html b/index.html index 1286fbe..761d301 100644 --- a/index.html +++ b/index.html @@ -12,62 +12,7 @@ - +
diff --git a/js/serverInfo.js b/js/serverInfo.js index 56b31d5..08cb728 100644 --- a/js/serverInfo.js +++ b/js/serverInfo.js @@ -1,19 +1,136 @@ +app.controller('ServerInfoController', ServerInfoController); -app.controller( 'ServerInfoController', ServerInfoController ); +function ServerInfoController($scope, rconService, $routeParams, $interval) { -function ServerInfoController( $scope, rconService, $routeParams, $interval ) -{ - $scope.info = {}; + var fpsData = []; + var netData = []; - $scope.refresh = function () - { - rconService.Request( 'serverinfo', $scope, function ( msg ) { - $scope.info = JSON.parse( msg.Message ); - } ); - } + // TODO: move serverinfo to service + $scope.serverinfo = {}; - rconService.InstallService( $scope, $scope.refresh ); + $scope.playersChart = { + options: { + chart: { + type: "pieChart", + height: 400, + x: function(d) { + return d.key; + }, + y: function(d) { + return d.value; + }, + showLabels: false + } + }, + data: [] + }; + + $scope.fpsChart = { + options: { + chart: { + type: 'lineChart', + height: 200, + y: function(d) { + return d.y; + }, + useInteractiveGuideline: true, + showXAxis: false, + duration: 0, + yAxis: { + axisLabel: 'FPS', + tickFormat: function(d) { + return d3.format('.d')(d); + } + } + } + }, + data: [ + { + values: [], + key: 'FPS' + } + ] + }; + + $scope.netChart = { + options: { + chart: { + "type": "stackedAreaChart", + "height": 250, + "useVoronoi": false, + "duration": 0, + "useInteractiveGuideline": true, + showXAxis: false, + "yAxis": { + axisLabel: 'Network', + tickFormat: function(d) { + return d3.format('.d')(d) + 'kb'; + } + } + } + }, + data: [ + { + key: 'IN', + values: [] + }, { + key: 'OUT', + values: [] + } + ] + }; + + rconService.InstallService($scope, _refresh); + + // TODO: move updateinterval to service + var timer = $interval(_refresh, 1000); + $scope.$on("$destroy", function() { + $interval.cancel(timer); + $scope.serverinfo = {}; + }); + + function _refresh() { + rconService.Request('serverinfo', $scope, function(msg) { + _updateData(JSON.parse(msg.Message)); + }); + } + + function _updateData(data) { + $scope.serverinfo = data; + + $scope.playersChart.data.push({'players': data.Players, 'queued': data.Queued, 'joining': data.Joining}); + + _collectChartData(data); + _generateChartData(); + } + + function _collectChartData(data) { + fpsData.push(data.Framerate); + if (fpsData.length > 100) { + fpsData.shift(); + } + + netData.push({in: data.NetworkIn, out: data.NetworkOut}); + if (netData.length > 100) { + netData.shift(); + } + } + + function _generateChartData() { + var fpsChartValues = []; + for (var i = 0; i < fpsData.length; i++) { + fpsChartValues.push({x: i, y: fpsData[i]}); + } + $scope.fpsChart.data[0].values = fpsChartValues; + + var netInChartValues = []; + var netOutChartValues = []; + for (var i = 0; i < netData.length; i++) { + netInChartValues.push({x: i, y: netData[i]. in}); + netOutChartValues.push({x: i, y: netData[i].out}); + } + $scope.netChart.data[0].values = netInChartValues; + $scope.netChart.data[1].values = netOutChartValues; + } - var timer = $interval( $scope.refresh, 500 ); - $scope.$on( "$destroy", function () { $interval.cancel( timer ); } ); } diff --git a/rcon.css b/rcon.css index d62ac92..90b6a00 100644 --- a/rcon.css +++ b/rcon.css @@ -123,7 +123,7 @@ a:hover color: #fff; } -.navbar-default .navbar-nav > li > .navbar-text, +.navbar-default .navbar-text, .navbar-default .navbar-nav > li > a, .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { color: #fff; From cab65aeab7d04eb7651eb5aa4fb644c3147ea9c6 Mon Sep 17 00:00:00 2001 From: alexfriesen Date: Tue, 25 Apr 2017 19:03:03 +0200 Subject: [PATCH 2/2] change charts change data collection charts are collapsible show fps and entity count in one chart improve network chart add player chart (queued, joining, playing, free) --- html/serverInfo.html | 72 ++++++++++++++++- index.html | 4 +- js/serverInfo.js | 183 ++++++++++++++++++++++++++++++++----------- 3 files changed, 210 insertions(+), 49 deletions(-) diff --git a/html/serverInfo.html b/html/serverInfo.html index 52c4180..ecdd567 100644 --- a/html/serverInfo.html +++ b/html/serverInfo.html @@ -1,4 +1,4 @@ -
+
@@ -17,8 +17,74 @@
- - + +
+
+ +

+ Server Performance +

+
+
+
+ +
+
+
+ +
+
+ + +

+ Server Networking +

+
+
+
+ +
+
+
+ +
+
+ +

+ Players +

+
+
+
+ +
+
+
+
diff --git a/index.html b/index.html index 761d301..76ecddf 100644 --- a/index.html +++ b/index.html @@ -51,8 +51,8 @@ - - + + diff --git a/js/serverInfo.js b/js/serverInfo.js index 08cb728..8dacc45 100644 --- a/js/serverInfo.js +++ b/js/serverInfo.js @@ -1,9 +1,10 @@ app.controller('ServerInfoController', ServerInfoController); -function ServerInfoController($scope, rconService, $routeParams, $interval) { +var DATA_LIMIT = 100; +var recordedData = []; - var fpsData = []; - var netData = []; +function ServerInfoController($scope, rconService, $routeParams, $interval) { + $scope.useCharts = false; // TODO: move serverinfo to service $scope.serverinfo = {}; @@ -11,43 +12,98 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) { $scope.playersChart = { options: { chart: { - type: "pieChart", - height: 400, + type: 'pieChart', + height: 250, + margin: { + top: 0, + right: 75, + bottom: 0, + left: 75 + }, + donut: true, x: function(d) { return d.key; }, y: function(d) { - return d.value; + return d.y; }, - showLabels: false + yAxis: { + axisLabel: 'Slots', + tickFormat: function(d) { + return d3.format('.d')(d); + } + }, + showLabels: true, + pie: { + startAngle: function(d) { + return d.startAngle / 2 - Math.PI / 2 + }, + endAngle: function(d) { + return d.endAngle / 2 - Math.PI / 2 + } + }, + duration: 500 } }, data: [] }; - $scope.fpsChart = { + $scope.performanceChart = { options: { chart: { - type: 'lineChart', + type: 'multiChart', height: 200, - y: function(d) { - return d.y; + margin: { + top: 30, + right: 75, + bottom: 40, + left: 75 + }, + color: [ + 'darkred', 'yellowgreen' + ], + duration: 0, + lines1: { + duration: 0 + }, + lines2: { + duration: 0 }, useInteractiveGuideline: true, - showXAxis: false, - duration: 0, - yAxis: { - axisLabel: 'FPS', + yAxis1: { + axisLabel: 'Framerate', tickFormat: function(d) { - return d3.format('.d')(d); + return d3.format(',d')(d); + } + }, + yAxis2: { + axisLabel: 'Entities', + tickFormat: function(d) { + return d3.format(',d')(d); + }, + // axisLabelDistance: 12 + }, + xAxis: { + axisLabel: "Time", + tickFormat: function(d) { + return d3.time.format('%H:%M:%S')(new Date(d)) } } } }, data: [ { - values: [], - key: 'FPS' + key: 'Framerate', + type: "line", + duration: 0, + yAxis: 1, + values: [] + }, { + key: 'Entities', + type: 'line', + duration: 0, + yAxis: 2, + values: [] } ] }; @@ -55,16 +111,36 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) { $scope.netChart = { options: { chart: { - "type": "stackedAreaChart", - "height": 250, - "useVoronoi": false, - "duration": 0, - "useInteractiveGuideline": true, - showXAxis: false, - "yAxis": { + type: 'stackedAreaChart', + height: 250, + margin: { + top: 0, + right: 75, + bottom: 40, + left: 75 + }, + useVoronoi: false, + duration: 0, + useInteractiveGuideline: true, + yAxis: { axisLabel: 'Network', + tickFormat: function(bytes) { + var fmt = d3.format('.0f'); + if (bytes < 1024) { + return fmt(bytes) + 'B'; + } else if (bytes < 1024 * 1024) { + return fmt(bytes / 1024) + 'kB'; + } else if (bytes < 1024 * 1024 * 1024) { + return fmt(bytes / 1024 / 1024) + 'MB'; + } else { + return fmt(bytes / 1024 / 1024 / 1024) + 'GB'; + } + } + }, + xAxis: { + axisLabel: "Time", tickFormat: function(d) { - return d3.format('.d')(d) + 'kb'; + return d3.time.format('%H:%M:%S')(new Date(d)) } } } @@ -98,37 +174,56 @@ function ServerInfoController($scope, rconService, $routeParams, $interval) { function _updateData(data) { $scope.serverinfo = data; - $scope.playersChart.data.push({'players': data.Players, 'queued': data.Queued, 'joining': data.Joining}); - - _collectChartData(data); - _generateChartData(); + if ($scope.useCharts) { + _collectChartData(data); + _generateChartData(); + } } function _collectChartData(data) { - fpsData.push(data.Framerate); - if (fpsData.length > 100) { - fpsData.shift(); - } + // player chart + $scope.playersChart.data = [ + { + key: 'Queued', + y: data.Queued + }, { + key: 'Joining', + y: data.Joining + }, { + key: 'Players', + y: data.Players + }, { + key: 'Free', + y: (data.MaxPlayers - (data.Joining + data.Players)) + } + ]; - netData.push({in: data.NetworkIn, out: data.NetworkOut}); - if (netData.length > 100) { - netData.shift(); + recordedData.push({ts: Date.now(), data: data}); + if (recordedData.length > DATA_LIMIT) { + recordedData = recordedData.slice(Math.max(recordedData.length - DATA_LIMIT, 1)); } } function _generateChartData() { + var fpsChartValues = []; - for (var i = 0; i < fpsData.length; i++) { - fpsChartValues.push({x: i, y: fpsData[i]}); - } - $scope.fpsChart.data[0].values = fpsChartValues; + var entChartValues = []; var netInChartValues = []; var netOutChartValues = []; - for (var i = 0; i < netData.length; i++) { - netInChartValues.push({x: i, y: netData[i]. in}); - netOutChartValues.push({x: i, y: netData[i].out}); + + for (var i = 0; i < recordedData.length; i++) { + var record = recordedData[i]; + fpsChartValues.push({x: record.ts, y: record.data.Framerate}); + entChartValues.push({x: record.ts, y: record.data.EntityCount}); + + netInChartValues.push({x: record.ts, y: record.data.NetworkIn}); + netOutChartValues.push({x: record.ts, y: record.data.NetworkOut}); } + + $scope.performanceChart.data[0].values = fpsChartValues; + $scope.performanceChart.data[1].values = entChartValues; + $scope.netChart.data[0].values = netInChartValues; $scope.netChart.data[1].values = netOutChartValues; }