angular.module('portainer.docker') .controller('ContainerStatsController', ['$q', '$scope', '$transition$', '$document', '$interval', 'ContainerService', 'ChartService', 'Notifications', 'HttpRequestHelper', function ($q, $scope, $transition$, $document, $interval, ContainerService, ChartService, Notifications, HttpRequestHelper) { $scope.state = { refreshRate: '5', networkStatsUnavailable: false }; $scope.$on('$destroy', function() { stopRepeater(); }); function stopRepeater() { var repeater = $scope.repeater; if (angular.isDefined(repeater)) { $interval.cancel(repeater); repeater = null; } } function updateNetworkChart(stats, chart) { if (stats.Networks.length > 0) { var rx = stats.Networks[0].rx_bytes; var tx = stats.Networks[0].tx_bytes; var label = moment(stats.read).format('HH:mm:ss'); ChartService.UpdateNetworkChart(label, rx, tx, chart); } } function updateMemoryChart(stats, chart) { var label = moment(stats.read).format('HH:mm:ss'); ChartService.UpdateMemoryChart(label, stats.MemoryUsage, stats.MemoryCache, chart); } function updateCPUChart(stats, chart) { var label = moment(stats.read).format('HH:mm:ss'); var value = stats.isWindows ? calculateCPUPercentWindows(stats) : calculateCPUPercentUnix(stats); ChartService.UpdateCPUChart(label, value, chart); } function calculateCPUPercentUnix(stats) { var cpuPercent = 0.0; var cpuDelta = stats.CurrentCPUTotalUsage - stats.PreviousCPUTotalUsage; var systemDelta = stats.CurrentCPUSystemUsage - stats.PreviousCPUSystemUsage; if (systemDelta > 0.0 && cpuDelta > 0.0) { cpuPercent = (cpuDelta / systemDelta) * stats.CPUCores * 100.0; } return cpuPercent; } function calculateCPUPercentWindows(stats) { var possIntervals = stats.NumProcs * parseFloat( moment(stats.read, 'YYYY-MM-DDTHH:mm:ss.SSSSSSSSSZ').valueOf() - moment(stats.preread, 'YYYY-MM-DDTHH:mm:ss.SSSSSSSSSZ').valueOf()); var windowsCpuUsage = 0.0; if(possIntervals > 0) { windowsCpuUsage = parseFloat(stats.CurrentCPUTotalUsage - stats.PreviousCPUTotalUsage) / parseFloat(possIntervals * 100); } return windowsCpuUsage; } $scope.changeUpdateRepeater = function() { var networkChart = $scope.networkChart; var cpuChart = $scope.cpuChart; var memoryChart = $scope.memoryChart; stopRepeater(); setUpdateRepeater(networkChart, cpuChart, memoryChart); $('#refreshRateChange').show(); $('#refreshRateChange').fadeOut(1500); }; function startChartUpdate(networkChart, cpuChart, memoryChart) { $q.all({ stats: ContainerService.containerStats($transition$.params().id), top: ContainerService.containerTop($transition$.params().id) }) .then(function success(data) { var stats = data.stats; $scope.processInfo = data.top; if (stats.Networks.length === 0) { $scope.state.networkStatsUnavailable = true; } updateNetworkChart(stats, networkChart); updateMemoryChart(stats, memoryChart); updateCPUChart(stats, cpuChart); setUpdateRepeater(networkChart, cpuChart, memoryChart); }) .catch(function error(err) { stopRepeater(); Notifications.error('Failure', err, 'Unable to retrieve container statistics'); }); } function setUpdateRepeater(networkChart, cpuChart, memoryChart) { var refreshRate = $scope.state.refreshRate; $scope.repeater = $interval(function() { $q.all({ stats: ContainerService.containerStats($transition$.params().id), top: ContainerService.containerTop($transition$.params().id) }) .then(function success(data) { var stats = data.stats; $scope.processInfo = data.top; updateNetworkChart(stats, networkChart); updateMemoryChart(stats, memoryChart); updateCPUChart(stats, cpuChart); }) .catch(function error(err) { stopRepeater(); Notifications.error('Failure', err, 'Unable to retrieve container statistics'); }); }, refreshRate * 1000); } function initCharts() { var networkChartCtx = $('#networkChart'); var networkChart = ChartService.CreateNetworkChart(networkChartCtx); $scope.networkChart = networkChart; var cpuChartCtx = $('#cpuChart'); var cpuChart = ChartService.CreateCPUChart(cpuChartCtx); $scope.cpuChart = cpuChart; var memoryChartCtx = $('#memoryChart'); var memoryChart = ChartService.CreateMemoryChart(memoryChartCtx); $scope.memoryChart = memoryChart; startChartUpdate(networkChart, cpuChart, memoryChart); } function initView() { HttpRequestHelper.setPortainerAgentTargetHeader($transition$.params().nodeName); ContainerService.container($transition$.params().id) .then(function success(data) { $scope.container = data; }) .catch(function error(err) { Notifications.error('Failure', err, 'Unable to retrieve container information'); }); $document.ready(function() { initCharts(); }); } initView(); }]);