Commit 61dba9ea authored by Leigh Stoller's avatar Leigh Stoller

Add experiment duration graphs, links off the summary stats page.

parent 8eb4b9bb
require(window.APT_OPTIONS.configObject,
['underscore', 'js/quickvm_sup', 'moment',
'js/lib/text!template/summary-graphs.html'],
function (_, sup, moment, templateString)
{
'use strict';
var isadmin = 0;
function initialize()
{
window.APT_OPTIONS.initialize(sup);
isadmin = window.ISADMIN;
ShowGraphs();
}
function ShowGraphs()
{
var callback = function(json) {
console.log(json);
$('#page-body').html(templateString);
PlotGraph(json.value.oneday, "duration_oneday");
PlotGraph(json.value.month, "duration_month");
}
var xmlthing = sup.CallServerMethod(null, "sumstats",
"GetDurationInfo", null);
xmlthing.done(callback);
}
function PlotGraph(duration_data, id)
{
var data = duration_data.durations;
// need to sort for plotting
data.sort(function(a, b) {
return a.x - b.x;
});
// A formatter for counts.
var formatCount = d3.format(",.0f");
var margin = {top: 10, right: 30, bottom: 30, left: 50};
var width = parseInt(d3.select('#' + id).style('width'), 10)
- margin.left - margin.right;
var height = 400 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(data.map(function(d) { return d.x; }))
.rangeRoundBands([0, width], 0.1);
// Generate a histogram using uniformly-spaced bins.
//var data = d3.layout.histogram()
// .bins(x.ticks(24))(values);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.y; })])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var svg = d3.select("#" + id).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 + ")");
var bar = svg.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bar");
bar.append("rect")
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return y(d.y); })
.attr("width", x.rangeBand())
.attr("height", function(d) { return height - y(d.y); });
bar.append("text")
.attr("dy", ".75em")
.attr("y", function(d) { return y(d.y) - 10; })
.attr("x", function(d) { return x(d.x) + (x.rangeBand() / 2); })
.attr("text-anchor", "middle")
.text(function(d) { return d.y; });
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
if (0) {
svg.append("text")
.attr("transform","rotate(-90)")
.attr("y", 0 - 100)
.attr("x", 0 - 100)
.attr("dy","1em")
.text("Number of Experiments");
svg.append("text")
.attr("class","title")
.attr("x", (width / 2))
.attr("y", 10)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("text-decoration", "underline")
.text("Experiment duration in hours (up to 36 hours)");
}
}
function gaussian(x,mean,sigma) {
return ((1 / (sigma * Math.sqrt(2 * Math.PI))) *
Math.exp(-((x - mean) * (x - mean) / (2 * sigma * sigma))))
* 10200;
};
function PlotLenthsNoWork(duration_data)
{
var data = duration_data.durations;
var mean = duration_data.average;
var sigma = duration_data.stddev;
data = data.map(function(a) {
return { "y" : gaussian(a.x, mean, sigma), "x" : a.x, "oy":a.y};
});
console.log(data);
// need to sort for plotting
data.sort(function(a, b) {
return a.x - b.x;
});
console.log(data);
// line chart based on http://bl.ocks.org/mbostock/3883245
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = 800 - margin.left - margin.right,
height = 500 - 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 line = d3.svg.line()
.x(function(d) {
return x(d.x);
})
.y(function(d) {
return y(d.y);
});
var svg = d3.select("#duration_graph").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 + ")");
if (0) {
x.domain(d3.extent(data, function(d) {
return d.x;
}));
y.domain(d3.extent(data, function(d) {
return d.y;
}));
}
x.domain([0,24]);
y.domain(d3.extent(data, function(d) {
return d.oy;
}));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
}
$(document).ready(initialize);
});
......@@ -50,6 +50,11 @@ $routing = array("myprofiles" =>
"guest" => true,
"methods" => array("GetStats" =>
"Do_GetStats")),
"sumstats" =>
array("file" => "sumstats.ajax",
"guest" => false,
"methods" => array("GetDurationInfo" =>
"Do_GetDurationInfo")),
"instantiate" =>
array("file" => "instantiate.ajax",
"guest" => true,
......
<?php
#
# Copyright (c) 2000-2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
chdir("..");
include("defs.php3");
include_once("geni_defs.php");
chdir("apt");
include("quickvm_sup.php");
include_once("instance_defs.php");
$page_title = "Summary Graphs";
#
# Get current user.
#
RedirectSecure();
$this_user = CheckLoginOrRedirect();
$isadmin = (ISADMIN() ? 1 : 0);
if (! (ISADMIN() || ISFOREIGN_ADMIN())) {
SPITUSERERROR("You do not have permission to view the dashboard");
}
SPITHEADER(1);
# Place to hang the toplevel template.
echo "<div id='page-body'></div>\n";
echo "<script type='text/javascript' src='js/lib/d3.v3.js'></script>";
echo "<script type='text/javascript' src='js/lib/d3.tip.v0.6.3.js'></script>";
echo "<script src='js/lib/bootstrap.js'></script>\n";
echo "<script src='js/lib/require.js' data-main='js/summary-graphs'></script>\n";
SPITFOOTER();
?>
<?php
#
# Copyright (c) 2000-2015 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
chdir("..");
chdir("apt");
include_once("instance_defs.php");
#
# Server side of getting summary info
#
function Do_GetDurationInfo()
{
$duration_info = array();
#
# Gather up info about experiment duration for graphing.
#
$durations = array();
$average = 0;
$stddev = 0;
$query_result =
DBQueryFatal("select count(*) as count, ".
" ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600)) as duration ".
"from apt_instance_history ".
"where ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600)) <= 36 " .
"group by duration order by duration desc");
while ($row = mysql_fetch_array($query_result)) {
$count = $row["count"];
$duration = $row["duration"];
$durations[] = array("x" => $duration, "y" => intval($count));
}
$query_result =
DBQueryFatal("select avg(ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600))), ".
" std(ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600))) ".
"from apt_instance_history ".
"where ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600)) <= 36");
$row = mysql_fetch_array($query_result);
$average = $row[0];
$stddev = $row[1];
$duration_info["oneday"] = array("durations" => $durations,
"average" => $average,
"stddev" => $stddev);
$durations = array();
$query_result =
DBQueryFatal("select count(*) as count, ".
" ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600 * 24)) as duration ".
"from apt_instance_history ".
"where ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600 * 24)) <= 30 " .
"group by duration order by duration asc");
# Throw away day one.
$row = mysql_fetch_array($query_result);
while ($row = mysql_fetch_array($query_result)) {
$count = $row["count"];
$duration = $row["duration"];
$durations[] = array("x" => $duration, "y" => intval($count));
}
$query_result =
DBQueryFatal("select avg(ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600 * 24))), ".
" std(ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600 * 24))) ".
"from apt_instance_history ".
"where ceil((UNIX_TIMESTAMP(destroyed) - ".
" UNIX_TIMESTAMP(created)) / (3600 * 24)) <= 30");
$row = mysql_fetch_array($query_result);
$average = $row[0];
$stddev = $row[1];
$duration_info["month"] = array("durations" => $durations,
"average" => $average,
"stddev" => $stddev);
SPITAJAX_RESPONSE($duration_info);
}
# Local Variables:
# mode:php
# End:
?>
......@@ -425,12 +425,14 @@ if (isset($min)) {
}
if ($showby == "user") {
echo "<a href='sumstats.php?showby=project$minmax'>".
"Show project stats</a><br>\n";
"Show project stats</a>,";
}
else {
echo "<a href='sumstats.php?showby=user$minmax'>".
"Show user stats</a><br>\n";
"Show user stats</a>,";
}
echo "<a href='summary-graphs.php'> Summary Graphs</a><br>\n";
echo "<div class='row'>
<div class='col-xs-10 col-xs-offset-1'>\n";
echo " <div id='date-slider'></div>\n";
......
<style>
.panel-body-dashboard {
padding: 5px;
}
.bar rect {
fill: steelblue;
shape-rendering: crispEdges;
}
.bar text {
fill: #000;
font: 10px sans-serif;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<div class='row'>
<div class='col-sm-10 col-sm-offset-1'>
<div class='panel panel-default'>
<div class="panel-heading">
<h5><center>Experiment duration in hours (up to 36 hours)</center></h5>
</div>
<div class='panel-body panel-body-dashboard align-center'
id="duration_oneday"></div>
</div>
</div>
</div>
<div class='row'>
<div class='col-sm-10 col-sm-offset-1'>
<div class='panel panel-default'>
<div class="panel-heading">
<h5><center>Experiment duration in days (up to 30 days)</center></h5>
</div>
<div class='panel-body panel-body-dashboard align-center'
id="duration_month"></div>
</div>
</div>
</div>
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