-
-
-
-
- {{ 'system.title' | tr }} - {{ 'main.action.logs' | tr }} - -
+
+
-
+
+ {{ 'system.title' | tr }} + {{ 'main.action.logs' | tr }} + +
+
-
-
+
+
-
+
+
+
- + Graphs + +
+ +
+
+
+
+ + +
-
+ + + +
{{ 'system.systemMemory.graphSubtext' | tr }}
-
-
-
-
+
-
+ {{ 'system.diskUsage.title' | tr }} + +
-
-
+
\ No newline at end of file
diff --git a/src/views/system.js b/src/views/system.js
index b248ea779..4a6347ca7 100644
--- a/src/views/system.js
+++ b/src/views/system.js
@@ -9,13 +9,7 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
$scope.config = Client.getConfig();
$scope.memory = null;
- $scope.busy = true;
- $scope.activeTab = 0;
$scope.volumesById = {};
- $scope.disks = [];
- $scope.period = 6;
- $scope.memoryChart = null;
- $scope.diskChart = null;
// http://stackoverflow.com/questions/1484506/random-color-generator-in-javascript
function getRandomColor() {
@@ -34,15 +28,17 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
return getRandomColor();
}
- $scope.refresh = function () {
- $scope.busy = true;
+ $scope.disks = {
+ busy: true,
+ disks: [],
- Client.getSystemGraphs($scope.period * 60, function (error, result) {
- if (error) return console.error('Failed to fetch system graphs:', error);
+ refresh: function () {
+ $scope.disks.busy = true;
- $scope.disks = result.disks; // [ { filesystem, type, size, used, available, capacity, mountpoint }]
+ var result;
+ $scope.disks.disks = result.disks; // [ { filesystem, type, size, used, available, capacity, mountpoint }]
- $scope.disks.forEach(function (disk) {
+ $scope.disks.disks.forEach(function (disk) {
var usageOther = disk.occupied;
colorIndex = 0;
@@ -57,7 +53,7 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
disk.contains.sort(function (x, y) { return y.usage - x.usage; }); // sort by usage
- if ($scope.disks[0] === disk) { // the root mount point is the first disk. keep this 'contains' in the end
+ if ($scope.disks.disks[0] === disk) { // the root mount point is the first disk. keep this 'contains' in the end
disk.contains.push({
type: 'standard',
label: 'Everything else (Ubuntu, Swap, etc)',
@@ -76,120 +72,139 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
}
});
- // in minutes
- var timePeriod = $scope.period * 60;
-
- // keep in sync with graphs.js
- var timeBucketSizeMinutes = timePeriod > (24 * 60) ? (6*60) : 5;
- var steps = Math.floor(timePeriod/timeBucketSizeMinutes);
-
- var labels = new Array(steps).fill(0);
- labels = labels.map(function (v, index) {
- var dateTime = new Date(Date.now() - ((timePeriod - (index * timeBucketSizeMinutes)) * 60 * 1000));
-
- if ($scope.period > 24) {
- return dateTime.toLocaleDateString();
- } else {
- return dateTime.toLocaleTimeString();
- }
- });
-
- var borderColors = [ '#2196F3', '#FF6384' ];
- var backgroundColors = [ '#82C4F844', '#FF63844F' ];
-
- function fillGraph(canvasId, contents, chartPropertyName, divisor, max) {
- if (!contents || !contents[0]) return; // no data available yet
-
- var datasets = [];
-
- contents.forEach(function (content, index) {
-
- // fill holes with previous value
- var cur = 0;
- content.data.datapoints.forEach(function (d) {
- if (d[0] === null) d[0] = cur;
- else cur = d[0];
- });
-
- var datapoints = Array(steps).map(function () { return '0'; });
-
- // walk backwards and fill up the datapoints
- content.data.datapoints.reverse().forEach(function (d, index) {
- datapoints[datapoints.length-1-index] = (d[0] / divisor).toFixed(2);
- // return parseInt((d[0] / divisor).toFixed(2));
- });
-
- datasets.push({
- label: content.label,
- backgroundColor: backgroundColors[index],
- borderColor: borderColors[index%2], // FIXME give real distinct colors
- borderWidth: 1,
- radius: 0,
- data: datapoints,
- cubicInterpolationMode: 'monotone',
- tension: 0.4
- });
- });
-
- var graphData = {
- labels: labels,
- datasets: datasets
- };
-
- var options = {
- responsive: true,
- maintainAspectRatio: true,
- aspectRatio: 2.5,
- animation: false,
- plugins: {
- legend: {
- display: false
- }
- },
- interaction: {
- intersect: false,
- mode: 'index',
- },
- scales: {
- x: {
- ticks: { autoSkipPadding: 50, maxRotation: 0 }
- },
- y: {
- min: 0,
- beginAtZero: true
- }
- }
- };
-
- if (max) options.scales.y.max = max;
-
- var ctx = $(canvasId).get(0).getContext('2d');
-
- if ($scope[chartPropertyName]) $scope[chartPropertyName].destroy();
- $scope[chartPropertyName] = new Chart(ctx, { type: 'line', data: graphData, options: options });
- }
-
- var threshold = 1024 * 1024 * 1024;
- var appsWithHighMemory = Object.keys(result.apps).map(function (appId) {
- result.apps[appId].id = appId;
- return result.apps[appId];
- }).filter(function (app) {
- if (!app.memory) return false; // not sure why we get empty objects
- return app.memory.datapoints.some(function (d) { return d[0] > threshold; });
- }).map(function (app) {
- return { data: app.memory, label: app.id };
- });
-
- fillGraph('#graphsCPUChart', [{ data: result.cpu, label: 'CPU' }], 'cpuChart', 100, 1);
- fillGraph('#graphsSystemMemoryChart', [{ data: result.memory, label: 'Memory' }].concat(appsWithHighMemory), 'memoryChart', 1024 * 1024, Number.parseInt($scope.memory.memory / 1024 / 1024));
-
- $scope.busy = false;
- });
+ $scope.disks.busy = false;
+ }
};
- $scope.setPeriod = function (hours) {
- $scope.period = hours;
- $scope.refresh();
+ $scope.graphs = {
+ busy: false,
+ period: 6,
+ memoryChart: null,
+ diskChart: null,
+
+ setPeriod: function (hours) {
+ $scope.graphs.period = hours;
+ $scope.graphs.refresh();
+ },
+
+ refresh: function () {
+ $scope.graphs.busy = true;
+
+ Client.getSystemGraphs($scope.graphs.period * 60, function (error, result) {
+ if (error) return console.error('Failed to fetch system graphs:', error);
+
+ // in minutes
+ var timePeriod = $scope.graphs.period * 60;
+
+ // keep in sync with graphs.js
+ var timeBucketSizeMinutes = timePeriod > (24 * 60) ? (6*60) : 5;
+ var steps = Math.floor(timePeriod/timeBucketSizeMinutes);
+
+ var labels = new Array(steps).fill(0);
+ labels = labels.map(function (v, index) {
+ var dateTime = new Date(Date.now() - ((timePeriod - (index * timeBucketSizeMinutes)) * 60 * 1000));
+
+ if ($scope.graphs.period > 24) {
+ return dateTime.toLocaleDateString();
+ } else {
+ return dateTime.toLocaleTimeString();
+ }
+ });
+
+ var colors = [ '#2196F3', '#FF6384' ];
+
+ function fillGraph(canvasId, contents, chartPropertyName, divisor, max) {
+ if (!contents || !contents[0]) return; // no data available yet
+
+ var datasets = [];
+
+ contents.forEach(function (content, index) {
+
+ // fill holes with previous value
+ var cur = 0;
+ content.data.datapoints.forEach(function (d) {
+ if (d[0] === null) d[0] = cur;
+ else cur = d[0];
+ });
+
+ var datapoints = Array(steps).map(function () { return '0'; });
+
+ // walk backwards and fill up the datapoints
+ content.data.datapoints.reverse().forEach(function (d, index) {
+ datapoints[datapoints.length-1-index] = (d[0] / divisor).toFixed(2);
+ // return parseInt((d[0] / divisor).toFixed(2));
+ });
+
+ var color = index > 2 ? getRandomColor() : colors[index];
+ datasets.push({
+ label: content.label,
+ backgroundColor: color + '4F',
+ borderColor: color, // FIXME give real distinct colors
+ borderWidth: 1,
+ radius: 0,
+ data: datapoints,
+ cubicInterpolationMode: 'monotone',
+ tension: 0.4
+ });
+ });
+
+ var graphData = {
+ labels: labels,
+ datasets: datasets
+ };
+
+ var options = {
+ responsive: true,
+ maintainAspectRatio: true,
+ aspectRatio: 2.5,
+ animation: false,
+ plugins: {
+ legend: {
+ display: false
+ }
+ },
+ interaction: {
+ intersect: false,
+ mode: 'index',
+ },
+ scales: {
+ x: {
+ ticks: { autoSkipPadding: 50, maxRotation: 0 }
+ },
+ y: {
+ min: 0,
+ beginAtZero: true
+ }
+ }
+ };
+
+ if (max) options.scales.y.max = max;
+
+ var ctx = $(canvasId).get(0).getContext('2d');
+
+ if ($scope.graphs[chartPropertyName]) $scope.graphs[chartPropertyName].destroy();
+ $scope.graphs[chartPropertyName] = new Chart(ctx, { type: 'line', data: graphData, options: options });
+ }
+
+ // var threshold = 1024 * 1024;
+ // var appsWithHighMemory = Object.keys(result.apps).map(function (appId) {
+ // result.apps[appId].id = appId;
+ // return result.apps[appId];
+ // }).filter(function (app) {
+ // if (!app.memory) return false; // not sure why we get empty objects
+ // return app.memory.datapoints.some(function (d) { return d[0] > threshold; });
+ // }).map(function (app) {
+ // return { data: app.memory, label: app.id };
+ // });
+
+ var appsWithHighMemory = [];
+
+ fillGraph('#graphsCPUChart', [{ data: result.cpu, label: 'CPU' }], 'cpuChart', 100, 1);
+ fillGraph('#graphsSystemMemoryChart', [{ data: result.memory, label: 'Memory' }].concat(appsWithHighMemory), 'memoryChart', 1024 * 1024, Number.parseInt($scope.memory.memory / 1024 / 1024));
+
+ $scope.graphs.busy = false;
+ });
+ }
};
Client.onReady(function () {
@@ -204,7 +219,8 @@ angular.module('Application').controller('SystemController', ['$scope', '$locati
$scope.volumesById = {};
volumes.forEach(function (v) { $scope.volumesById[v.id] = v; });
- $scope.refresh();
+ $scope.graphs.refresh();
+ // $scope.disks.refresh();
});
});
});
+
+
-
-
-
+
-
-
- @@ -57,22 +84,7 @@
-
-
-
+