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:
parent
f6b08577c5
commit
dd1786701f
BIN
modules/openstack_project/files/zuul/green.png
Normal file
BIN
modules/openstack_project/files/zuul/green.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 409 B |
BIN
modules/openstack_project/files/zuul/line-angle.png
Normal file
BIN
modules/openstack_project/files/zuul/line-angle.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 281 B |
BIN
modules/openstack_project/files/zuul/line-t.png
Normal file
BIN
modules/openstack_project/files/zuul/line-t.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 216 B |
BIN
modules/openstack_project/files/zuul/line.png
Normal file
BIN
modules/openstack_project/files/zuul/line.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 B |
BIN
modules/openstack_project/files/zuul/red.png
Normal file
BIN
modules/openstack_project/files/zuul/red.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 409 B |
@ -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&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&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: [
|
||||
|
@ -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">↑</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;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user