Visualize Zuul's NNFI scheduler

Adds a subway map to the status page that reflects the current
proposed merge state according to Zuul's NNFI scheduler.

Makes the screen wider (1024 instead of 950 px) to accomodate
the additional width of the subway map.

Widen the graphs as well to match (also, evenly space them).

Change-Id: I11689c24c5d4aa58bb2dac3c595068e24af7e1d5
This commit is contained in:
James E. Blair 2013-09-13 11:42:46 -07:00
parent f6b08577c5
commit dd1786701f
7 changed files with 184 additions and 85 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

View File

@ -2,14 +2,81 @@
xmlns:py="http://genshi.edgewall.org/"
lang="en">
<HEAD>
<TITLE>Zuul Status</TITLE>
<script type="text/javascript"
src="http://status.openstack.org/jquery.min.js"></script>
<script type="text/javascript"
src="http://status.openstack.org/jquery-visibility.min.js"></script>
<script type="text/javascript"
src="http://status.openstack.org/jquery-graphite.js"></script>
<script type="text/javascript"
src="http://status.openstack.org/common.js"></script>
<script type="text/javascript"
src="status.js"></script>
<!-- Google Fonts -->
<link href='http://fonts.googleapis.com/css?family=PT+Sans&amp;subset=latin' rel='stylesheet' type='text/css'/>
<!-- Framework CSS -->
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/blueprint/screen.css" type="text/css" media="screen, projection"/>
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/blueprint/print.css" type="text/css" media="print"/>
<!-- IE CSS -->
<!--[if lt IE 8]><link rel="stylesheet" href="http://www.openstack.org/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->
<!-- OpenStack Specific CSS -->
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/dropdown.css" type="text/css" media="screen, projection, print"/>
<!-- Page Specific CSS -->
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/home.css" type="text/css" media="screen, projection, print"/>
<link rel="stylesheet" type="text/css" href="http://www.openstack.org/themes/openstack/css/main.css" />
<style type="text/css">
.container {
width: 1024px;
}
#pipeline-container {
max-width: 950px;
margin: 0 auto;
}
.line {
background-image: url('line.png');
background-repeat: repeat-y;
}
.pipeline {
float: left;
padding: 4px;
}
.pipeline > .header {
background: #0000cc;
color: white;
}
.pipeline > .subhead > .count {
float: right;
margin-right: 1em;
color: #535353;
font-size: 11pt;
}
.pipeline table {
margin: 0 0 2px 0;
}
.pipeline table td {
margin: 0;
padding: 0 0 10px 0;
}
td.graph {
width: 16px;
height: 100%;
vertical-align: top;
}
.pipeline table td.change-container {
padding-left: 4px;
}
.change {
border: 1px solid #95c7db;
margin-top: 10px;
padding: 2px;
}
.change > .header {
@ -24,28 +91,9 @@
.change > .header > .time {
float: right;
}
.pipeline > .subhead > .count {
float: right;
margin-right: 1em;
color: #535353;
font-size: 11pt;
}
.job {
display: block;
}
.pipeline {
float: left;
width: 25em;
padding: 4px;
}
.pipeline > .header {
background: #0000cc;
color: white;
}
.arrow {
text-align: center;
font-size: 16pt;
line-height: 1.0;
line-height: 1.5;
}
.result {
float: right;
@ -59,6 +107,12 @@
.result_unstable {
color: #e39f00;
}
#graph-container img {
margin-left: 10px;
}
#graph-container img:first-of-type {
margin-left: 0px;
}
a:link {
color: #204A87;
}
@ -143,37 +197,6 @@ progress[aria-valuenow]:before {
</style>
<TITLE>Zuul Status</TITLE>
<script type="text/javascript"
src="http://status.openstack.org/jquery.min.js"></script>
<script type="text/javascript"
src="http://status.openstack.org/jquery-visibility.min.js"></script>
<script type="text/javascript"
src="http://status.openstack.org/jquery-graphite.js"></script>
<script type="text/javascript"
src="http://status.openstack.org/common.js"></script>
<script type="text/javascript"
src="status.js"></script>
<!-- Google Fonts -->
<link href='http://fonts.googleapis.com/css?family=PT+Sans&amp;subset=latin' rel='stylesheet' type='text/css'/>
<!-- Framework CSS -->
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/blueprint/screen.css" type="text/css" media="screen, projection"/>
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/blueprint/print.css" type="text/css" media="print"/>
<!-- IE CSS -->
<!--[if lt IE 8]><link rel="stylesheet" href="http://www.openstack.org/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->
<!-- OpenStack Specific CSS -->
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/dropdown.css" type="text/css" media="screen, projection, print"/>
<!-- Page Specific CSS -->
<link rel="stylesheet" href="http://www.openstack.org/themes/openstack/css/home.css" type="text/css" media="screen, projection, print"/>
<link rel="stylesheet" type="text/css" href="http://www.openstack.org/themes/openstack/css/main.css" />
</HEAD>
<BODY>
@ -211,8 +234,8 @@ $.fn.graphite.defaults.url = "http://graphite.openstack.org/render/";
$("#graph-container").append($(new Image()).addClass('graph').graphite({
from: "-24hours",
width: 310,
height: 170,
width: 334,
height: 180,
bgcolor: 'ffffff',
fgcolor: '000000',
areaMode: 'stacked',
@ -227,8 +250,8 @@ $("#graph-container").append($(new Image()).addClass('graph').graphite({
$("#graph-container").append($(new Image()).addClass('graph').graphite({
from: "-24hours",
width: 310,
height: 170,
width: 334,
height: 180,
bgcolor: 'ffffff',
fgcolor: '000000',
target: [
@ -239,8 +262,8 @@ $("#graph-container").append($(new Image()).addClass('graph').graphite({
$("#graph-container").append($(new Image()).addClass('graph').graphite({
from: "-24hours",
width: 310,
height: 170,
width: 334,
height: 180,
bgcolor: 'ffffff',
fgcolor: '000000',
target: [

View File

@ -68,38 +68,86 @@ function is_hide_project(project) {
return hide;
}
function count_changes(pipeline) {
function remove(l, idx) {
l[idx] = null;
while (l[l.length-1] === null) {
l.pop();
}
}
function create_graph(pipeline) {
var count = 0;
var pipeline_max_graph_columns = 1;
$.each(pipeline['change_queues'], function(change_queue_i, change_queue) {
var graph = [];
var max_graph_columns = 1;
var changes = [];
var last_graph_length = 0;
$.each(change_queue['heads'], function(head_i, head) {
count += head.length;
$.each(head, function(change_i, change) {
changes[change['id']] = change;
change['_graph_position'] = change_i;
});
});
$.each(change_queue['heads'], function(head_i, head) {
$.each(head, function(change_i, change) {
count += 1;
var idx = graph.indexOf(change['id']);
if (idx > -1) {
change['_graph_index'] = idx;
remove(graph, idx);
} else {
change['_graph_index'] = 0;
}
change['_graph_branches'] = [];
change['_graph'] = [];
change['items_behind'].sort(function(a, b) {
return changes[b]['_graph_position'] - changes[a]['_graph_position'];
});
$.each(change['items_behind'], function(i, id) {
graph.push(id);
if (last_graph_length>0 && graph.length>last_graph_length)
change['_graph_branches'].push(graph.length-1);
});
if (graph.length > max_graph_columns) {
max_graph_columns = graph.length;
}
if (graph.length > pipeline_max_graph_columns) {
pipeline_max_graph_columns = graph.length;
}
change['_graph'] = graph.slice(0); // make a copy
last_graph_length = graph.length;
});
});
change_queue['_graph_columns'] = max_graph_columns;
});
pipeline['_graph_columns'] = pipeline_max_graph_columns;
return count;
}
function get_sparkline_url(pipeline_name) {
if (!(pipeline_name in window.zuul_sparkline_urls)) {
window.zuul_sparkline_urls[pipeline_name] = $.fn.graphite.geturl({
url: "http://graphite.openstack.org/render/",
from: "-8hours",
width: 100,
height: 16,
margin: 0,
hideLegend: true,
hideAxes: true,
hideGrid: true,
target: [
"color(stats.gauges.zuul.pipeline."+pipeline_name+".current_changes, '6b8182')",
],
});
window.zuul_sparkline_urls[pipeline_name] = $.fn.graphite.geturl({
url: "http://graphite.openstack.org/render/",
from: "-8hours",
width: 100,
height: 16,
margin: 0,
hideLegend: true,
hideAxes: true,
hideGrid: true,
target: [
"color(stats.gauges.zuul.pipeline."+pipeline_name+".current_changes, '6b8182')",
],
});
}
return window.zuul_sparkline_urls[pipeline_name];
}
function format_pipeline(data) {
var count = count_changes(data);
var html = '<div class="pipeline"><h3 class="subhead">'+
var count = create_graph(data);
var width = (16 * data['_graph_columns']) + 300;
var html = '<div class="pipeline" style="width:'+width+'"><h3 class="subhead">'+
data['name'];
html += '<span class="count"><img src="' + get_sparkline_url(data['name']);
@ -134,13 +182,11 @@ function format_pipeline(data) {
}
html += name + '</a></div>';
}
html += '<table>'
$.each(head, function(change_i, change) {
if (change_i > 0) {
html += '<div class="arrow">&uarr;</div>';
}
html += format_change(change);
html += format_change(change, change_queue);
});
html += '</div>'
html += '</table></div>'
});
});
@ -148,8 +194,38 @@ function format_pipeline(data) {
return html;
}
function format_change(change) {
var html = '<div class="change"><div class="header">';
function safe_id(id) {
return id.replace(',', '_');
}
function format_change(change, change_queue) {
var html = '<tr>';
for (var i=0; i<change_queue['_graph_columns']; i++) {
var cls = 'graph';
if (i < change['_graph'].length && change['_graph'][i] !== null) {
cls += ' line';
}
html += '<td class="'+cls+'">';
if (i == change['_graph_index']) {
if (change['failing_reasons'] && change['failing_reasons'].length > 0) {
html += '<img src="red.png" title="Failing because '+
change['failing_reasons'].join(', ')+'"/>';
} else {
html += '<img src="green.png" title="Succeeding"/>';
}
}
if (change['_graph_branches'].indexOf(i) != -1) {
if (change['_graph_branches'].indexOf(i) == change['_graph_branches'].length-1)
html += '<img src="line-angle.png"/>';
else
html += '<img src="line-t.png"/>';
}
html += '</td>';
}
html += '<td class="change-container">';
html += '<div class="change" id="'+safe_id(change['id'])+'"><div class="header">';
html += '<span class="project">'+change['project']+'</span>';
var id = change['id'];
@ -209,7 +285,7 @@ function format_change(change) {
html += '</span>';
});
html += '</div></div>';
html += '</div></div></td></tr>';
return html;
}
@ -275,7 +351,7 @@ function update_graphs() {
var parts = url.split('#');
newimg.src = parts[0] + '#' + new Date().getTime();
$(newimg).load(function (x) {
window.zuul_sparkline_urls[name] = newimg.src;
window.zuul_sparkline_urls[name] = newimg.src;
});
});
}