diff --git a/src/theme.scss b/src/theme.scss index 948859ae4..fd5b43071 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -566,7 +566,7 @@ multiselect { } .card { - min-height: 383px; + min-height: 418px; } @media(min-width:768px) { diff --git a/src/views/app.html b/src/views/app.html index 93bf2b5e1..21fed25ae 100644 --- a/src/views/app.html +++ b/src/views/app.html @@ -464,6 +464,7 @@
Location
Access Control
Resources
+
Graphs
Security
Email
Updates
@@ -805,6 +806,29 @@ +
+
+
+ + + + + +
+
+
+
diff --git a/src/views/app.js b/src/views/app.js index a8e985194..aee589983 100644 --- a/src/views/app.js +++ b/src/views/app.js @@ -8,6 +8,7 @@ /* global ISTATES */ /* global ERROR */ /* global moment */ +/* global Chart */ angular.module('Application').controller('AppController', ['$scope', '$location', '$timeout', '$interval', '$route', '$routeParams', 'Client', function ($scope, $location, $timeout, $interval, $route, $routeParams, Client) { Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); }); @@ -586,6 +587,82 @@ angular.module('Application').controller('AppController', ['$scope', '$location' } }; + $scope.graphs = { + error: {}, + + period: 6, + periodLabel: '6 hours', + memoryChart: null, + diskChart: null, + + setPeriod: function (hours, label) { + $scope.graphs.period = hours; + $scope.graphs.periodLabel = label; + $scope.graphs.show(); + }, + + show: function () { + var timePeriod = $scope.graphs.period * 60; // in minutes + var timeBucketSize = 60; // in minutes + + function fillGraph(canvasId, data, label, chartPropertyName) { + // translate the data from bytes to MB + var datapoints = data.datapoints.map(function (d) { return parseInt((d[0] / 1024 / 1024).toFixed(2)); }); + var labels = datapoints.map(function (d, index) { + var dateTime = new Date(Date.now() - ((timePeriod - (index * timeBucketSize)) * 60 *1000)); + return ('0' + dateTime.getHours()).slice(-2) + ':00'; + }); + + var data = { + labels: labels, + datasets: [{ + label: label, + backgroundColor: '#82C4F8', + borderColor: '#2196F3', + borderWidth: 2, + pointBackgroundColor: 'rgba(151,187,205,1)', + pointBorderColor: '#2196F3', + pointHoverBackgroundColor: '#82C4F8', + pointHoverBorderColor: '#82C4F8', + data: datapoints + }] + }; + + var options = { + legend: { + display: false + }, + tooltips: { + intersect: false + }, + scales: { + yAxes: [{ + ticks: { + min: 0, + beginAtZero: true + } + }] + } + }; + + var ctx = $(canvasId).get(0).getContext('2d'); + + if ($scope.graphs[chartPropertyName]) $scope.graphs[chartPropertyName].destroy(); + $scope.graphs[chartPropertyName] = new Chart(ctx, { type: 'line', data: data, options: options }); + } + + var memoryQuery = 'summarize(collectd.localhost.table-' + appId + '-memory.gauge-rss, "' + timeBucketSize + 'min", "avg")'; + var diskQuery = 'absolute(collectd.localhost.du-' + appId + '.capacity-usage)'; + + Client.graphs([memoryQuery, diskQuery], '-' + timePeriod + 'min', {}, function (error, result) { + if (error) return console.error(error); + + fillGraph('#graphsMemoryChart', result[0], 'Memory', 'memoryChart'); + fillGraph('#graphsDiskChart', result[1], 'Disk', 'diskChart'); + }); + } + }; + $scope.email = { busy: false, error: {},