import moment from 'moment'; angular.module('portainer.docker').controller('ContainerStatsController', [ '$q', '$scope', '$transition$', '$document', '$interval', 'ContainerService', 'ChartService', 'Notifications', 'HttpRequestHelper', 'endpoint', function ($q, $scope, $transition$, $document, $interval, ContainerService, ChartService, Notifications, HttpRequestHelper, endpoint) { $scope.state = { refreshRate: '5', networkStatsUnavailable: false, ioStatsUnavailable: 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 updateIOChart(stats, chart) { var label = moment(stats.read).format('HH:mm:ss'); if (stats.noIOData !== true) { ChartService.UpdateIOChart(label, stats.BytesRead, stats.BytesWrite, 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; var ioChart = $scope.ioChart; stopRepeater(); setUpdateRepeater(networkChart, cpuChart, memoryChart, ioChart); $('#refreshRateChange').show(); $('#refreshRateChange').fadeOut(1500); }; function startChartUpdate(networkChart, cpuChart, memoryChart, ioChart) { $q.all({ stats: ContainerService.containerStats(endpoint.Id, $transition$.params().id), top: ContainerService.containerTop(endpoint.Id, $transition$.params().id), }) .then(function success(data) { var stats = data.stats; $scope.processInfo = data.top; if (stats.Networks.length === 0) { $scope.state.networkStatsUnavailable = true; } if (stats.noIOData === true) { $scope.state.ioStatsUnavailable = true; } updateNetworkChart(stats, networkChart); updateMemoryChart(stats, memoryChart); updateCPUChart(stats, cpuChart); updateIOChart(stats, ioChart); setUpdateRepeater(networkChart, cpuChart, memoryChart, ioChart); }) .catch(function error(err) { stopRepeater(); Notifications.error('Failure', err, 'Unable to retrieve container statistics'); }); } function setUpdateRepeater(networkChart, cpuChart, memoryChart, ioChart) { var refreshRate = $scope.state.refreshRate; $scope.repeater = $interval(function () { $q.all({ stats: ContainerService.containerStats(endpoint.Id, $transition$.params().id), top: ContainerService.containerTop(endpoint.Id, $transition$.params().id), }) .then(function success(data) { var stats = data.stats; $scope.processInfo = data.top; updateNetworkChart(stats, networkChart); updateMemoryChart(stats, memoryChart); updateCPUChart(stats, cpuChart); updateIOChart(stats, ioChart); }) .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; var ioChartCtx = $('#ioChart'); var ioChart = ChartService.CreateIOChart(ioChartCtx); $scope.ioChart = ioChart; startChartUpdate(networkChart, cpuChart, memoryChart, ioChart); } function initView() { HttpRequestHelper.setPortainerAgentTargetHeader($transition$.params().nodeName); ContainerService.container(endpoint.Id, $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(); }, ]);