From 07c1e1bc3e4e90ca3f12c2bfb7a18a7de4fc4be6 Mon Sep 17 00:00:00 2001 From: Yassir Hannoun Date: Sun, 28 Oct 2018 03:45:02 +0100 Subject: [PATCH] feat(container-stats): display cache in memory usage chart (#2383) --- app/docker/models/container.js | 1 + .../stats/containerStatsController.js | 3 +- app/portainer/services/chartService.js | 310 ++++++++++-------- 3 files changed, 180 insertions(+), 134 deletions(-) diff --git a/app/docker/models/container.js b/app/docker/models/container.js index 627ebec86..ee8837498 100644 --- a/app/docker/models/container.js +++ b/app/docker/models/container.js @@ -65,6 +65,7 @@ function ContainerViewModel(data) { function ContainerStatsViewModel(data) { this.Date = data.read; this.MemoryUsage = data.memory_stats.usage - data.memory_stats.stats.cache; + this.MemoryCache = data.memory_stats.stats.cache; this.PreviousCPUTotalUsage = data.precpu_stats.cpu_usage.total_usage; this.PreviousCPUSystemUsage = data.precpu_stats.system_cpu_usage; this.CurrentCPUTotalUsage = data.cpu_stats.cpu_usage.total_usage; diff --git a/app/docker/views/containers/stats/containerStatsController.js b/app/docker/views/containers/stats/containerStatsController.js index ed161c8d1..d14aeaca1 100644 --- a/app/docker/views/containers/stats/containerStatsController.js +++ b/app/docker/views/containers/stats/containerStatsController.js @@ -31,9 +31,8 @@ function ($q, $scope, $transition$, $document, $interval, ContainerService, Char function updateMemoryChart(stats, chart) { var label = moment(stats.Date).format('HH:mm:ss'); - var value = stats.MemoryUsage; - ChartService.UpdateMemoryChart(label, value, chart); + ChartService.UpdateMemoryChart(label, stats.MemoryUsage, stats.MemoryCache, chart); } function updateCPUChart(stats, chart) { diff --git a/app/portainer/services/chartService.js b/app/portainer/services/chartService.js index 4b10c9a83..818ed6e3d 100644 --- a/app/portainer/services/chartService.js +++ b/app/portainer/services/chartService.js @@ -1,14 +1,14 @@ angular.module('portainer.app') -.factory('ChartService', [function ChartService() { - 'use strict'; + .factory('ChartService', [function ChartService() { + 'use strict'; - // Max. number of items to display on a chart - var CHART_LIMIT = 600; + // Max. number of items to display on a chart + var CHART_LIMIT = 600; - var service = {}; + var service = {}; - function defaultChartOptions(pos, tooltipCallback, scalesCallback) { - return { + function defaultChartOptions(pos, tooltipCallback, scalesCallback, isStacked) { + return { animation: { duration: 0 }, responsiveAnimationDuration: 0, responsive: true, @@ -17,7 +17,7 @@ angular.module('portainer.app') intersect: false, position: pos, callbacks: { - label: function(tooltipItem, data) { + label: function (tooltipItem, data) { var datasetLabel = data.datasets[tooltipItem.datasetIndex].label; return tooltipCallback(datasetLabel, tooltipItem.yLabel); } @@ -26,142 +26,188 @@ angular.module('portainer.app') hover: { animationDuration: 0 }, scales: { yAxes: [{ - ticks: { - beginAtZero: true, - callback: scalesCallback - } + stacked: isStacked, + ticks: { + beginAtZero: true, + callback: scalesCallback + } }] } }; - } - - function CreateChart (context, label, tooltipCallback, scalesCallback) { - return new Chart(context, { - type: 'line', - data: { - labels: [], - datasets: [ - { - label: label, - data: [], - fill: true, - backgroundColor: 'rgba(151,187,205,0.4)', - borderColor: 'rgba(151,187,205,0.6)', - pointBackgroundColor: 'rgba(151,187,205,1)', - pointBorderColor: 'rgba(151,187,205,1)', - pointRadius: 2, - borderWidth: 2 - } - ] - }, - options: defaultChartOptions('nearest', tooltipCallback, scalesCallback) - }); - } - - service.CreateCPUChart = function(context) { - return CreateChart(context, 'CPU', percentageBasedTooltipLabel, percentageBasedAxisLabel); - }; - - service.CreateMemoryChart = function(context) { - return CreateChart(context, 'Memory', byteBasedTooltipLabel, byteBasedAxisLabel); - }; - - service.CreateNetworkChart = function(context) { - return new Chart(context, { - type: 'line', - data: { - labels: [], - datasets: [ - { - label: 'RX on eth0', - data: [], - fill: false, - backgroundColor: 'rgba(151,187,205,0.4)', - borderColor: 'rgba(151,187,205,0.6)', - pointBackgroundColor: 'rgba(151,187,205,1)', - pointBorderColor: 'rgba(151,187,205,1)', - pointRadius: 2, - borderWidth: 2 - }, - { - label: 'TX on eth0', - data: [], - fill: false, - backgroundColor: 'rgba(255,180,174,0.4)', - borderColor: 'rgba(255,180,174,0.6)', - pointBackgroundColor: 'rgba(255,180,174,1)', - pointBorderColor: 'rgba(255,180,174,1)', - pointRadius: 2, - borderWidth: 2 - } - ] - }, - options: defaultChartOptions('average', byteBasedTooltipLabel, byteBasedAxisLabel) - }); - }; - - function UpdateChart(label, value, chart) { - chart.data.labels.push(label); - chart.data.datasets[0].data.push(value); - - if (chart.data.datasets[0].data.length > CHART_LIMIT) { - chart.data.labels.pop(); - chart.data.datasets[0].data.pop(); } - chart.update(0); - } - - service.UpdateMemoryChart = UpdateChart; - service.UpdateCPUChart = UpdateChart; - - service.UpdateNetworkChart = function(label, rx, tx, chart) { - chart.data.labels.push(label); - chart.data.datasets[0].data.push(rx); - chart.data.datasets[1].data.push(tx); - - if (chart.data.datasets[0].data.length > CHART_LIMIT) { - chart.data.labels.pop(); - chart.data.datasets[0].data.pop(); - chart.data.datasets[1].data.pop(); + function CreateChart(context, label, tooltipCallback, scalesCallback) { + return new Chart(context, { + type: 'line', + data: { + labels: [], + datasets: [ + { + label: label, + data: [], + fill: true, + backgroundColor: 'rgba(151,187,205,0.4)', + borderColor: 'rgba(151,187,205,0.6)', + pointBackgroundColor: 'rgba(151,187,205,1)', + pointBorderColor: 'rgba(151,187,205,1)', + pointRadius: 2, + borderWidth: 2 + } + ] + }, + options: defaultChartOptions('nearest', tooltipCallback, scalesCallback) + }); } - chart.update(0); - }; - - function byteBasedTooltipLabel(label, value) { - var processedValue = 0; - if (value > 5) { - processedValue = filesize(value, {base: 10, round: 1}); - } else { - processedValue = value.toFixed(1) + 'B'; + function CreateMemoryChart(context, tooltipCallback, scalesCallback) { + return new Chart(context, { + type: 'line', + data: { + labels: [], + datasets: [ + { + label: 'Memory', + data: [], + fill: true, + backgroundColor: 'rgba(151,187,205,0.4)', + borderColor: 'rgba(151,187,205,0.6)', + pointBackgroundColor: 'rgba(151,187,205,1)', + pointBorderColor: 'rgba(151,187,205,1)', + pointRadius: 2, + borderWidth: 2 + }, + { + label: 'Cache', + data: [], + fill: true, + backgroundColor: 'rgba(255,180,174,0.4)', + borderColor: 'rgba(255,180,174,0.6)', + pointBackgroundColor: 'rgba(255,180,174,1)', + pointBorderColor: 'rgba(255,180,174,1)', + pointRadius: 2, + borderWidth: 2 + } + ] + }, + options: defaultChartOptions('nearest', tooltipCallback, scalesCallback, true) + }); } - return label + ': ' + processedValue; - } - function byteBasedAxisLabel(value) { - if (value > 5) { - return filesize(value, {base: 10, round: 1}); + service.CreateCPUChart = function (context) { + return CreateChart(context, 'CPU', percentageBasedTooltipLabel, percentageBasedAxisLabel); + }; + + service.CreateMemoryChart = function (context) { + return CreateMemoryChart(context, byteBasedTooltipLabel, byteBasedAxisLabel); + }; + + service.CreateNetworkChart = function (context) { + return new Chart(context, { + type: 'line', + data: { + labels: [], + datasets: [ + { + label: 'RX on eth0', + data: [], + fill: false, + backgroundColor: 'rgba(151,187,205,0.4)', + borderColor: 'rgba(151,187,205,0.6)', + pointBackgroundColor: 'rgba(151,187,205,1)', + pointBorderColor: 'rgba(151,187,205,1)', + pointRadius: 2, + borderWidth: 2 + }, + { + label: 'TX on eth0', + data: [], + fill: false, + backgroundColor: 'rgba(255,180,174,0.4)', + borderColor: 'rgba(255,180,174,0.6)', + pointBackgroundColor: 'rgba(255,180,174,1)', + pointBorderColor: 'rgba(255,180,174,1)', + pointRadius: 2, + borderWidth: 2 + } + ] + }, + options: defaultChartOptions('average', byteBasedTooltipLabel, byteBasedAxisLabel) + }); + }; + + function UpdateChart(label, value, chart) { + chart.data.labels.push(label); + chart.data.datasets[0].data.push(value); + + if (chart.data.datasets[0].data.length > CHART_LIMIT) { + chart.data.labels.pop(); + chart.data.datasets[0].data.pop(); + } + + chart.update(0); } - return value.toFixed(1) + 'B'; - } - function percentageBasedAxisLabel(value) { - if (value > 1) { - return Math.round(value) + '%'; + service.UpdateMemoryChart = function UpdateChart(label, memoryValue, cacheValue, chart) { + chart.data.labels.push(label); + chart.data.datasets[0].data.push(memoryValue); + chart.data.datasets[1].data.push(cacheValue); + + if (chart.data.datasets[0].data.length > CHART_LIMIT) { + chart.data.labels.pop(); + chart.data.datasets[0].data.pop(); + } + + chart.update(0); + }; + service.UpdateCPUChart = UpdateChart; + + service.UpdateNetworkChart = function (label, rx, tx, chart) { + chart.data.labels.push(label); + chart.data.datasets[0].data.push(rx); + chart.data.datasets[1].data.push(tx); + + if (chart.data.datasets[0].data.length > CHART_LIMIT) { + chart.data.labels.pop(); + chart.data.datasets[0].data.pop(); + chart.data.datasets[1].data.pop(); + } + + chart.update(0); + }; + + function byteBasedTooltipLabel(label, value) { + var processedValue = 0; + if (value > 5) { + processedValue = filesize(value, { base: 10, round: 1 }); + } else { + processedValue = value.toFixed(1) + 'B'; + } + return label + ': ' + processedValue; } - return value.toFixed(1) + '%'; - } - function percentageBasedTooltipLabel(label, value) { - var processedValue = 0; - if (value > 1) { - processedValue = Math.round(value); - } else { - processedValue = value.toFixed(1); + function byteBasedAxisLabel(value) { + if (value > 5) { + return filesize(value, { base: 10, round: 1 }); + } + return value.toFixed(1) + 'B'; } - return label + ': ' + processedValue + '%'; - } - return service; -}]); + function percentageBasedAxisLabel(value) { + if (value > 1) { + return Math.round(value) + '%'; + } + return value.toFixed(1) + '%'; + } + + function percentageBasedTooltipLabel(label, value) { + var processedValue = 0; + if (value > 1) { + processedValue = Math.round(value); + } else { + processedValue = value.toFixed(1); + } + return label + ': ' + processedValue + '%'; + } + + return service; + }]);