blob: e5dbc03750592f4d4ff08ecc36fc7ab3b207dbff [file] [log] [blame]
<!--
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. See accompanying LICENSE file.
-->
<!doctype>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap.min.css" media="screen">
<link rel="stylesheet" href="css/bootstrap-responsive.min.css">
<style type="text/css">
body {
font: 20px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 20px;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 3px;
}
.legend {
padding: 1px;
font: 18px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.title {
font: 24px sans-serif;
}
.divborder {
border-width: 1px;
border-style: solid;
border-color: black;
margin-top:10px
}
</style>
<script src="js/thirdparty/d3.v3.js"></script>
<script src="js/thirdparty/jquery.js"></script>
<script src="js/thirdparty/bootstrap.min.js"></script>
</head>
<body>
<div class="row">
<div class="offset5" style="margin-top:20px; margin-bottom:20px">
Select the generated metrics log file (realtimetrack.json): <input type='file' id='jsonfile' /> <input type='button' value='Generate !' onClick='draw()' /><br>
</div>
</div>
<div>
<div id="error-div" style="display:none">
<div class="alert alert-danger" role="alert" style="margin-left:20%; margin-right:20%">
<span id="error-message"></span>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
</div>
</div>
<div id="data" style="display:none;">
<div class="row">
<div class="divborder span8 chart-area" style="margin-left:50px" id="area1"></div>
<div class="divborder span8 chart-area" id="area2"></div>
</div>
<div class="row">
<div class="divborder span8 chart-area" style="margin-left:50px" id="area3"></div>
<div class="divborder span8 chart-area" id="area4"></div>
</div>
<div class="row">
<div class="divborder span8 chart-area" style="margin-left:50px" id="area5"></div>
<div class="divborder span8 chart-area" id="area6"></div>
</div>
<div class="row">
<div class="divborder span8 " style="margin-left:50px" id="area7"></div>
<div class="span7 chart-area" id="area8"></div>
</div>
<div class="row">
<div class="divborder span8 chart-area" style="margin-left:50px" id="area9"></div>
<div class="divborder span8 chart-area" id="area10"></div>
</div>
</div>
<p>&nbsp;</p>
<script>
// select file and draw
function draw() {
$("#error-div").css("display", "none");
var filepath = document.getElementById('jsonfile').value;
if (filepath) {
$(".chart-area").empty();
filepath = filepath.replace("C:\\fakepath\\", "");
drawCharts(filepath);
} else {
$("#error-message").html("Please choose file.");
$("#error-div").css("display", "block");
$("#data").css("display", "none");
}
}
function drawCharts(filepath) {
$.getJSON(filepath, function(data) {
var numQueues = 0;
var queueNames = new Array();
for (var j in data[0]) {
if (j.substring(0, 'queue'.length) === 'queue') {
queueNames[numQueues] = j;
numQueues ++;
}
}
numQueues /= 2;
// create graph
$.getJSON(filepath, function(data) {
var basetime = data[0].time;
data.forEach(function(d) {
d.time = (d.time - basetime) / 1000;
});
var legends = ["running.applications", "running.containers"];
drawEachChart("#area1", data, legends, "Cluster running applications & containers", "Number", 0, 0);
legends = ["jvm.free.memory", "jvm.max.memory", "jvm.total.memory"];
drawEachChart("#area2", data, legends, "JVM memory", "Memory (GB)", 0, 0);
legends = ["cluster.allocated.memory", "cluster.available.memory"];
drawEachChart("#area3", data, legends, "Cluster allocated & available memory", "Memory (GB)", 0, 0);
legends = ["cluster.allocated.vcores", "cluster.available.vcores"];
drawEachChart("#area4", data, legends, "Cluster allocated & available vcores", "Number", 0, 0);
for (var i = 0; i < numQueues; i ++) {
legends[i] = queueNames[i * 2];
}
drawEachChart("#area5", data, legends, "Queue allocated memory", "Memory (GB)", 1, 100);
for (var i = 0; i < numQueues; i ++) {
legends[i] = queueNames[i * 2 + 1];
}
drawEachChart("#area6", data, legends, "Queue allocated vcores", "VCores", 1, 90);
legends = [
"scheduler.allocate.timecost",
"scheduler.handle-NODE_ADDED.timecost", "scheduler.handle-NODE_REMOVED.timecost",
"scheduler.handle-NODE_UPDATE.timecost", "scheduler.handle-APP_ADDED.timecost",
"scheduler.handle-APP_REMOVED.timecost", "scheduler.handle-CONTAINER_EXPIRED.timecost"
];
drawEachChart("#area7", data, legends, "Scheduler allocate & handle operations timecost", "Timecost (ms)", 0, 210);
// Node usage stats
legends = [
"nodes.memory.unused", "nodes.memory.1to19pctUsed",
"nodes.memory.20to39pctUsed", "nodes.memory.40to59pctUsed",
"nodes.memory.60to79pctUsed","nodes.memory.80to99pctUsed",
"nodes.memory.full"
];
drawEachChart("#area9", data, legends, "Cluster nodes memory usage", "Node count", 1, 0);
legends = [
"nodes.vcores.unused", "nodes.vcores.1to19pctUsed",
"nodes.vcores.20to39pctUsed", "nodes.vcores.40to59pctUsed",
"nodes.vcores.60to79pctUsed", "nodes.vcores.80to99pctUsed",
"nodes.vcores.full"
];
drawEachChart("#area10", data, legends, "Cluster nodes vcores usage", "Node count", 1, 0);
});
}).done(function() {
$("#data").css("display", "block");
}).fail(function(jqxhr, textStatus, error) {
$("#error-message").html(String(error));
$("#error-div").css("display", "block");
$("#data").css("display", "none");
});
}
// draw different chart
function drawEachChart(chartArea, data, legends, title, yLabelTitle, isArea, pl) {
// drawchart
var margin = {top: 50, right: 250, bottom: 50, left: 70};
var width = 800 - margin.left - margin.right;
var height = 420 - margin.top - margin.bottom;
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
var xAxis = d3.svg.axis().scale(x).orient("bottom");
var yAxis = d3.svg.axis().scale(y).orient("left");
var color = d3.scale.category10();
if (isArea == 1) {
var area = d3.svg.area()
.x(function(d) { return x(d.time); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); });
var stack = d3.layout.stack()
.values(function(d) { return d.values; });
// create chart
var svg = d3.select(chartArea).append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
color.domain(d3.keys(data[0])
.filter(function(key) {return $.inArray(key, legends) !== -1; }));
var points = stack(color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {time: d.time, y: d[name]};
})
};
}));
// x & y
x.domain(d3.extent(data, function(d) { return d.time; }));
y.domain([
d3.min(points, function(c) {
return 0.9 * d3.min(c.values, function(v) { return v.y; }); }),
d3.max(points, function(c) {
return 1.1 * d3.max(c.values, function(v) { return v.y + v.y0; }); })
]);
svg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "translate(" + (width / 2) + ", 45)")
.style("text-anchor", "middle")
.text("Time (s)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text(yLabelTitle);
var point = svg.selectAll(".point")
.data(points)
.enter().append("g");
point.append("path")
.attr("class", "area")
.attr("d", function(d) { return area(d.values); })
.style("fill", function(d) { return color(d.name); });
} else {
// lines
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.time); })
.y(function(d) { return y(d.value); });
// create chart
var svg = d3.select(chartArea).append("svg")
.attr("id", title)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
color.domain(d3.keys(data[0])
.filter(function(key) {return $.inArray(key, legends) !== -1; }));
var values = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {time: d.time, value: +d[name]};
})
};
});
// x & y
x.domain(d3.extent(data, function(d) { return d.time; }));
y.domain([
d3.min(values, function(c) { return 0.9 * d3.min(c.values, function(v) { return v.value; }); }),
d3.max(values, function(c) { return 1.1 * d3.max(c.values, function(v) { return v.value; }); })
]);
svg.append("g").attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("transform", "translate(" + (width / 2) + ", 45)")
.style("text-anchor", "middle")
.text("Time (s)");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x",0 - (height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.text(yLabelTitle);
var value = svg.selectAll(".city")
.data(values)
.enter().append("g")
.attr("class", "city");
value.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
}
// title
svg.append("text")
.attr("x", (width / 2))
.attr("y", 10 - (margin.top / 2))
.attr("text-anchor", "middle")
.text(title);
// legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("x", width - 50)
.attr("y", 25)
.attr("height", 120)
.attr("width", 140);
legend.selectAll('g').data(legends)
.enter()
.append('g')
.each(function(d, i) {
var g = d3.select(this);
g.append("rect")
.attr("x", width - 5 - pl)
.attr("y", i*20 + 0)
.attr("width", 10)
.attr("height", 10)
.style("fill", color(d));
g.append("text")
.attr("x", width + 15 - pl)
.attr("y", i * 20 + 8)
.attr("height",30)
.attr("width",250)
.style("fill", color(d))
.text(d);
});
}
</script>
</body>
</html>