Commit c4d460dd authored by Leigh B Stoller's avatar Leigh B Stoller

Add the idledata graphs. Remember, it takes a few extra seconds to get the

data from the remote cluster and graph it.
parent 186b8a6a
......@@ -99,10 +99,15 @@ echo " window.CREATOR = '" . $creator . "';\n";
echo " window.DAYS = $days;\n";
echo "</script>\n";
echo "<link rel='stylesheet'
href='css/nv.d3.css'>\n";
# Place to hang the toplevel template.
echo "<div id='main-body'></div>\n";
SPITREQUIRE("adminextend",
"<script src='js/lib/d3.v3.js'></script>".
"<script src='js/lib/nv.d3.js'></script>".
"<script src='js/lib/jquery.tablesorter.min.js'></script>".
"<script src='js/lib/jquery.tablesorter.widgets.min.js'></script>".
"<script src='js/lib/sugar.min.js'></script>".
......
......@@ -24,6 +24,7 @@ function (_, sup, moment, mainString, waitwaitString, oopsString)
extensionsTemplate = _.template($('#history-template', html).html());
LoadUtilization();
LoadIdleData();
LoadFirstRow();
// Second row is the user/project usage summarys. We make two calls
......@@ -202,6 +203,199 @@ function (_, sup, moment, mainString, waitwaitString, oopsString)
xmlthing.done(callback);
}
function LoadIdleData()
{
var exptTraffic = [];
var ctrlTraffic = [];
var loadavs = [];
var ProcessSite = function(idledata) {
/*
* Array of objects, one per node. But some nodes might not
* have any data (main array is zero), so need to skip those.
*/
var index = 0;
for (var i in idledata) {
var obj = idledata[i];
var node_id = obj.node_id;
var loadvalues = [];
//
// If idlestats finds no data, the main array is zero length.
// Skip.
//
if (obj.main.length == 0) {
console.info("No idledata for " + node_id);
continue;
}
// The main array is the load average data.
for (var j = 1; j < obj.main.length; j++) {
var loads = obj.main[j];
loadvalues[j - 1] = {
// convert seconds to milliseconds.
"x" : loads[0] * 1000,
"y" : loads[3],
};
}
loadavs[index] = {
"key" : node_id,
"area" : 0,
"values" : loadvalues,
};
var control_iface = obj.interfaces.ctrl_iface;
for (var mac in obj.interfaces) {
//console.info(mac, obj.interfaces[mac]);
if (mac == "ctrl_iface") {
continue;
}
if (obj.interfaces[mac].length) {
var trafficvalues = [];
for (var j = 1; j < obj.interfaces[mac].length; j++) {
var data = obj.interfaces[mac][j];
trafficvalues[j - 1] = {
"x" : data[0] * 1000,
"y" : data[1] + data[2]
};
}
var datum = {
"key" : node_id,
"area" : 0,
"values" : trafficvalues,
};
if (mac == control_iface) {
ctrlTraffic[index] = datum;
}
else {
exptTraffic[index] = datum;
}
}
}
index++;
}
};
var callback = function(json) {
if (json.code) {
console.info("Failed to get idledata: " + json.value);
return;
}
_.each(json.value, function(data, name) {
var idledata = JSON.parse(data);
ProcessSite(idledata);
});
//console.info(loadavs);
//console.info(ctrlTraffic);
//console.info(exptTraffic);
if (loadavs.length) {
$("#loadavg-panel-div").removeClass("hidden");
$("#loadavg-collapse").addClass("in");
window.nv.addGraph(function() {
var chart = window.nv.models.lineWithFocusChart();
CreateIdleGraph('#loadavg-chart svg',
chart, loadavs, "float");
});
}
if (ctrlTraffic.length) {
$("#ctrl-traffic-panel-div").removeClass("hidden");
$("#ctrl-traffic-collapse").addClass("in");
window.nv.addGraph(function() {
var chart = window.nv.models.lineWithFocusChart();
CreateIdleGraph('#ctrl-traffic-chart svg',
chart, ctrlTraffic, "int");
});
}
if (exptTraffic.length) {
$("#expt-traffic-panel-div").removeClass("hidden");
$("#expt-traffic-collapse").addClass("in");
window.nv.addGraph(function() {
var chart = window.nv.models.lineWithFocusChart();
CreateIdleGraph('#expt-traffic-chart svg',
chart, exptTraffic, "int");
});
}
};
var xmlthing = sup.CallServerMethod(null, "status", "IdleData",
{"uuid" : window.UUID});
xmlthing.done(callback);
}
function CreateIdleGraph(id, chart, datums, ytype) {
var tickMultiFormat = d3.time.format.multi([
// not the beginning of the hour
["%-I:%M%p", function(d) { return d.getMinutes(); }],
// not midnight
["%-I%p", function(d) { return d.getHours(); }],
// not the first of the month
["%b %-d", function(d) { return d.getDate() != 1; }],
// not Jan 1st
["%b %-d", function(d) { return d.getMonth(); }],
["%Y", function() { return true; }]
]);
/*
* We need the min,max of the time stamps for the brush. We can use
* just one of the nodes.
*/
var minTime = d3.min(datums[0].values,
function (d) { return d.x; });
var maxTime = d3.max(datums[0].values,
function (d) { return d.x; });
// Adjust the brush to the last day.
if (maxTime - minTime > (3600 * 24 * 1000)) {
minTime = maxTime - (3600 * 24 * 1000);
}
chart.brushExtent([minTime,maxTime]);
// We want different Y axis scales, wow this took a long time
// to figure out.
chart.lines.scatter.yScale(d3.scale.sqrt());
chart.yAxis.scale(d3.scale.sqrt());
chart.xAxis.tickFormat(function (d) {
return tickMultiFormat(new Date(d));
});
chart.x2Axis.tickFormat(function (d) {
return tickMultiFormat(new Date(d));
});
if (ytype == "float") {
chart.yAxis.tickFormat(d3.format(',.2f'));
chart.y2Axis.tickFormat(d3.format(',.2f'));
}
else {
chart.yAxis.tickFormat(d3.format(',.0f'));
chart.y2Axis.tickFormat(d3.format(',.0f'));
}
chart.useInteractiveGuideline(true);
d3.select(id)
.datum(datums)
.call(chart);
// set up the tooltip to display full dates
var tsFormat = d3.time.format('%b %-d, %Y %I:%M%p');
var contentGenerator = chart.interactiveLayer.tooltip.contentGenerator();
var tooltip = chart.interactiveLayer.tooltip;
tooltip.contentGenerator(function (d) {
d.value = d.series[0].data.x; return contentGenerator(d);
});
tooltip.headerFormatter(function (d) {
return tsFormat(new Date(d));
});
tooltip.classes("tooltip-font");
window.nv.utils.windowResize(chart.update);
return chart;
}
// Helper.
function decodejson(id) {
return JSON.parse(_.unescape($(id)[0].textContent));
......
......@@ -3,6 +3,10 @@
max-height:350px;
overflow-y:scroll;
}
.fixedsize-panel {
max-height:350px;
height:350px;
}
td textarea {
width: 100%;
height: 100%;
......@@ -115,6 +119,78 @@ pre {
<div id='waitwait_div'></div>
<div id='oops_div'></div>
</div>
<div class='row'>
<div class='col-sm-10 col-sm-offset-1
col-xs-12 col-xs-offset-0'>
<div class='panel panel-default hidden' id="loadavg-panel-div">
<div class="panel-heading">
<h5>
<a data-toggle="collapse" id="loadavg-toggle"
href="#loadavg-collapse"><span>Load Average Graph</span>
<span class="glyphicon glyphicon-chevron-right pull-right"></span>
</a>
</h5>
</div>
<div id="loadavg-collapse"
class="panel-collapse collapse">
<div class='panel-body'>
<div id="loadavg-chart"
class='fixedsize-panel with-3d-shadow with-transitions'>
<svg></svg>
</div>
</div>
</div>
</div>
</div>
</div>
<div class='row'>
<div class='col-sm-10 col-sm-offset-1
col-xs-12 col-xs-offset-0'>
<div class='panel panel-default hidden' id="ctrl-traffic-panel-div">
<div class="panel-heading">
<h5>
<a data-toggle="collapse" id="ctrl-traffic-toggle"
href="#ctrl-traffic-collapse"><span>Control Traffic Graph</span>
<span class="glyphicon glyphicon-chevron-right pull-right"></span>
</a>
</h5>
</div>
<div id="ctrl-traffic-collapse"
class="panel-collapse collapse">
<div class='panel-body'>
<div id="ctrl-traffic-chart"
class='fixedsize-panel with-3d-shadow with-transitions'>
<svg></svg>
</div>
</div>
</div>
</div>
</div>
</div>
<div class='row'>
<div class='col-sm-10 col-sm-offset-1
col-xs-12 col-xs-offset-0'>
<div class='panel panel-default hidden' id="expt-traffic-panel-div">
<div class="panel-heading">
<h5>
<a data-toggle="collapse" id="expt-traffic-toggle"
href="#expt-traffic-collapse"><span>Experiment Traffic Graph</span>
<span class="glyphicon glyphicon-chevron-right pull-right"></span>
</a>
</h5>
</div>
<div id="expt-traffic-collapse"
class="panel-collapse collapse">
<div class='panel-body'>
<div id="expt-traffic-chart"
class='fixedsize-panel with-3d-shadow with-transitions'>
<svg></svg>
</div>
</div>
</div>
</div>
</div>
</div>
<div>
<script id="history-template" type="text/template">
<table class="table table-condensed">
......@@ -202,7 +278,7 @@ pre {
</div>
</script>
</div>
<div>app
<div>
<script id="secondrow-template" type="text/template">
<div class='col-sm-6'>
<div class='panel panel-default'>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment