Separated asset files into their own folder with the correct file

formats, and added a script to build them into required .go file using
go-bindata.
This commit is contained in:
Ainsley Chong 2016-04-13 12:55:45 -07:00
parent 24b1bb0f2a
commit 700c3d1d4d
14 changed files with 1199 additions and 797 deletions

View File

@ -33,6 +33,7 @@ vet:
build:
@echo ">> building binaries"
@./build/assets.sh
@./build/build.sh
release: build

37
build/assets.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# Copyright 2015 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.
GIT_ROOT=$(dirname "${BASH_SOURCE}")/..
YEAR=$(date +%Y)
TMP_OUTPUT="/tmp/cadvisor_assets.go"
ASSETS_OUTPUT=$GIT_ROOT/pages/static/assets.go
go get -u github.com/jteeuwen/go-bindata/...
for f in $GIT_ROOT/pages/assets/**/*; do
if [ "$f" -nt $ASSETS_OUTPUT -o ! -e $ASSETS_OUTPUT ]; then
go-bindata -o $ASSETS_OUTPUT -pkg static $GIT_ROOT/pages/assets/...
cat build/boilerplate/boilerplate.go.txt | sed "s/YEAR/$YEAR/" > "${TMP_OUTPUT}"
echo -e "// generated by build/assets.sh; DO NOT EDIT\n" >> "${TMP_OUTPUT}"
cat "${ASSETS_OUTPUT}" >> "${TMP_OUTPUT}"
gofmt -w -s "${TMP_OUTPUT}"
mv "${TMP_OUTPUT}" "${ASSETS_OUTPUT}"
break
fi
done
exit 0

View File

@ -43,3 +43,13 @@ Now you can run the built binary:
```
$GOPATH/src/github.com/google/cadvisor $ sudo ./cadvisor
```
## Compiling Assets
If you modify files in the /assets folder, you will need to rebuild the assets:
```
$GOPATH/src/github.com/google/cadvisor $ ./build/assets.sh
$GOPATH/src/github.com/google/cadvisor $ godep go build .
```

File diff suppressed because one or more lines are too long

View File

@ -12,9 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package static
const containersJs = gchartsJs + `
function humanize(num, size, units) {
var unit;
for (unit = units.pop(); units.length && num >= size; unit = units.pop()) {
@ -25,24 +22,27 @@ function humanize(num, size, units) {
// Following the IEC naming convention
function humanizeIEC(num) {
var ret = humanize(num, 1024, ["TiB", "GiB", "MiB", "KiB", "B"]);
return ret[0].toFixed(2) + " " + ret[1];
var ret = humanize(num, 1024, ['TiB', 'GiB', 'MiB', 'KiB', 'B']);
return ret[0].toFixed(2) + ' ' + ret[1];
}
// Following the Metric naming convention
function humanizeMetric(num) {
var ret = humanize(num, 1000, ["TB", "GB", "MB", "KB", "Bytes"]);
return ret[0].toFixed(2) + " " + ret[1];
var ret = humanize(num, 1000, ['TB', 'GB', 'MB', 'KB', 'Bytes']);
return ret[0].toFixed(2) + ' ' + ret[1];
}
// Draw a table.
function drawTable(seriesTitles, titleTypes, data, elementId, numPages, sortIndex) {
function drawTable(
seriesTitles, titleTypes, data, elementId, numPages, sortIndex) {
var dataTable = new google.visualization.DataTable();
for (var i = 0; i < seriesTitles.length; i++) {
dataTable.addColumn(titleTypes[i], seriesTitles[i]);
}
dataTable.addRows(data);
if (!(elementId in window.charts)) {
window.charts[elementId] = new google.visualization.Table(document.getElementById(elementId));
window.charts[elementId] =
new google.visualization.Table(document.getElementById(elementId));
}
var cssClassNames = {
@ -57,7 +57,7 @@ function drawTable(seriesTitles, titleTypes, data, elementId, numPages, sortInde
allowHtml: true,
sortColumn: sortIndex,
sortAscending: false,
cssClassNames: cssClassNames,
cssClassNames: cssClassNames
};
window.charts[elementId].draw(dataTable, opts);
}
@ -101,29 +101,31 @@ function drawLineChart(seriesTitles, data, elementId, unit) {
// Create and draw the visualization.
if (!(elementId in window.charts)) {
window.charts[elementId] = new google.visualization.LineChart(document.getElementById(elementId));
window.charts[elementId] =
new google.visualization.LineChart(document.getElementById(elementId));
}
// TODO(vmarmol): Look into changing the view window to get a smoother animation.
// TODO(vmarmol): Look into changing the view window to get a smoother
// animation.
var opts = {
curveType: 'function',
height: 300,
legend:{position:"none"},
focusTarget: "category",
legend: {position: 'none'},
focusTarget: 'category',
vAxis: {
title: unit,
viewWindow: {
min: minWindow,
},
}
},
legend: {
position: 'bottom',
},
position: 'bottom'
}
};
// If the whole data series has the same value, try to center it in the chart.
if ( min == max) {
opts.vAxis.viewWindow.max = 1.1 * max
opts.vAxis.viewWindow.min = 0.9 * max
if (min == max) {
opts.vAxis.viewWindow.max = 1.1 * max;
opts.vAxis.viewWindow.min = 0.9 * max;
}
window.charts[elementId].draw(dataTable, opts);
@ -143,7 +145,8 @@ function hasResource(stats, resource) {
return stats.stats.length > 0 && stats.stats[0][resource];
}
// Draw a set of gauges. Data is comprised of an array of arrays with two elements:
// Draw a set of gauges. Data is comprised of an array of arrays with two
// elements:
// a string label and a numeric value for the gauge.
function drawGauges(elementId, gauges) {
gauges.unshift(['Label', 'Value']);
@ -154,34 +157,28 @@ function drawGauges(elementId, gauges) {
// Create and draw the visualization.
var options = {
height: 100,
redFrom: 90, redTo: 100,
yellowFrom:75, yellowTo: 90,
redFrom: 90,
redTo: 100,
yellowFrom: 75,
yellowTo: 90,
minorTicks: 5,
animation: {
duration: 900,
easing: 'linear'
}
animation: {duration: 900, easing: 'linear'}
};
var chart = new google.visualization.Gauge(document.getElementById(elementId));
var chart =
new google.visualization.Gauge(document.getElementById(elementId));
chart.draw(data, options);
}
// Get the machine info.
function getMachineInfo(rootDir, callback) {
$.getJSON(rootDir + "api/v1.0/machine", function(data) {
callback(data);
});
$.getJSON(rootDir + 'api/v1.0/machine', function(data) { callback(data); });
}
// Get ps info.
function getProcessInfo(rootDir, containerName, callback) {
$.getJSON(rootDir + "api/v2.0/ps" + containerName)
.done(function(data) {
callback(data);
})
.fail(function(jqhxr, textStatus, error) {
callback([]);
});
$.getJSON(rootDir + 'api/v2.0/ps' + containerName)
.done(function(data) { callback(data); })
.fail(function(jqhxr, textStatus, error) { callback([]); });
}
// Get the container stats for the specified container.
@ -189,21 +186,21 @@ function getStats(rootDir, 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
'num_stats': 60,
'num_samples': 0
});
$.post(rootDir + "api/v1.0/containers" + containerName, request, function(data) {
callback(data);
}, "json");
$.post(
rootDir + 'api/v1.0/containers' + containerName, request,
function(data) { callback(data); }, 'json');
}
// Draw the graph for CPU usage.
function drawCpuTotalUsage(elementId, machineInfo, stats) {
if (stats.spec.has_cpu && !hasResource(stats, "cpu")) {
if (stats.spec.has_cpu && !hasResource(stats, 'cpu')) {
return;
}
var titles = ["Time", "Total"];
var titles = ['Time', 'Total'];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
@ -215,36 +212,34 @@ function drawCpuTotalUsage(elementId, machineInfo, stats) {
elements.push((cur.cpu.usage.total - prev.cpu.usage.total) / intervalInNs);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Cores");
drawLineChart(titles, data, elementId, 'Cores');
}
// Draw the graph for CPU load.
function drawCpuLoad(elementId, machineInfo, stats) {
var titles = ["Time", "Average"];
var titles = ['Time', 'Average'];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
var elements = [];
elements.push(cur.timestamp);
elements.push(cur.cpu.load_average/1000);
elements.push(cur.cpu.load_average / 1000);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Runnable threads");
drawLineChart(titles, data, elementId, 'Runnable threads');
}
// Draw the graph for per-core CPU usage.
function drawCpuPerCoreUsage(elementId, machineInfo, stats) {
if (stats.spec.has_cpu && !hasResource(stats, "cpu")) {
if (stats.spec.has_cpu && !hasResource(stats, 'cpu')) {
return;
}
// Add a title for each core.
var titles = ["Time"];
var titles = ['Time'];
for (var i = 0; i < machineInfo.num_cores; i++) {
titles.push("Core " + i);
titles.push('Core ' + i);
}
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
@ -255,20 +250,22 @@ function drawCpuPerCoreUsage(elementId, machineInfo, stats) {
var elements = [];
elements.push(cur.timestamp);
for (var j = 0; j < machineInfo.num_cores; j++) {
elements.push((cur.cpu.usage.per_cpu_usage[j] - prev.cpu.usage.per_cpu_usage[j]) / intervalInNs);
elements.push(
(cur.cpu.usage.per_cpu_usage[j] - prev.cpu.usage.per_cpu_usage[j]) /
intervalInNs);
}
data.push(elements);
}
drawLineChart(titles, data, elementId, "Cores");
drawLineChart(titles, data, elementId, 'Cores');
}
// Draw the graph for CPU usage breakdown.
function drawCpuUsageBreakdown(elementId, machineInfo, containerInfo) {
if (containerInfo.spec.has_cpu && !hasResource(containerInfo, "cpu")) {
if (containerInfo.spec.has_cpu && !hasResource(containerInfo, 'cpu')) {
return;
}
var titles = ["Time", "User", "Kernel"];
var titles = ['Time', 'User', 'Kernel'];
var data = [];
for (var i = 1; i < containerInfo.stats.length; i++) {
var cur = containerInfo.stats[i];
@ -278,10 +275,11 @@ function drawCpuUsageBreakdown(elementId, machineInfo, containerInfo) {
var elements = [];
elements.push(cur.timestamp);
elements.push((cur.cpu.usage.user - prev.cpu.usage.user) / intervalInNs);
elements.push((cur.cpu.usage.system - prev.cpu.usage.system) / intervalInNs);
elements.push(
(cur.cpu.usage.system - prev.cpu.usage.system) / intervalInNs);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Cores");
drawLineChart(titles, data, elementId, 'Cores');
}
// Draw the gauges for overall resource usage.
@ -296,7 +294,8 @@ function drawOverallUsage(elementId, machineInfo, containerInfo) {
var intervalInNs = getInterval(cur.timestamp, prev.timestamp);
// Convert to millicores and take the percentage
cpuUsage = Math.round(((rawUsage / intervalInNs) / machineInfo.num_cores) * 100);
cpuUsage =
Math.round(((rawUsage / intervalInNs) / machineInfo.num_cores) * 100);
if (cpuUsage > 100) {
cpuUsage = 100;
}
@ -341,11 +340,11 @@ var oneMegabyte = 1024 * 1024;
var oneGigabyte = 1024 * oneMegabyte;
function drawMemoryUsage(elementId, machineInfo, containerInfo) {
if (containerInfo.spec.has_memory && !hasResource(containerInfo, "memory")) {
if (containerInfo.spec.has_memory && !hasResource(containerInfo, 'memory')) {
return;
}
var titles = ["Time", "Total", "Hot"];
var titles = ['Time', 'Total', 'Hot'];
var data = [];
for (var i = 0; i < containerInfo.stats.length; i++) {
var cur = containerInfo.stats[i];
@ -359,20 +358,24 @@ function drawMemoryUsage(elementId, machineInfo, containerInfo) {
// Get the memory limit, saturate to the machine size.
var memory_limit = machineInfo.memory_capacity;
if (containerInfo.spec.memory.limit && (containerInfo.spec.memory.limit < memory_limit)) {
if (containerInfo.spec.memory.limit &&
(containerInfo.spec.memory.limit < memory_limit)) {
memory_limit = containerInfo.spec.memory.limit;
}
// Updating the progress bar.
var cur = containerInfo.stats[containerInfo.stats.length-1];
var cur = containerInfo.stats[containerInfo.stats.length - 1];
var hotMemory = Math.floor((cur.memory.working_set * 100.0) / memory_limit);
var totalMemory = Math.floor((cur.memory.usage * 100.0) / memory_limit);
var coldMemory = totalMemory - hotMemory;
$("#progress-hot-memory").width(hotMemory + "%");
$("#progress-cold-memory").width(coldMemory + "%");
$("#memory-text").text(humanizeIEC(cur.memory.usage) + " / " + humanizeIEC(memory_limit) + " ("+ totalMemory +"%)");
$('#progress-hot-memory').width(hotMemory + '%');
$('#progress-cold-memory').width(coldMemory + '%');
$('#memory-text')
.text(
humanizeIEC(cur.memory.usage) + ' / ' + humanizeIEC(memory_limit) +
' (' + totalMemory + '%)');
drawLineChart(titles, data, elementId, "Megabytes");
drawLineChart(titles, data, elementId, 'Megabytes');
}
// Get the index of the interface with the specified name.
@ -387,21 +390,24 @@ function getNetworkInterfaceIndex(interfaceName, interfaces) {
// Draw the graph for network tx/rx bytes.
function drawNetworkBytes(elementId, machineInfo, stats) {
if (stats.spec.has_network && !hasResource(stats, "network")) {
if (stats.spec.has_network && !hasResource(stats, 'network')) {
return;
}
// Get interface index.
var interfaceIndex = -1;
if (stats.stats.length > 0) {
interfaceIndex = getNetworkInterfaceIndex(window.cadvisor.network.interface, stats.stats[0].network.interfaces);
interfaceIndex = getNetworkInterfaceIndex(
window.cadvisor.network.interface, stats.stats[0].network.interfaces);
}
if (interfaceIndex < 0) {
console.log("Unable to find interface\"", interfaceName, "\" in ", stats.stats.network);
console.log(
'Unable to find interface"', interfaceName, '" in ',
stats.stats.network);
return;
}
var titles = ["Time", "Tx bytes", "Rx bytes"];
var titles = ['Time', 'Tx bytes', 'Rx bytes'];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
@ -410,30 +416,39 @@ function drawNetworkBytes(elementId, machineInfo, stats) {
var elements = [];
elements.push(cur.timestamp);
elements.push((cur.network.interfaces[interfaceIndex].tx_bytes - prev.network.interfaces[interfaceIndex].tx_bytes) / intervalInSec);
elements.push((cur.network.interfaces[interfaceIndex].rx_bytes - prev.network.interfaces[interfaceIndex].rx_bytes) / intervalInSec);
elements.push(
(cur.network.interfaces[interfaceIndex].tx_bytes -
prev.network.interfaces[interfaceIndex].tx_bytes) /
intervalInSec);
elements.push(
(cur.network.interfaces[interfaceIndex].rx_bytes -
prev.network.interfaces[interfaceIndex].rx_bytes) /
intervalInSec);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Bytes per second");
drawLineChart(titles, data, elementId, 'Bytes per second');
}
// Draw the graph for network errors
function drawNetworkErrors(elementId, machineInfo, stats) {
if (stats.spec.has_network && !hasResource(stats, "network")) {
if (stats.spec.has_network && !hasResource(stats, 'network')) {
return;
}
// Get interface index.
var interfaceIndex = -1;
if (stats.stats.length > 0) {
interfaceIndex = getNetworkInterfaceIndex(window.cadvisor.network.interface, stats.stats[0].network.interfaces);
interfaceIndex = getNetworkInterfaceIndex(
window.cadvisor.network.interface, stats.stats[0].network.interfaces);
}
if (interfaceIndex < 0) {
console.log("Unable to find interface\"", interfaceName, "\" in ", stats.stats.network);
console.log(
'Unable to find interface"', interfaceName, '" in ',
stats.stats.network);
return;
}
var titles = ["Time", "Tx", "Rx"];
var titles = ['Time', 'Tx', 'Rx'];
var data = [];
for (var i = 1; i < stats.stats.length; i++) {
var cur = stats.stats[i];
@ -442,11 +457,17 @@ function drawNetworkErrors(elementId, machineInfo, stats) {
var elements = [];
elements.push(cur.timestamp);
elements.push((cur.network.interfaces[interfaceIndex].tx_errors - prev.network.interfaces[interfaceIndex].tx_errors) / intervalInSec);
elements.push((cur.network.interfaces[interfaceIndex].rx_errors - prev.network.interfaces[interfaceIndex].rx_errors) / intervalInSec);
elements.push(
(cur.network.interfaces[interfaceIndex].tx_errors -
prev.network.interfaces[interfaceIndex].tx_errors) /
intervalInSec);
elements.push(
(cur.network.interfaces[interfaceIndex].rx_errors -
prev.network.interfaces[interfaceIndex].rx_errors) /
intervalInSec);
data.push(elements);
}
drawLineChart(titles, data, elementId, "Errors per second");
drawLineChart(titles, data, elementId, 'Errors per second');
}
// Update the filesystem usage values.
@ -456,15 +477,17 @@ function drawFileSystemUsage(machineInfo, stats) {
return;
}
var el = $("<div>");
var el = $('<div>');
for (var i = 0; i < cur.filesystem.length; i++) {
var data = cur.filesystem[i];
var totalUsage = Math.floor((data.usage * 100.0) / data.capacity);
// Update DOM elements.
var els = window.cadvisor.fsUsage.elements[data.device];
els.progressElement.width(totalUsage + "%");
els.textElement.text(humanizeMetric(data.usage) + " / " + humanizeMetric(data.capacity)+ " (" + totalUsage + "%)");
els.progressElement.width(totalUsage + '%');
els.textElement.text(
humanizeMetric(data.usage) + ' / ' + humanizeMetric(data.capacity) +
' (' + totalUsage + '%)');
}
}
@ -473,67 +496,84 @@ function drawImages(images) {
return;
}
window.charts = {};
var titles = ["Repository", "Tags", "ID", "Virtual Size", "Creation Time"];
var titles = ['Repository', 'Tags', 'ID', 'Virtual Size', 'Creation Time'];
var titleTypes = ['string', 'string', 'string', 'number', 'number'];
var sortIndex = 0;
var data = [];
for (var i = 0; i < images.length; i++) {
var elements = [];
var tags = [];
var repos = images[i].repo_tags[0].split(":");
repos.splice(-1,1)
var repos = images[i].repo_tags[0].split(':');
repos.splice(-1, 1);
for (var j = 0; j < images[i].repo_tags.length; j++) {
var splits = images[i].repo_tags[j].split(":")
var splits = images[i].repo_tags[j].split(':');
if (splits.length > 1) {
tags.push(splits[splits.length - 1])
tags.push(splits[splits.length - 1]);
}
}
elements.push(repos.join(":"));
elements.push(tags.join(", "));
elements.push(images[i].id.substr(0,24));
elements.push({v: images[i].virtual_size, f: humanizeIEC(images[i].virtual_size)});
elements.push(repos.join(':'));
elements.push(tags.join(', '));
elements.push(images[i].id.substr(0, 24));
elements.push(
{v: images[i].virtual_size, f: humanizeIEC(images[i].virtual_size)});
var d = new Date(images[i].created * 1000);
elements.push({v: images[i].created, f: d.toLocaleString()});
data.push(elements);
}
drawTable(titles, titleTypes, data, "docker-images", 30, sortIndex);
drawTable(titles, titleTypes, data, 'docker-images', 30, sortIndex);
}
function drawProcesses(isRoot, rootDir, processInfo) {
if (processInfo.length == 0) {
$("#processes-top").text("No processes found");
$('#processes-top').text('No processes found');
return;
}
var titles = ["User", "PID", "PPID", "Start Time", "CPU %", "MEM %", "RSS", "Virtual Size", "Status", "Running Time", "Command"];
var titleTypes = ['string', 'number', 'number', 'string', 'number', 'number', 'number', 'number', 'string', 'string', 'string'];
var sortIndex = 4
var titles = [
'User', 'PID', 'PPID', 'Start Time', 'CPU %', 'MEM %', 'RSS',
'Virtual Size', 'Status', 'Running Time', 'Command'
];
var titleTypes = [
'string', 'number', 'number', 'string', 'number', 'number', 'number',
'number', 'string', 'string', 'string'
];
var sortIndex = 4;
if (isRoot) {
titles.push("Container");
titles.push('Container');
titleTypes.push('string');
}
var data = []
var data = [];
for (var i = 0; i < processInfo.length; i++) {
var elements = [];
elements.push(processInfo[i].user);
elements.push(processInfo[i].pid);
elements.push(processInfo[i].parent_pid);
elements.push(processInfo[i].start_time);
elements.push({ v:processInfo[i].percent_cpu, f:processInfo[i].percent_cpu.toFixed(2)});
elements.push({ v:processInfo[i].percent_mem, f:processInfo[i].percent_mem.toFixed(2)});
elements.push({ v:processInfo[i].rss, f:humanizeIEC(processInfo[i].rss)});
elements.push({ v:processInfo[i].virtual_size, f:humanizeIEC(processInfo[i].virtual_size)});
elements.push({
v: processInfo[i].percent_cpu,
f: processInfo[i].percent_cpu.toFixed(2)
});
elements.push({
v: processInfo[i].percent_mem,
f: processInfo[i].percent_mem.toFixed(2)
});
elements.push({v: processInfo[i].rss, f: humanizeIEC(processInfo[i].rss)});
elements.push({
v: processInfo[i].virtual_size,
f: humanizeIEC(processInfo[i].virtual_size)
});
elements.push(processInfo[i].status);
elements.push(processInfo[i].running_time);
elements.push(processInfo[i].cmd);
if (isRoot) {
var cgroup = processInfo[i].cgroup_path
var cgroup = processInfo[i].cgroup_path;
// Use the raw cgroup link as it works for all containers.
var cgroupLink = '<a href="' + rootDir + 'containers/' + cgroup +'">' + cgroup.substr(0,30) + ' </a>';
elements.push({v:cgroup, f:cgroupLink});
var cgroupLink = '<a href="' + rootDir + 'containers/' + cgroup + '">' +
cgroup.substr(0, 30) + ' </a>';
elements.push({v: cgroup, f: cgroupLink});
}
data.push(elements);
}
drawTable(titles, titleTypes, data, "processes-top", 25, sortIndex);
drawTable(titles, titleTypes, data, 'processes-top', 25, sortIndex);
}
// Draw the filesystem usage nodes.
@ -544,25 +584,25 @@ function startFileSystemUsage(elementId, machineInfo, stats) {
window.cadvisor.fsUsage.elements = {};
var cur = stats.stats[stats.stats.length - 1];
var el = $("<div>");
var el = $('<div>');
if (!cur.filesystem) {
return;
}
for (var i = 0; i < cur.filesystem.length; i++) {
var data = cur.filesystem[i];
el.append($("<div>")
.addClass("row col-sm-12")
.append($("<h4>")
.text("FS #" + (i + 1) + ": " + data.device)));
el.append(
$('<div>')
.addClass('row col-sm-12')
.append($('<h4>').text('FS #' + (i + 1) + ': ' + data.device)));
var progressElement = $("<div>").addClass("progress-bar progress-bar-danger");
el.append($("<div>")
.addClass("col-sm-9")
.append($("<div>")
.addClass("progress")
.append(progressElement)));
var progressElement =
$('<div>').addClass('progress-bar progress-bar-danger');
el.append(
$('<div>')
.addClass('col-sm-9')
.append($('<div>').addClass('progress').append(progressElement)));
var textElement = $("<div>").addClass("col-sm-3");
var textElement = $('<div>').addClass('col-sm-3');
el.append(textElement);
window.cadvisor.fsUsage.elements[data.device] = {
@ -571,12 +611,13 @@ function startFileSystemUsage(elementId, machineInfo, stats) {
'index': i,
};
}
$("#" + elementId).empty().append(el);
$('#' + elementId).empty().append(el);
drawFileSystemUsage(machineInfo, stats);
}
// Expects an array of closures to call. After each execution the JS runtime is given control back before continuing.
// 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.
@ -589,9 +630,7 @@ function stepExecute(steps) {
step();
// Schedule the next step.
setTimeout(function() {
stepExecute(steps);
}, 0);
setTimeout(function() { stepExecute(steps); }, 0);
}
// Draw all the charts on the page.
@ -600,56 +639,59 @@ function drawCharts(machineInfo, containerInfo) {
if (containerInfo.spec.has_cpu || containerInfo.spec.has_memory) {
steps.push(function() {
drawOverallUsage("usage-gauge", machineInfo, containerInfo)
drawOverallUsage('usage-gauge', machineInfo, containerInfo);
});
}
// CPU.
if (containerInfo.spec.has_cpu) {
steps.push(function() {
drawCpuTotalUsage("cpu-total-usage-chart", machineInfo, containerInfo);
drawCpuTotalUsage('cpu-total-usage-chart', machineInfo, containerInfo);
});
// TODO(rjnagal): Re-enable CPU Load after understanding resource usage.
// steps.push(function() {
// drawCpuLoad("cpu-load-chart", machineInfo, containerInfo);
// });
steps.push(function() {
drawCpuPerCoreUsage("cpu-per-core-usage-chart", machineInfo, containerInfo);
drawCpuPerCoreUsage(
'cpu-per-core-usage-chart', machineInfo, containerInfo);
});
steps.push(function() {
drawCpuUsageBreakdown("cpu-usage-breakdown-chart", machineInfo, containerInfo);
drawCpuUsageBreakdown(
'cpu-usage-breakdown-chart', machineInfo, containerInfo);
});
}
// Memory.
if (containerInfo.spec.has_memory) {
steps.push(function() {
drawMemoryUsage("memory-usage-chart", machineInfo, containerInfo);
drawMemoryUsage('memory-usage-chart', machineInfo, containerInfo);
});
}
// Network.
if (containerInfo.spec.has_network) {
steps.push(function() {
drawNetworkBytes("network-bytes-chart", machineInfo, containerInfo);
drawNetworkBytes('network-bytes-chart', machineInfo, containerInfo);
});
steps.push(function() {
drawNetworkErrors("network-errors-chart", machineInfo, containerInfo);
drawNetworkErrors('network-errors-chart', machineInfo, containerInfo);
});
}
// Filesystem.
if (containerInfo.spec.has_filesystem) {
steps.push(function() {
drawFileSystemUsage(machineInfo, containerInfo);
});
steps.push(function() { drawFileSystemUsage(machineInfo, containerInfo); });
}
// Custom Metrics
if (containerInfo.spec.has_custom_metrics) {
steps.push(function() {
getCustomMetrics(window.cadvisor.rootDir, window.cadvisor.containerName, function(metricsInfo) {
drawCustomMetrics("custom-metrics-chart", containerInfo, metricsInfo)
getCustomMetrics(
window.cadvisor.rootDir, window.cadvisor.containerName,
function(metricsInfo) {
drawCustomMetrics(
'custom-metrics-chart', containerInfo, metricsInfo);
});
});
}
@ -658,10 +700,10 @@ function drawCharts(machineInfo, containerInfo) {
}
function setNetwork(interfaceName) {
$("#network-selection-text")
$('#network-selection-text')
.empty()
.append($("<span>").text("Interface: "))
.append($("<b>").text(interfaceName));
.append($('<span>').text('Interface: '))
.append($('<b>').text(interfaceName));
window.cadvisor.network.interface = interfaceName;
// Draw the new stats.
@ -670,23 +712,25 @@ function setNetwork(interfaceName) {
// Creates the network selection dropdown.
function startNetwork(selectionElement, containerInfo) {
if (!hasResource(containerInfo, "network") || containerInfo.stats.length == 0
|| !containerInfo.stats[0].network.interfaces || containerInfo.stats[0].network.interfaces.length == 0) {
if (!hasResource(containerInfo, 'network') ||
containerInfo.stats.length == 0 ||
!containerInfo.stats[0].network.interfaces ||
containerInfo.stats[0].network.interfaces.length == 0) {
return;
}
window.cadvisor.network = {};
window.cadvisor.network.interface = "";
window.cadvisor.network.interface = '';
// Add all interfaces to the dropdown.
var el = $("#" + selectionElement);
var el = $('#' + selectionElement);
for (var i = 0; i < containerInfo.stats[0].network.interfaces.length; i++) {
var interfaceName = containerInfo.stats[0].network.interfaces[i].name;
el.append($("<li>")
.attr("role", "presentation")
.append($("<a>")
.attr("role", "menuitem")
.attr("tabindex", -1)
el.append($('<li>')
.attr('role', 'presentation')
.append($('<a>')
.attr('role', 'menuitem')
.attr('tabindex', -1)
.click(setNetwork.bind(null, interfaceName))
.text(interfaceName)));
}
@ -696,18 +740,21 @@ function startNetwork(selectionElement, containerInfo) {
// Refresh the stats on the page.
function refreshStats() {
var machineInfo = window.cadvisor.machineInfo;
getStats(window.cadvisor.rootDir, window.cadvisor.containerName, function(containerInfo){
getStats(
window.cadvisor.rootDir, window.cadvisor.containerName,
function(containerInfo) {
if (window.cadvisor.firstRun) {
window.cadvisor.firstRun = false;
if (containerInfo.spec.has_filesystem) {
startFileSystemUsage("filesystem-usage", machineInfo, containerInfo);
startFileSystemUsage(
'filesystem-usage', machineInfo, containerInfo);
}
if (containerInfo.spec.has_network) {
startNetwork("network-selection", containerInfo);
startNetwork('network-selection', containerInfo);
}
if (containerInfo.spec.has_custom_metrics) {
startCustomMetrics("custom-metrics-chart", containerInfo);
startCustomMetrics('custom-metrics-chart', containerInfo);
}
}
drawCharts(machineInfo, containerInfo);
@ -721,19 +768,21 @@ function addAllLabels(containerInfo, metricsInfo) {
var metricSpec = containerInfo.spec.custom_metrics;
for (var containerName in metricsInfo) {
var container = metricsInfo[containerName];
for (i=0; i<metricSpec.length; i++) {
for (i = 0; i < metricSpec.length; i++) {
metricName = metricSpec[i].name;
metricLabelVal = container[metricName];
firstLabel = true;
for (var label in metricLabelVal) {
if (label == "") {
$('#button-'+metricName).hide();
if (label == '') {
$('#button-' + metricName).hide();
}
$("#"+metricName+"_labels").append($("<li>")
.attr("role", "presentation")
.append($("<a>")
.attr("role", "menuitem")
$('#' + metricName + '_labels')
.append(
$('<li>')
.attr('role', 'presentation')
.append($('<a>')
.attr('role', 'menuitem')
.click(setLabel.bind(null, metricName, label))
.text(label)));
if (firstLabel) {
@ -746,18 +795,17 @@ function addAllLabels(containerInfo, metricsInfo) {
}
function getMetricIndex(metricName) {
for (i = 0; i<window.cadvisor.metricLabelPair.length; ++i) {
if (window.cadvisor.metricLabelPair[i][0] == metricName)
return i;
for (i = 0; i < window.cadvisor.metricLabelPair.length; ++i) {
if (window.cadvisor.metricLabelPair[i][0] == metricName) { return i; }
}
return -1;
}
function setLabel(metric, label) {
$("#"+metric+"-selection-text")
$('#' + metric + '-selection-text')
.empty()
.append($("<span>").text("Label: "))
.append($("<b>").text(label))
.append($('<span>').text('Label: '))
.append($('<b>').text(label));
index = getMetricIndex(metric);
if (index == -1) {
@ -771,53 +819,56 @@ function setLabel(metric, label) {
function getSelectedLabel(metricName) {
index = getMetricIndex(metricName);
if (index == -1)
return "";
if (index == -1) { return ''; }
return window.cadvisor.metricLabelPair[index][1];
}
function startCustomMetrics(elementId, containerInfo) {
var metricSpec = containerInfo.spec.custom_metrics;
var metricStats = containerInfo.stats.custom_metrics;
var el=$("<div>");
var el = $('<div>');
if (metricSpec.length < window.cadvisor.maxCustomMetrics)
window.cadvisor.maxCustomMetrics = metricSpec.length
for (i = 0; i<window.cadvisor.maxCustomMetrics; i++) {
if (metricSpec.length < window.cadvisor.maxCustomMetrics) {
window.cadvisor.maxCustomMetrics = metricSpec.length;
for (i = 0; i < window.cadvisor.maxCustomMetrics; i++) {
metricName = metricSpec[i].name;
var divText = "<div class='dropdown'> <button class='btn btn-default dropdown-toggle' type='button' id='button-"+metricName;
divText += "' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>";
divText += "<span id='"+metricName+"-selection-text'></span> <span class='caret'></span> </button>";
divText += "<ul id='"+metricName+"_labels' class='dropdown-menu' role='menu' aria-labelledby='button-"+metricName+ "'> </ul> </div>";
divText += "<div id='"+elementId+"-"+metricName+"'> </div>";
var divText =
'<div class=\'dropdown\'> <button class=\'btn btn-default' +
' dropdown-toggle\' type=\'button\' id=\'button-' + metricName;
divText +=
'\' data-toggle=\'dropdown\' aria-haspopup=\'true\'' +
' aria-expanded=\'false\'>';
divText += '<span id=\'' + metricName +
'-selection-text\'></span> <span class=\'caret\'></span> </button>';
divText += '<ul id=\'' + metricName +
'_labels\' class=\'dropdown-menu\' role=\'menu\'' +
' aria-labelledby=\'button-' + metricName + '\'> </ul> </div>';
divText += '<div id=\'' + elementId + '-' + metricName + '\'> </div>';
el.append($(divText));
}
el.append($("</div>"));
}
el.append($('</div>'));
$("#"+elementId).append(el);
$('#' + elementId).append(el);
}
function getCustomMetrics(rootDir, containerName, callback) {
$.getJSON(rootDir + "api/v2.0/appmetrics/" + containerName)
.done(function(data) {
callback(data);
})
.fail(function(jqhxr, textStatus, error) {
callback([]);
});
$.getJSON(rootDir + 'api/v2.0/appmetrics/' + containerName)
.done(function(data) { callback(data); })
.fail(function(jqhxr, textStatus, error) { callback([]); });
}
function drawCustomMetrics(elementId, containerInfo, metricsInfo) {
if(metricsInfo.length == 0) {
if (metricsInfo.length == 0) {
return;
}
var metricSpec = containerInfo.spec.custom_metrics;
for (var containerName in metricsInfo) {
var container = metricsInfo[containerName];
for (i=0; i<window.cadvisor.maxCustomMetrics; i++) {
for (i = 0; i < window.cadvisor.maxCustomMetrics; i++) {
metricName = metricSpec[i].name;
metricUnits = metricSpec[i].units;
var titles = ["Time", metricName];
var titles = ['Time', metricName];
metricLabelVal = container[metricName];
if (window.cadvisor.firstCustomCollection) {
window.cadvisor.firstCustomCollection = false;
@ -833,12 +884,12 @@ function drawCustomMetrics(elementId, containerInfo, metricsInfo) {
value = metric[attribute];
elements.push(value);
}
if (elements.length<2) {
if (elements.length < 2) {
elements.push(0);
}
data.push(elements);
}
drawLineChart(titles, data, elementId+"-"+metricName, metricUnits);
drawLineChart(titles, data, elementId + '-' + metricName, metricUnits);
}
}
}
@ -862,20 +913,17 @@ function startPage(containerName, hasCpu, hasMemory, rootDir, isRoot) {
// Draw process information at start and refresh every 60s.
getProcessInfo(rootDir, containerName, function(processInfo) {
drawProcesses(isRoot, rootDir, processInfo)
drawProcesses(isRoot, rootDir, processInfo);
});
setInterval(function() {
getProcessInfo(rootDir, containerName, function(processInfo) {
drawProcesses(isRoot, rootDir, processInfo)
drawProcesses(isRoot, rootDir, processInfo);
});
}, 60000);
// Get machine info, then get the stats every 1s.
getMachineInfo(rootDir, function(machineInfo) {
window.cadvisor.machineInfo = machineInfo;
setInterval(function() {
refreshStats();
}, 1000);
setInterval(function() { refreshStats(); }, 1000);
});
}
`

View File

@ -1,20 +1,3 @@
// Copyright 2015 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 gchartsJs = `
(function() {
var aa=encodeURIComponent,ba=window,ca=Object,da=Infinity,ea=document,fa=isNaN,h=Math,ga=Array,ha=Number,ia=NaN,m=Error,ja=Boolean,ka=parseInt,la=parseFloat,na=isFinite,oa=decodeURIComponent;function pa(a,b){return a.width=b}function qa(a,b){return a.data=b}function ra(a,b){return a.ceil=b}function sa(a,b){return a.floor=b}function ta(a,b){return a.format=b}function ua(a,b){return a.remove=b}function va(a,b){return a.clear=b}function wa(a,b){return a.getColumnIndex=b}
function xa(a,b){return a.stroke=b}function ya(a,b){return a.getTime=b}function za(a,b){return a.fill=b}function Aa(a,b){return a.toString=b}function Ba(a,b){return a.position=b}function Ca(a,b){return a.toJSON=b}function Da(a,b){return a.next=b}function Ea(a,b){return a.constructor=b}function Fa(a,b){return a.fontSize=b}function Ga(a,b){return a.message=b}function Ia(a,b){return a.clone=b}function Ka(a,b){return a.start=b}function La(a,b){return a.init=b}function Ma(a,b){return a.bottom=b}
@ -1392,4 +1375,4 @@ xx(oX[K],oX[K][hA]);Cw(oX[K],oX[K][qy]);oX[K].setAction=oX[K].dj;oX[K].getAction
google.load('visualization','1',{packages: ['corechart', 'gauge', 'default', 'format', 'ui', 'table']});
google.loader.loaded({"module":"visualization","version":"1.0","components":["ui","corechart","default","gauge","format"]});
google.loader.eval.visualization = function() {eval(arguments[0]);};if (google.loader.eval.scripts && google.loader.eval.scripts['visualization']) {(function() {var scripts = google.loader.eval.scripts['visualization'];for (var i = 0; i < scripts.length; i++) {google.loader.eval.visualization(scripts[i]);}})();google.loader.eval.scripts['visualization'] = null;}})();`
google.loader.eval.visualization = function() {eval(arguments[0]);};if (google.loader.eval.scripts && google.loader.eval.scripts['visualization']) {(function() {var scripts = google.loader.eval.scripts['visualization'];for (var i = 0; i < scripts.length; i++) {google.loader.eval.visualization(scripts[i]);}})();google.loader.eval.scripts['visualization'] = null;}})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -32,6 +32,7 @@ const containersHtmlTemplate = `
<script type="text/javascript" src="{{.Root}}static/google-jsapi.js"></script>
<script type="text/javascript" src="{{.Root}}static/containers.js"></script>
<script type="text/javascript" src="{{.Root}}static/gcharts.js"></script>
</head>
<body>
<div class="container theme-showcase" >

419
pages/static/assets.go Normal file

File diff suppressed because one or more lines are too long

View File

@ -26,14 +26,25 @@ import (
const StaticResource = "/static/"
var staticFiles = map[string]string{
var bootstrapJs, _ = Asset("pages/assets/js/bootstrap-3.1.1.min.js")
var containersJs, _ = Asset("pages/assets/js/containers.js")
var gchartsJs, _ = Asset("pages/assets/js/gcharts.js")
var googleJsapiJs, _ = Asset("pages/assets/js/google-jsapi.js")
var jqueryJs, _ = Asset("pages/assets/js/jquery-1.10.2.min.js")
var bootstrapCss, _ = Asset("pages/assets/styles/bootstrap-3.1.1.min.css")
var bootstrapThemeCss, _ = Asset("pages/assets/styles/bootstrap-theme-3.1.1.min.css")
var containersCss, _ = Asset("pages/assets/styles/containers.css")
var staticFiles = map[string][]byte{
"bootstrap-3.1.1.min.css": bootstrapCss,
"bootstrap-3.1.1.min.js": bootstrapJs,
"bootstrap-theme-3.1.1.min.css": bootstrapThemeCss,
"containers.css": containersCss,
"containers.js": containersJs,
"bootstrap-3.1.1.min.css": bootstrapCss,
"bootstrap-theme-3.1.1.min.css": bootstrapThemeCss,
"jquery-1.10.2.min.js": jqueryJs,
"bootstrap-3.1.1.min.js": bootstrapJs,
"gcharts.js": gchartsJs,
"google-jsapi.js": googleJsapiJs,
"jquery-1.10.2.min.js": jqueryJs,
}
func HandleRequest(w http.ResponseWriter, u *url.URL) error {
@ -54,6 +65,6 @@ func HandleRequest(w http.ResponseWriter, u *url.URL) error {
w.Header().Set("Content-Type", contentType)
}
_, err := w.Write([]byte(content))
_, err := w.Write(content)
return err
}