mirror of
https://github.com/portainer/portainer.git
synced 2025-07-23 15:29:42 +02:00
Current progress on stats page, nonfunctional.
This commit is contained in:
parent
66894e7596
commit
b7daf91723
6 changed files with 119 additions and 3 deletions
|
@ -1,4 +1,4 @@
|
||||||
angular.module('dockerui', ['dockerui.templates', 'ngRoute', 'dockerui.services', 'dockerui.filters', 'masthead', 'footer', 'dashboard', 'container', 'containers', 'containersNetwork', 'images', 'image', 'pullImage', 'startContainer', 'sidebar', 'info', 'builder', 'containerLogs', 'containerTop', 'events'])
|
angular.module('dockerui', ['dockerui.templates', 'ngRoute', 'dockerui.services', 'dockerui.filters', 'masthead', 'footer', 'dashboard', 'container', 'containers', 'containersNetwork', 'images', 'image', 'pullImage', 'startContainer', 'sidebar', 'info', 'builder', 'containerLogs', 'containerTop', 'events', 'stats'])
|
||||||
.config(['$routeProvider', function ($routeProvider) {
|
.config(['$routeProvider', function ($routeProvider) {
|
||||||
'use strict';
|
'use strict';
|
||||||
$routeProvider.when('/', {
|
$routeProvider.when('/', {
|
||||||
|
@ -21,6 +21,10 @@ angular.module('dockerui', ['dockerui.templates', 'ngRoute', 'dockerui.services'
|
||||||
templateUrl: 'app/components/containerTop/containerTop.html',
|
templateUrl: 'app/components/containerTop/containerTop.html',
|
||||||
controller: 'ContainerTopController'
|
controller: 'ContainerTopController'
|
||||||
});
|
});
|
||||||
|
$routeProvider.when('/containers/:id/stats', {
|
||||||
|
templateUrl: 'app/components/stats/stats.html',
|
||||||
|
controller: 'StatsController'
|
||||||
|
});
|
||||||
$routeProvider.when('/containers_network', {
|
$routeProvider.when('/containers_network', {
|
||||||
templateUrl: 'app/components/containersNetwork/containersNetwork.html',
|
templateUrl: 'app/components/containersNetwork/containersNetwork.html',
|
||||||
controller: 'ContainersNetworkController'
|
controller: 'ContainersNetworkController'
|
||||||
|
|
|
@ -133,6 +133,10 @@
|
||||||
<td>Logs:</td>
|
<td>Logs:</td>
|
||||||
<td><a href="#/containers/{{ container.Id }}/logs">stdout/stderr</a></td>
|
<td><a href="#/containers/{{ container.Id }}/logs">stdout/stderr</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Stats:</td>
|
||||||
|
<td><a href="#/containers/{{ container.Id }}/stats">stats</a></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Top:</td>
|
<td>Top:</td>
|
||||||
<td><a href="#/containers/{{ container.Id }}/top">Top</a></td>
|
<td><a href="#/containers/{{ container.Id }}/top">Top</a></td>
|
||||||
|
|
21
app/components/stats/stats.html
Normal file
21
app/components/stats/stats.html
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<h2>Stats</h2>
|
||||||
|
<canvas id="cpu-stats-chart" width="700"></canvas>
|
||||||
|
<br>
|
||||||
|
<table class="table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Time read</th>
|
||||||
|
<th>CPU usage</th>
|
||||||
|
<th>Stat</th>
|
||||||
|
</tr>
|
||||||
|
<tr ng-repeat="stat in dockerStats">
|
||||||
|
<td ng-bind="stat.read"/>
|
||||||
|
<td ng-bind="calculateCPUPercent(stat)"/>
|
||||||
|
<td ng-bind="stat"/>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
56
app/components/stats/statsController.js
Normal file
56
app/components/stats/statsController.js
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
angular.module('stats', [])
|
||||||
|
.controller('StatsController', ['Settings', '$scope', 'Messages', '$timeout', 'Container', 'LineChart', '$routeParams', function (Settings, $scope, Messages, $timeout, Container, LineChart, $routeParams) {
|
||||||
|
var sessionKey = 'dockeruiStats-' + $routeParams.id;
|
||||||
|
var localData = sessionStorage.getItem(sessionKey);
|
||||||
|
if (localData) {
|
||||||
|
$scope.dockerStats = localData;
|
||||||
|
} else {
|
||||||
|
$scope.dockerStats = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updateStats() {
|
||||||
|
Container.stats({id: $routeParams.id}, function (d) {
|
||||||
|
console.log(d);
|
||||||
|
var arr = Object.keys(d).map(function (key) {return d[key];});
|
||||||
|
if (arr.join('').indexOf('no such id') !== -1) {
|
||||||
|
Messages.error('Unable to retrieve container stats', 'Has this container been removed?');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$scope.dockerStats.push(d);
|
||||||
|
sessionStorage.setItem(sessionKey, $scope.dockerStats);
|
||||||
|
$timeout(updateStats, 1000);
|
||||||
|
// Update graph with latest data
|
||||||
|
updateChart($scope.dockerStats);
|
||||||
|
}, function () {
|
||||||
|
Messages.error('Unable to retrieve container stats', 'Has this container been removed?');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStats();
|
||||||
|
|
||||||
|
$scope.calculateCPUPercent = function (stats) {
|
||||||
|
// Same algorithm the official client uses: https://github.com/docker/docker/blob/master/api/client/stats.go#L195-L208
|
||||||
|
var prevCpu = stats.precpu_stats;
|
||||||
|
var curCpu = stats.cpu_stats;
|
||||||
|
|
||||||
|
var cpuPercent = 0.0;
|
||||||
|
|
||||||
|
// calculate the change for the cpu usage of the container in between readings
|
||||||
|
var cpuDelta = curCpu.cpu_usage.total_usage - prevCpu.cpu_usage.total_usage;
|
||||||
|
// calculate the change for the entire system between readings
|
||||||
|
var systemDelta = curCpu.system_cpu_usage - prevCpu.system_cpu_usage;
|
||||||
|
|
||||||
|
if (systemDelta > 0.0 && cpuDelta > 0.0) {
|
||||||
|
cpuPercent = (cpuDelta / systemDelta) * curCpu.cpu_usage.percpu_usage.size() * 100.0;
|
||||||
|
}
|
||||||
|
return cpuPercent
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateChart(data) {
|
||||||
|
// TODO: Build data in the right format and create chart.
|
||||||
|
//LineChart.build('#cpu-stats-chart', $scope.dockerStats, function (d) {
|
||||||
|
// return $scope.calculateCPUPercent(d)
|
||||||
|
//});
|
||||||
|
}
|
||||||
|
}]);
|
|
@ -17,7 +17,8 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
changes: {method: 'GET', params: {action: 'changes'}, isArray: true},
|
changes: {method: 'GET', params: {action: 'changes'}, isArray: true},
|
||||||
create: {method: 'POST', params: {action: 'create'}},
|
create: {method: 'POST', params: {action: 'create'}},
|
||||||
remove: {method: 'DELETE', params: {id: '@id', v: 0}},
|
remove: {method: 'DELETE', params: {id: '@id', v: 0}},
|
||||||
rename: {method: 'POST', params: {id: '@id', action: 'rename'}, isArray: false}
|
rename: {method: 'POST', params: {id: '@id', action: 'rename'}, isArray: false},
|
||||||
|
stats: {method: 'GET', params: {id: '@id', stream: false, action: 'stats'}}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.factory('ContainerCommit', function ($resource, $http, Settings) {
|
.factory('ContainerCommit', function ($resource, $http, Settings) {
|
||||||
|
@ -192,7 +193,6 @@ angular.module('dockerui.services', ['ngResource'])
|
||||||
})
|
})
|
||||||
.factory('LineChart', function (Settings) {
|
.factory('LineChart', function (Settings) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var url = Settings.rawUrl + '/build';
|
|
||||||
return {
|
return {
|
||||||
build: function (id, data, getkey) {
|
build: function (id, data, getkey) {
|
||||||
var chart = new Chart($(id).get(0).getContext("2d"));
|
var chart = new Chart($(id).get(0).getContext("2d"));
|
||||||
|
|
31
test/unit/app/components/statsController.spec.js
Normal file
31
test/unit/app/components/statsController.spec.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
describe("StatsController", function () {
|
||||||
|
var $scope, $httpBackend, $routeParams;
|
||||||
|
|
||||||
|
beforeEach(angular.mock.module('dockerui'));
|
||||||
|
|
||||||
|
beforeEach(inject(function (_$rootScope_, _$httpBackend_, $controller, _$routeParams_) {
|
||||||
|
$scope = _$rootScope_.$new();
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$routeParams = _$routeParams_;
|
||||||
|
$routeParams.id = 'b17882378cee8ec0136f482681b764cca430befd52a9bfd1bde031f49b8bba9f';
|
||||||
|
$controller('StatsController', {
|
||||||
|
'$scope': $scope,
|
||||||
|
'$routeParams': $routeParams
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("should test controller initialize", function () {
|
||||||
|
$httpBackend.expectGET('dockerapi/containers/b17882378cee8ec0136f482681b764cca430befd52a9bfd1bde031f49b8bba9f/stats?stream=false').respond(200);
|
||||||
|
//expect($scope.ps_args).toBeDefined();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("a correct top request to the Docker remote API", function () {
|
||||||
|
//$httpBackend.expectGET('dockerapi/containers/' + $routeParams.id + '/top?ps_args=').respond(200);
|
||||||
|
//$routeParams.id = '123456789123456789123456789';
|
||||||
|
//$scope.ps_args = 'aux';
|
||||||
|
//$httpBackend.expectGET('dockerapi/containers/' + $routeParams.id + '/top?ps_args=' + $scope.ps_args).respond(200);
|
||||||
|
//$scope.getTop();
|
||||||
|
//$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue