cadvisor/pages/static/containers_js.go
Vishnu Kannan 1a24eed18f Fix storage driver buffer duration default value.
The cache will now hold atlest the minimum number of stats required by the UI and more
if the buffer duration is longer than the default.

Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)
2014-08-20 20:46:14 +00:00

346 lines
10 KiB
Go

// Copyright 2014 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package static
const containersJs = `
google.load("visualization", "1", {packages: ["corechart", "gauge"]});
// Draw a line chart.
function drawLineChart(seriesTitles, data, elementId, unit) {
// Convert the first column to a Date.
for (var i = 0; i < data.length; i++) {
if (data[i] != null) {
data[i][0] = new Date(data[i][0]);
}
}
// Add the definition of each column and the necessary data.
var dataTable = new google.visualization.DataTable();
dataTable.addColumn('datetime', seriesTitles[0]);
for (var i = 1; i < seriesTitles.length; i++) {
dataTable.addColumn('number', seriesTitles[i]);
}
dataTable.addRows(data);
// Create and draw the visualization.
var ac = null;
var opts = null;
// TODO(vmarmol): Remove this hack, it is to support the old charts and the new charts during the transition.
if (window.charts) {
if (!(elementId in window.charts)) {
ac = new google.visualization.LineChart(document.getElementById(elementId));
window.charts[elementId] = ac;
}
ac = window.charts[elementId];
opts = window.chartOptions;
} else {
ac = new google.visualization.LineChart(document.getElementById(elementId));
opts = {};
}
opts.vAxis = {title: unit};
opts.legend = {position: 'bottom'};
ac.draw(dataTable, window.chartOptions);
}
// Draw a gauge.
function drawGauge(elementId, cpuUsage, memoryUsage) {
var gauges = [['Label', 'Value']];
if (cpuUsage >= 0) {
gauges.push(['CPU', cpuUsage]);
}
if (memoryUsage >= 0) {
gauges.push(['Memory', memoryUsage]);
}
// Create and populate the data table.
var data = google.visualization.arrayToDataTable(gauges);
// Create and draw the visualization.
var options = {
width: 400, height: 120,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
minorTicks: 5,
animation: {
duration: 900,
easing: 'linear'
}
};
var chart = new google.visualization.Gauge(document.getElementById(elementId));
chart.draw(data, options);
}
// Get the machine info.
function getMachineInfo(callback) {
$.getJSON("/api/v1.0/machine", function(data) {
callback(data);
});
}
// Get the container stats for the specified container.
function getStats(containerName, callback) {
// Request 60s of container history and no samples.
var request = JSON.stringify({
// Update main.statsRequestedByUI while updating "num_stats" here.
"num_stats": 60,
"num_samples": 0
});
$.post("/api/v1.0/containers" + containerName, request, function(data) {
callback(data);
}, "json");
}
// Draw the graph for CPU usage.
function drawCpuTotalUsage(elementId, machineInfo, stats) {
var titles = ["Time", "Total"];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
var prev = stats.stats[i - 1];
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
var elements = [];
elements.push(cur.timestamp);
elements.push((cur.cpu.usage.total - prev.cpu.usage.total) / 1000000000);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Cores");
}
// Draw the graph for per-core CPU usage.
function drawCpuPerCoreUsage(elementId, machineInfo, stats) {
// Add a title for each core.
var titles = ["Time"];
for (var i = 0; i < machineInfo.num_cores; i++) {
titles.push("Core " + i);
}
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
var prev = stats.stats[i - 1];
var elements = [];
elements.push(cur.timestamp);
for (var j = 0; j < machineInfo.num_cores; j++) {
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
elements.push((cur.cpu.usage.per_cpu_usage[j] - prev.cpu.usage.per_cpu_usage[j]) / 1000000000);
}
data.push(elements);
}
drawLineChart(titles, data, elementId, "Cores");
}
// Draw the graph for CPU usage breakdown.
function drawCpuUsageBreakdown(elementId, containerInfo) {
var titles = ["Time", "User", "Kernel"];
var data = [];
for (var i = 1; i < containerInfo.stats.length; i++) {
var cur = containerInfo.stats[i];
var prev = containerInfo.stats[i - 1];
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
var elements = [];
elements.push(cur.timestamp);
elements.push((cur.cpu.usage.user - prev.cpu.usage.user) / 1000000000);
elements.push((cur.cpu.usage.system - prev.cpu.usage.system) / 1000000000);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Cores");
}
// Draw the gauges for overall resource usage.
function drawOverallUsage(elementId, machineInfo, containerInfo) {
var cur = containerInfo.stats[containerInfo.stats.length - 1];
var cpuUsage = 0;
if (containerInfo.spec.cpu && containerInfo.stats.length >= 2) {
var prev = containerInfo.stats[containerInfo.stats.length - 2];
var rawUsage = cur.cpu.usage.total - prev.cpu.usage.total;
// Convert to millicores and take the percentage
cpuUsage = Math.round(((rawUsage / 1000000) / (machineInfo.num_cores * 1000)) * 100);
if (cpuUsage > 100) {
cpuUsage = 100;
}
}
var memoryUsage = 0;
if (containerInfo.spec.memory) {
// Saturate to the machine size.
var limit = containerInfo.spec.memory.limit;
if (limit > machineInfo.memory_capacity) {
limit = machineInfo.memory_capacity;
}
memoryUsage = Math.round((cur.memory.usage / limit) * 100);
}
drawGauge(elementId, cpuUsage, memoryUsage);
}
var oneMegabyte = 1024 * 1024;
function drawMemoryUsage(elementId, containerInfo) {
var titles = ["Time", "Total"];
var data = [];
for (var i = 0; i < containerInfo.stats.length; i++) {
var cur = containerInfo.stats[i];
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
var elements = [];
elements.push(cur.timestamp);
elements.push(cur.memory.usage / oneMegabyte);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Megabytes");
}
function drawMemoryPageFaults(elementId, containerInfo) {
var titles = ["Time", "Faults", "Major Faults"];
var data = [];
for (var i = 1; i < containerInfo.stats.length; i++) {
var cur = containerInfo.stats[i];
var prev = containerInfo.stats[i - 1];
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
var elements = [];
elements.push(cur.timestamp);
elements.push(cur.memory.hierarchical_data.pgfault - prev.memory.hierarchical_data.pgfault);
// TODO(vmarmol): Fix to expose this data.
//elements.push(cur.memory.hierarchical_data.pgmajfault - prev.memory.hierarchical_data.pgmajfault);
elements.push(0);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Faults");
}
// Draw the graph for network tx/rx bytes.
function drawNetworkBytes(elementId, machineInfo, stats) {
var titles = ["Time", "Tx bytes", "Rx bytes"];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
var prev = stats.stats[i - 1];
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
var elements = [];
elements.push(cur.timestamp);
elements.push(cur.network.tx_bytes - prev.network.tx_bytes);
elements.push(cur.network.rx_bytes - prev.network.rx_bytes);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Bytes per second");
}
// Draw the graph for network errors
function drawNetworkErrors(elementId, machineInfo, stats) {
var titles = ["Time", "Tx", "Rx"];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
var prev = stats.stats[i - 1];
// TODO(vmarmol): This assumes we sample every second, use the timestamps.
var elements = [];
elements.push(cur.timestamp);
elements.push(cur.network.tx_errors - prev.network.tx_errors);
elements.push(cur.network.rx_errors - prev.network.rx_errors);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Errors per second");
}
// Expects an array of closures to call. After each execution the JS runtime is given control back before continuing.
// This function returns asynchronously
function stepExecute(steps) {
// No steps, stop.
if (steps.length == 0) {
return;
}
// Get a step and execute it.
var step = steps.shift();
step();
// Schedule the next step.
setTimeout(function() {
stepExecute(steps);
}, 0);
}
// Draw all the charts on the page.
function drawCharts(machineInfo, containerInfo) {
var steps = [];
steps.push(function() {
drawOverallUsage("usage-gauge", machineInfo, containerInfo)
});
// CPU.
steps.push(function() {
drawCpuTotalUsage("cpu-total-usage-chart", machineInfo, containerInfo);
});
steps.push(function() {
drawCpuPerCoreUsage("cpu-per-core-usage-chart", machineInfo, containerInfo);
});
steps.push(function() {
drawCpuUsageBreakdown("cpu-usage-breakdown-chart", containerInfo);
});
// Memory.
steps.push(function() {
drawMemoryUsage("memory-usage-chart", containerInfo);
});
steps.push(function() {
drawMemoryPageFaults("memory-page-faults-chart", containerInfo);
});
// Network.
steps.push(function() {
drawNetworkBytes("network-bytes-chart", machineInfo, containerInfo);
});
steps.push(function() {
drawNetworkErrors("network-errors-chart", machineInfo, containerInfo);
});
stepExecute(steps);
}
// Executed when the page finishes loading.
function startPage(containerName, hasCpu, hasMemory) {
// Don't fetch data if we don't have any resource.
if (!hasCpu && !hasMemory) {
return;
}
// TODO(vmarmol): Look into changing the view window to get a smoother animation.
window.chartOptions = {
curveType: 'function',
height: 300,
legend:{position:"none"},
focusTarget: "category",
};
window.charts = {};
// Get machine info, then get the stats every 1s.
getMachineInfo(function(machineInfo) {
setInterval(function() {
getStats(containerName, function(stats){
drawCharts(machineInfo, stats);
});
}, 1000);
});
}
`