<!doctype html>
<html ng-app="App">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Rally version 0.12.1">
<title>Rally | Rally Task Report</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.1.15-beta/nv.d3.min.js"></script>
<script type="text/javascript">
"use strict";
function changeFrameHeight(){
var ifm= document.getElementById("embedchart");
ifm.height=document.documentElement.clientHeight;
ifm.width=document.documentElement.clientWidth;
}
window.onresize=function(){
changeFrameHeight();
}
var widgetDirective = function($compile) {
var Chart = {
_render: function(node, data, chart, do_after){
nv.addGraph(function() {
d3.select(node)
.datum(data).transition().duration(0)
.call(chart);
if (typeof do_after === "function") {
do_after(node, chart)
}
nv.utils.windowResize(chart.update);
})
},
_widgets: {
Pie: "pie",
StackedArea: "stack",
Lines: "lines",
Histogram: "histogram"
},
get_chart: function(widget) {
if (widget in this._widgets) {
var name = this._widgets[widget];
return Chart[name]
}
return function() { console.log("Error: unexpected widget:", widget) }
},
pie: function(node, data, opts, do_after) {
var chart = nv.models.pieChart()
.x(function(d) { return d.key })
.y(function(d) { return d.values })
.showLabels(true)
.labelType("percent")
.donut(true)
.donutRatio(0.25)
.donutLabelsOutside(true)
.color(function(d){
if (d.data && d.data.color) { return d.data.color }
});
var colorizer = new Chart.colorizer("errors"), data_ = [];
for (var i in data) {
data_.push({key:data[i][0], values:data[i][1], color:colorizer.get_color(data[i][0])})
}
Chart._render(node, data_, chart)
},
colorizer: function(failure_key, failure_color) {
this.failure_key = failure_key || "failed_duration";
this.failure_color = failure_color || "#d62728"; // red
this.color_idx = -1;
/* NOTE(amaretskiy): this is actually a result of
d3.scale.category20().range(), excluding red color (#d62728)
which is reserved for errors */
this.colors = ["#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c",
"#98df8a", "#ff9896", "#9467bd", "#c5b0d5", "#8c564b",
"#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f", "#c7c7c7",
"#bcbd22", "#dbdb8d", "#17becf", "#9edae5"];
this.get_color = function(key) {
if (key === this.failure_key) {
return this.failure_color
}
if (this.color_idx > (this.colors.length - 2)) {
this.color_idx = 0
} else {
this.color_idx++
}
return this.colors[this.color_idx]
}
},
stack: function(node, data, opts, do_after) {
var chart = nv.models.stackedAreaChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.useInteractiveGuideline(opts.guide)
.showControls(opts.controls)
.clipEdge(true);
chart.xAxis
.axisLabel(opts.xname)
.tickFormat(opts.xformat)
.showMaxMin(opts.showmaxmin);
chart.yAxis
.orient("left")
.tickFormat(d3.format(opts.yformat || ",.3f"));
var colorizer = new Chart.colorizer(), data_ = [];
for (var i in data) {
data_.push({key:data[i][0], values:data[i][1], color:colorizer.get_color(data[i][0])})
}
Chart._render(node, data_, chart, do_after);
},
lines: function(node, data, opts, do_after) {
var chart = nv.models.lineChart()
.x(function(d) { return d[0] })
.y(function(d) { return d[1] })
.useInteractiveGuideline(opts.guide)
.clipEdge(true);
chart.xAxis
.axisLabel(opts.xname)
.tickFormat(opts.xformat)
.rotateLabels(opts.xrotate)
.showMaxMin(opts.showmaxmin);
chart.yAxis
.orient("left")
.tickFormat(d3.format(opts.yformat || ",.3f"));
var colorizer = new Chart.colorizer(), data_ = [];
for (var i in data) {
data_.push({key:data[i][0], values:data[i][1], color:colorizer.get_color(data[i][0])})
}
Chart._render(node, data_, chart, do_after)
},
histogram: function(node, data, opts) {
var chart = nv.models.multiBarChart()
.reduceXTicks(true)
.showControls(false)
.transitionDuration(0)
.groupSpacing(0.05);
chart
.legend.radioButtonMode(true);
chart.xAxis
.axisLabel("Duration (seconds)")
.tickFormat(d3.format(",.2f"));
chart.yAxis
.axisLabel("Iterations (frequency)")
.tickFormat(d3.format("d"));
Chart._render(node, data, chart)
}
};
return {
restrict: "A",
scope: { data: "=" },
link: function(scope, element, attrs) {
scope.$watch("data", function(data) {
if (! data) { return console.log("Chart has no data to render!") }
if (attrs.widget === "Table") {
var template = "<table class='striped'><thead>" +
"<tr><th ng-repeat='i in data.cols track by $index'>{{i}}<tr>" +
"</thead><tbody>" +
"<tr ng-class='data.styles[$index] ? data.styles[$index] : \"\"' ng-repeat='row in data.rows track by $index'>" +
"<td ng-repeat='i in row track by $index'>{{i}}" +
"<tr>" +
"</tbody></table>";
var el = element.empty().append($compile(template)(scope)).children()[0]
} else if (attrs.widget === "TextArea") {
var template = "<div style='padding:0 0 5px' ng-repeat='str in data track by $index'>{{str}}</div><div style='height:10px'></div>";
var el = element.empty().append($compile(template)(scope)).children()[0]
}
else if (attrs.widget == "EmbedChart") {
/* NOTE(chenxu): tag <\/script> in javascript string will be parsed incorrectly.
so we convert <\/script> to <\\/script> in python and convert it back here. */
data = data.replace(/\\\/script>/ig, "\/script>");
var template = "<iframe scrolling='no' id='embedchart' frameborder='0' onload='changeFrameHeight()' style='width:100%;'></iframe>"
var el = element.empty().append($compile(template)(scope)).children()[0];
var iframe = el.contentWindow || ( el.contentDocument.document || el.contentDocument);
iframe.document.open();
iframe.document.write(data);
iframe.document.close();
}
else {
var el_chart = element.addClass("chart").css({display:"block"});
var el = el_chart.html("<svg></svg>").children()[0];
var do_after = null;
if (attrs.widget in {StackedArea:0, Lines:0}) {
/* Hide widget if not enough data */
if ((! data.length) || (data[0].length < 1) || (data[0][1].length < 2)) {
return element.empty().css({display:"none"})
}
/* NOTE(amaretskiy): Dirty fix for changing chart width in case
if there are too long Y values that overlaps chart box. */
var do_after = function(node, chart){
var g_box = angular.element(el_chart[0].querySelector(".nv-y.nv-axis"));
if (g_box && g_box[0] && g_box[0].getBBox) {
try {
// 30 is padding aroung graphs
var width = g_box[0].getBBox().width + 30;
} catch (err) {
// This happens sometimes, just skip silently
return
}
// 890 is chart width (set by CSS)
if (typeof width === "number" && width > 890) {
width = (890 * 2) - width;
if (width > 0) {
angular.element(node).css({width:width+"px"});
chart.update()
}
}
}
}
}
else if (attrs.widget === "Pie") {
if (! data.length) {
return element.empty().css({display:"none"})
}
}
var opts = {
xname: attrs.nameX || "",
xrotate: attrs.rotateX || 0,
yformat: attrs.formatY || ",.3f",
controls: attrs.controls === "true",
guide: attrs.guide === "true",
showmaxmin: attrs.showmaxmin === "true"
};
if (attrs.formatDateX) {
opts.xformat = function(d) { return d3.time.format(attrs.formatDateX)(new Date(d)) }
} else {
opts.xformat = d3.format(attrs.formatX || "d")
}
Chart.get_chart(attrs.widget)(el, data, opts, do_after);
}
if (attrs.nameY) {
/* NOTE(amaretskiy): Dirty fix for displaying Y-axis label correctly.
I believe sometimes NVD3 will allow doing this in normal way */
var label_y = angular.element("<div>").addClass("chart-label-y").text(attrs.nameY);
angular.element(el).parent().prepend(label_y)
}
if (attrs.description) {
var desc_el = angular.element("<div>").addClass(attrs.descriptionClass || "h3").text(attrs.description);
angular.element(el).parent().prepend(desc_el)
}
if (attrs.title) {
var title_el = angular.element("<div>").addClass(attrs.titleClass || "h2").text(attrs.title);
angular.element(el).parent().prepend(title_el)
}
angular.element(el).parent().append(angular.element("<div style='clear:both'>"))
});
}
}
};
var controllerFunction = function($scope, $location) {
$scope.source = "{\n \"version\": 2, \n \"title\": \"\", \n \"description\": \"\", \n \"subtasks\": [\n {\n \"title\": \"Keystone Stress test\", \n \"description\": \"Include just one scenario:\\n1. Keystone.create_tenant_with_users\\n\", \n \"workloads\": [\n {\n \"scenario\": {\n \"MyKeystone.create_tenant_with_users\": {\n \"users_per_tenant\": 2, \n \"tenant_create_kwargs\": {}\n }\n }, \n \"description\": \"Create a keystone tenant and several users belonging to it.\", \n \"contexts\": {}, \n \"runner\": {\n \"constant\": {\n \"concurrency\": 30, \n \"times\": 30\n }\n }, \n \"hooks\": [], \n \"sla\": {\n \"failure_rate\": {\n \"max\": 0\n }\n }\n }\n ]\n }\n ]\n}";
$scope.scenarios = [{"runner": "constant", "hooks": [], "pos": "0", "atomic": {"pie": [["keystone_v3.create_project", 1.4607575019200643], ["keystone_v3.create_users", 3.531839140256246], ["keystone_v3.delete_project", 1.657518982887268], ["keystone_v3.delete_user (x2)", 0.0]], "iter": [["keystone_v3.create_project", [[1, 1.3892159461975098], [2, 1.476902961730957], [3, 1.3312349319458008], [4, 1.4110372066497803], [5, 1.287830114364624], [6, 1.4189820289611816], [7, 1.3392560482025146], [8, 1.3409459590911865], [9, 1.344606876373291], [10, 1.3339810371398926], [11, 1.4349400997161865], [12, 1.3727810382843018], [13, 1.353722095489502], [14, 1.4668910503387451], [15, 1.3762400150299072], [16, 1.4457449913024902], [17, 1.3954761028289795], [18, 1.4769620895385742], [19, 1.5337789058685303], [20, 1.5085408687591553], [21, 1.4572200775146484], [22, 1.4725189208984375], [23, 1.5988469123840332], [24, 1.5622918605804443], [25, 1.5106909275054932], [26, 1.5967381000518799], [27, 1.5326039791107178], [28, 1.6830198764801025], [29, 1.5991480350494385], [30, 1.770576000213623]]], ["keystone_v3.create_users", [[1, 3.4837400913238525], [2, 3.44173002243042], [3, 3.4638280868530273], [4, 3.406230926513672], [5, 3.513098955154419], [6, 3.4493699073791504], [7, 3.4628231525421143], [8, 3.4632441997528076], [9, 3.557404041290283], [10, 3.4962799549102783], [11, 3.524553060531616], [12, 3.5383949279785156], [13, 3.5187900066375732], [14, 3.53658390045166], [15, 3.4340500831604004], [16, 3.5215229988098145], [17, 3.5155179500579834], [18, 3.5452139377593994], [19, 3.4959070682525635], [20, 3.6062021255493164], [21, 3.6314427852630615], [22, 3.566401958465576], [23, 3.584118127822876], [24, 3.609890937805176], [25, 3.565845012664795], [26, 3.622983932495117], [27, 3.597543954849243], [28, 3.5706841945648193], [29, 3.6373698711395264], [30, 3.5944080352783203]]], ["keystone_v3.delete_project", [[1, 0.38025712966918945], [2, 0.3978581428527832], [3, 0.42977190017700195], [4, 0.723862886428833], [5, 0.820842981338501], [6, 1.0913009643554688], [7, 0.7719078063964844], [8, 1.005605936050415], [9, 1.2643699645996094], [10, 1.2420470714569092], [11, 1.8572978973388672], [12, 1.5312800407409668], [13, 1.521308183670044], [14, 1.6915578842163086], [15, 1.2222881317138672], [16, 1.71150803565979], [17, 1.5639879703521729], [18, 1.884032964706421], [19, 1.9898860454559326], [20, 2.352152109146118], [21, 1.9502580165863037], [22, 2.155735969543457], [23, 2.5720951557159424], [24, 2.4840400218963623], [25, 2.145836114883423], [26, 2.674194097518921], [27, 2.222121000289917], [28, 2.832080125808716], [29, 2.7275049686431885], [30, 2.508579969406128]]], ["keystone_v3.delete_user (x2)", [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0], [9, 0], [10, 0], [11, 0], [12, 0], [13, 0], [14, 0], [15, 0], [16, 0], [17, 0], [18, 0], [19, 0], [20, 0], [21, 0], [22, 0], [23, 0], [24, 0], [25, 0], [26, 0], [27, 0], [28, 0], [29, 0], [30, 0]]]], "histogram": {"data": [[{"disabled": 0, "values": [{"y": 7, "x": 1.3685}, {"y": 8, "x": 1.449}, {"y": 7, "x": 1.5295}, {"y": 6, "x": 1.6099999999999999}, {"y": 1, "x": 1.6905}, {"y": 1, "x": 1.771}], "key": "keystone_v3.create_project", "view": "Square Root Choice"}, {"disabled": 1, "values": [{"y": 3, "x": 3.4445}, {"y": 4, "x": 3.483}, {"y": 6, "x": 3.5215}, {"y": 6, "x": 3.56}, {"y": 6, "x": 3.5985}, {"y": 4, "x": 3.637}], "key": "keystone_v3.create_users", "view": "Square Root Choice"}, {"disabled": 2, "values": [{"y": 5, "x": 0.7886666666666666}, {"y": 3, "x": 1.1973333333333334}, {"y": 6, "x": 1.6059999999999999}, {"y": 6, "x": 2.014666666666667}, {"y": 4, "x": 2.4233333333333333}, {"y": 5, "x": 2.832}], "key": "keystone_v3.delete_project", "view": "Square Root Choice"}, {"disabled": 3, "values": [{"y": 30, "x": 2.224}, {"y": 0, "x": 2.857}, {"y": 0, "x": 3.49}, {"y": 0, "x": 4.123}, {"y": 0, "x": 4.756}, {"y": 0, "x": 5.389}], "key": "keystone_v3.delete_user (x2)", "view": "Square Root Choice"}], [{"disabled": 0, "values": [{"y": 7, "x": 1.3685}, {"y": 8, "x": 1.449}, {"y": 7, "x": 1.5295}, {"y": 6, "x": 1.6099999999999999}, {"y": 1, "x": 1.6905}, {"y": 1, "x": 1.771}], "key": "keystone_v3.create_project", "view": "Sturges Formula"}, {"disabled": 1, "values": [{"y": 3, "x": 3.4445}, {"y": 4, "x": 3.483}, {"y": 6, "x": 3.5215}, {"y": 6, "x": 3.56}, {"y": 6, "x": 3.5985}, {"y": 4, "x": 3.637}], "key": "keystone_v3.create_users", "view": "Sturges Formula"}, {"disabled": 2, "values": [{"y": 5, "x": 0.7886666666666666}, {"y": 3, "x": 1.1973333333333334}, {"y": 6, "x": 1.6059999999999999}, {"y": 6, "x": 2.014666666666667}, {"y": 4, "x": 2.4233333333333333}, {"y": 5, "x": 2.832}], "key": "keystone_v3.delete_project", "view": "Sturges Formula"}, {"disabled": 3, "values": [{"y": 30, "x": 2.224}, {"y": 0, "x": 2.857}, {"y": 0, "x": 3.49}, {"y": 0, "x": 4.123}, {"y": 0, "x": 4.756}, {"y": 0, "x": 5.389}], "key": "keystone_v3.delete_user (x2)", "view": "Sturges Formula"}], [{"disabled": 0, "values": [{"y": 7, "x": 1.357}, {"y": 6, "x": 1.426}, {"y": 7, "x": 1.4949999999999999}, {"y": 5, "x": 1.564}, {"y": 3, "x": 1.633}, {"y": 1, "x": 1.702}, {"y": 1, "x": 1.771}], "key": "keystone_v3.create_project", "view": "Rice Rule"}, {"disabled": 1, "values": [{"y": 2, "x": 3.439}, {"y": 5, "x": 3.472}, {"y": 3, "x": 3.505}, {"y": 6, "x": 3.5380000000000003}, {"y": 6, "x": 3.571}, {"y": 3, "x": 3.604}, {"y": 4, "x": 3.637}], "key": "keystone_v3.create_users", "view": "Rice Rule"}, {"disabled": 2, "values": [{"y": 4, "x": 0.7302857142857142}, {"y": 3, "x": 1.0805714285714285}, {"y": 4, "x": 1.4308571428571426}, {"y": 5, "x": 1.7811428571428571}, {"y": 4, "x": 2.1314285714285712}, {"y": 4, "x": 2.4817142857142853}, {"y": 5, "x": 2.832}], "key": "keystone_v3.delete_project", "view": "Rice Rule"}, {"disabled": 3, "values": [{"y": 30, "x": 2.1335714285714285}, {"y": 0, "x": 2.676142857142857}, {"y": 0, "x": 3.2187142857142854}, {"y": 0, "x": 3.761285714285714}, {"y": 0, "x": 4.303857142857143}, {"y": 0, "x": 4.8464285714285715}, {"y": 0, "x": 5.389}], "key": "keystone_v3.delete_user (x2)", "view": "Rice Rule"}]], "views": [{"id": 0, "name": "Square Root Choice"}, {"id": 1, "name": "Sturges Formula"}, {"id": 2, "name": "Rice Rule"}]}}, "iterations": {"pie": [["success", 30], ["errors", 0]], "iter": [["duration", [[1, 10.431030988693237], [2, 10.430891990661621], [3, 10.465256929397583], [4, 10.838617086410522], [5, 11.198161840438843], [6, 11.766495943069458], [7, 10.821957111358643], [8, 11.58237099647522], [9, 12.186467170715332], [10, 12.03373908996582], [11, 12.633859157562256], [12, 12.2099609375], [13, 12.354514837265015], [14, 12.535539150238037], [15, 11.897559881210327], [16, 12.552489995956421], [17, 12.375818967819214], [18, 12.713470220565796], [19, 12.777254104614258], [20, 13.159801006317139], [21, 12.787435054779053], [22, 13.002640962600708], [23, 13.189954996109009], [24, 13.213238000869751], [25, 12.960143089294434], [26, 13.374254941940308], [27, 12.94136095046997], [28, 13.483658075332642], [29, 13.318512201309204], [30, 13.448041915893555]]], ["idle_duration", [[1, 0.0], [2, 0.0], [3, 0.0], [4, 0.0], [5, 0.0], [6, 0.0], [7, 0.0], [8, 0.0], [9, 0.0], [10, 0.0], [11, 0.0], [12, 0.0], [13, 0.0], [14, 0.0], [15, 0.0], [16, 0.0], [17, 0.0], [18, 0.0], [19, 0.0], [20, 0.0], [21, 0.0], [22, 0.0], [23, 0.0], [24, 0.0], [25, 0.0], [26, 0.0], [27, 0.0], [28, 0.0], [29, 0.0], [30, 0.0]]]], "histogram": {"data": [[{"disabled": null, "values": [{"y": 5, "x": 10.93968633810679}, {"y": 1, "x": 11.448480685551962}, {"y": 3, "x": 11.957275032997131}, {"y": 5, "x": 12.4660693804423}, {"y": 8, "x": 12.97486372788747}, {"y": 8, "x": 13.483658075332642}], "key": "task", "view": "Square Root Choice"}], [{"disabled": null, "values": [{"y": 5, "x": 10.93968633810679}, {"y": 1, "x": 11.448480685551962}, {"y": 3, "x": 11.957275032997131}, {"y": 5, "x": 12.4660693804423}, {"y": 8, "x": 12.97486372788747}, {"y": 8, "x": 13.483658075332642}], "key": "task", "view": "Sturges Formula"}], [{"disabled": null, "values": [{"y": 5, "x": 10.86700143132891}, {"y": 1, "x": 11.303110871996198}, {"y": 1, "x": 11.739220312663488}, {"y": 3, "x": 12.175329753330775}, {"y": 6, "x": 12.611439193998065}, {"y": 7, "x": 13.047548634665354}, {"y": 7, "x": 13.483658075332642}], "key": "task", "view": "Rice Rule"}]], "views": [{"id": 0, "name": "Square Root Choice"}, {"id": 1, "name": "Sturges Formula"}, {"id": 2, "name": "Rice Rule"}]}}, "table": {"styles": {"2": "oblique", "3": "oblique", "4": "oblique", "7": "rich", "8": "oblique", "9": "oblique"}, "rows": [["keystone_v3.create_project", 1.288, 1.451, 1.599, 1.645, 1.771, 1.461, "100.0%", 30], ["keystone_v3.create_users", 3.406, 3.531, 3.611, 3.628, 3.637, 3.532, "100.0%", 30], [" -> keystone_v3.create_user (x2)", 3.406, 3.531, 3.611, 3.628, 3.637, 3.532, "100.0%", 30], [" --> keystone_v3.list_roles (x2)", 0.613, 0.654, 0.72, 0.754, 0.92, 0.676, "100.0%", 30], [" --> keystone_v3.add_role (x2)", 0.638, 0.885, 0.997, 1.031, 1.086, 0.875, "100.0%", 30], ["keystone_v3.delete_project", 0.38, 1.702, 2.582, 2.704, 2.832, 1.658, "100.0%", 30], ["keystone_v3.delete_user (x2)", 1.591, 4.684, 5.284, 5.312, 5.389, 4.628, "100.0%", 30], ["total", 10.431, 12.544, 13.324, 13.415, 13.484, 12.289, "100.0%", 30], [" -> duration", 10.431, 12.544, 13.324, 13.415, 13.484, 12.289, "100.0%", 30], [" -> idle_duration", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, "100.0%", 30]], "cols": ["Action", "Min (sec)", "Median (sec)", "90%ile (sec)", "95%ile (sec)", "Max (sec)", "Avg (sec)", "Success", "Count"]}, "errors": [], "iterations_count": 30, "load_duration": 13.976090908050537, "complete_output": [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []], "config": "{\n \"version\": 2, \n \"title\": \"A cropped version of a bigger task.\", \n \"description\": \"Auto-generated task from a single workload (uuid=807231a0-511d-4339-8c09-6f2b44c41094)\", \n \"subtasks\": [\n {\n \"title\": \"MyKeystone.create_tenant_with_users\", \n \"description\": \"Create a keystone tenant and several users belonging to it.\", \n \"scenario\": {\n \"MyKeystone.create_tenant_with_users\": {\n \"users_per_tenant\": 2, \n \"tenant_create_kwargs\": {}\n }\n }, \n \"contexts\": {}, \n \"runner\": {\n \"constant\": {\n \"concurrency\": 30, \n \"times\": 30\n }\n }, \n \"hooks\": [], \n \"sla\": {\n \"failure_rate\": {\n \"max\": 0\n }\n }\n }\n ]\n}", "sla_success": true, "output_errors": [], "cls": "MyKeystone", "description": "Create a keystone tenant and several users belonging to it.", "met": "create_tenant_with_users", "has_output": false, "full_duration": 20.679630994796753, "load_profile": [["parallel iterations", [[0.0, 0], [0.1425561272621155, 2.3114318077075273], [0.285112254524231, 5.350543274001507], [0.4276683817863465, 12.514253087649804], [0.570224509048462, 28.741765002100735], [0.7127806363105775, 30], [0.855336763572693, 30], [0.9978928908348085, 30], [1.140449018096924, 30], [1.2830051453590394, 30], [1.425561272621155, 30], [1.5681173998832705, 30], [1.710673527145386, 30], [1.8532296544075015, 30], [1.995785781669617, 30], [2.1383419089317326, 30], [2.280898036193848, 30], [2.4234541634559634, 30], [2.566010290718079, 30], [2.7085664179801947, 30], [2.85112254524231, 30], [2.9936786725044255, 30], [3.136234799766541, 30], [3.2787909270286564, 30], [3.421347054290772, 30], [3.5639031815528877, 30], [3.706459308815003, 30], [3.8490154360771185, 30], [3.991571563339234, 30], [4.13412769060135, 30], [4.276683817863465, 30], [4.419239945125581, 30], [4.561796072387696, 30], [4.704352199649811, 30], [4.846908326911927, 30], [4.989464454174042, 30], [5.132020581436158, 30], [5.274576708698273, 30], [5.417132835960389, 30], [5.559688963222505, 30], [5.70224509048462, 30], [5.844801217746736, 30], [5.987357345008851, 30], [6.1299134722709665, 30], [6.272469599533082, 30], [6.415025726795197, 30], [6.557581854057313, 30], [6.700137981319428, 30], [6.842694108581544, 30], [6.98525023584366, 30], [7.127806363105775, 30], [7.270362490367891, 30], [7.412918617630006, 30], [7.555474744892122, 30], [7.698030872154237, 30], [7.840586999416352, 30], [7.983143126678468, 30], [8.125699253940583, 30], [8.2682553812027, 30], [8.410811508464814, 30], [8.55336763572693, 30], [8.695923762989045, 30], [8.838479890251161, 30], [8.981036017513276, 30], [9.123592144775392, 30], [9.266148272037508, 30], [9.408704399299623, 30], [9.55126052656174, 30], [9.693816653823854, 30], [9.83637278108597, 30], [9.978928908348085, 30], [10.1214850356102, 30], [10.264041162872315, 30], [10.406597290134432, 30], [10.549153417396546, 28.35013783032047], [10.691709544658663, 27.118159926907115], [10.834265671920779, 27], [10.976821799182893, 27], [11.11937792644501, 25.667711979912504], [11.261934053707124, 25], [11.40449018096924, 24.917055000306025], [11.547046308231355, 24], [11.689602435493471, 24], [11.832158562755586, 24], [11.974714690017702, 23.104150425841226], [12.117270817279817, 22.21813363345347], [12.259826944541933, 22], [12.40238307180405, 20.96625134741178], [12.544939199066164, 19.91682440501104], [12.68749532632828, 18.17813866786141], [12.830051453590395, 16.817159743229478], [12.972607580852511, 15.324608290160798], [13.115163708114626, 13.07751913647563], [13.257719835376742, 11.050713929277503], [13.400275962638856, 9.846910003613358], [13.542832089900973, 7.135876741583389], [13.685388217163087, 5.38151662816375], [13.827944344425203, 3.4880006706835105], [13.97050047168732, 1.7248980081798742], [14.113056598949434, 0.0392156862744895], [14.255612726211549, 0]]]], "name": "create_tenant_with_users", "created_at": "2019-06-12T18:34:16", "additive_output": [], "sla": [{"criterion": "failure_rate", "detail": "Failure rate criteria 0.00% <= 0.00% <= 0.00% - Passed", "success": true}]}];
$scope.location = {
/* #/path/hash/sub/div */
normalize: function(str) {
/* Remove unwanted characters from string */
if (typeof str !== "string") { return "" }
return str.replace(/[^\w\-\.]/g, "")
},
uri: function(obj) {
/* Getter/Setter */
if (! obj) {
var uri = {path: "", hash: "", sub: "", div: ""};
var arr = ["div", "sub", "hash", "path"];
angular.forEach($location.url().split("/"), function(value){
var v = $scope.location.normalize(value);
if (v) { var k = arr.pop(); if (k) { this[k] = v }}
}, uri);
return uri
}
var arr = [obj.path, obj.hash, obj.sub, obj.div], res = [];
for (var i in arr) { if (! arr[i]) { break }; res.push(arr[i]) }
return $location.url("/" + res.join("/"))
},
path: function(path, hash) {
/* Getter/Setter */
if (path === "") { return this.uri({}) }
path = this.normalize(path);
var uri = this.uri();
if (! path) { return uri.path }
uri.path = path;
var _hash = this.normalize(hash);
if (_hash || hash === "") { uri.hash = _hash }
return this.uri(uri)
},
hash: function(hash) {
/* Getter/Setter */
if (hash) { this.uri({path:this.uri().path, hash:hash}) }
return this.uri().hash
}
}
/* Dispatch */
$scope.route = function(uri) {
if (! $scope.scenarios_map) { return }
// Expand menu if there is only one menu group
if ($scope.nav.length === 1) {
$scope.nav_idx = $scope.nav[0].idx;
}
if (uri.path in $scope.scenarios_map) {
$scope.view = {is_scenario:true};
$scope.scenario = $scope.scenarios_map[uri.path];
$scope.nav_idx = $scope.nav_map[uri.path];
if ($scope.scenario.iterations.histogram.views.length) {
$scope.mainHistogram = $scope.scenario.iterations.histogram.views[0]
}
if ($scope.scenario.atomic.histogram.views.length) {
$scope.atomicHistogram = $scope.scenario.atomic.histogram.views[0]
}
$scope.outputIteration = 0;
$scope.showTab(uri);
} else {
$scope.scenario = null;
if (uri.path === "source") {
$scope.view = {is_source:true}
} else {
$scope.view = {is_main:true}
}
}
}
$scope.$on("$locationChangeSuccess", function (event, newUrl, oldUrl) {
$scope.route($scope.location.uri())
});
$scope.showNav = function(nav_idx) { $scope.nav_idx = nav_idx }
/* Tabs */
$scope.tabs = [
{
id: "overview",
name: "Overview",
visible: function(){ return !! $scope.scenario.iterations.pie.length }
},{
id: "details",
name: "Details",
visible: function(){ return !! $scope.scenario.atomic.pie.length }
},{
id: "output",
name: "Scenario Data",
visible: function(){ return $scope.scenario.has_output }
},{
id: "hooks",
name: "Hooks",
visible: function(){ return $scope.scenario.hooks.length }
},{
id: "failures",
name: "Failures",
visible: function(){ return !! $scope.scenario.errors.length }
},{
id: "task",
name: "Input task",
visible: function(){ return !! $scope.scenario.config }
}
];
$scope.tabs_map = {};
angular.forEach($scope.tabs,
function(tab){ this[tab.id] = tab }, $scope.tabs_map);
$scope.showTab = function(uri) {
$scope.tab = uri.hash in $scope.tabs_map ? uri.hash : "overview";
if (uri.hash === "output") {
if (typeof $scope.scenario.output === "undefined") {
var has_additive = !! $scope.scenario.additive_output.length;
var has_complete = !! ($scope.scenario.complete_output.length
&& $scope.scenario.complete_output[0].length);
$scope.scenario.output = {
has_additive: has_additive,
has_complete: has_complete,
length: has_additive + has_complete,
active: has_additive ? "additive" : (has_complete ? "complete" : "")
}
}
if (uri.sub && $scope.scenario.output["has_" + uri.sub]) {
$scope.scenario.output.active = uri.sub
}
}
else if (uri.hash === "hooks") {
if ($scope.scenario.hooks.length) {
var hook_idx = parseInt(uri.sub);
if (isNaN(hook_idx) || ($scope.scenario.hooks.length - hook_idx) <= 0) {
hook_idx = 0
}
if ($scope.scenario.hook_idx === hook_idx) {
return
}
$scope.scenario.hooks.cur = $scope.scenario.hooks[hook_idx];
$scope.scenario.hook_idx = hook_idx;
if (typeof $scope.scenario.hooks.cur.active === "undefined") {
if ($scope.scenario.hooks.cur.additive.length) {
$scope.scenario.hooks.cur.active = "additive"
}
if ($scope.scenario.hooks.cur.complete.length) {
if (typeof $scope.scenario.hooks.cur.active === "undefined") {
$scope.scenario.hooks.cur.active = "complete"
}
$scope.set_hook_run()
}
}
}
}
}
for (var i in $scope.tabs) {
if ($scope.tabs[i].id === $scope.location.hash()) {
$scope.tab = $scope.tabs[i].id
}
$scope.tabs[i].isVisible = function() {
if ($scope.scenario) {
if (this.visible()) { return true }
/* If tab should be hidden but is selected - show another one */
if (this.id === $scope.location.hash()) {
for (var i in $scope.tabs) {
var tab = $scope.tabs[i];
if (tab.id != this.id && tab.visible()) {
$scope.tab = tab.id;
return false
}
}
}
}
return false
}
}
$scope.set_hook_run = function(idx) {
if (typeof idx !== "undefined") {
$scope.scenario.hooks.cur.run_idx = idx
}
else if (typeof $scope.scenario.hooks.cur.run_idx === "undefined") {
$scope.scenario.hooks.cur.run_idx = 0
}
idx = $scope.scenario.hooks.cur.run_idx;
if (($scope.scenario.hooks.cur.complete.length - idx) > 0) {
$scope.scenario.hooks.cur.run = $scope.scenario.hooks.cur.complete[idx]
}
}
$scope.complete_hooks_as_dropdown = function() {
return $scope.scenario.hooks.cur.complete.length > 10
}
/* Other helpers */
$scope.showError = function(message) {
return (function (e) {
e.style.display = "block";
e.textContent = message
})(document.getElementById("page-error"))
}
$scope.compact_atomics = function() {
return ($scope.scenario && $scope.scenario.atomic.iter.length < 9)
}
/* Initialization */
angular.element(document).ready(function(){
if (! $scope.scenarios.length) {
return $scope.showError("No data...")
}
/* Compose data mapping */
$scope.nav = [];
$scope.nav_map = {};
$scope.scenarios_map = {};
var met = [], itr = 0, cls_idx = 0;
var prev_cls, prev_met;
for (var idx in $scope.scenarios) {
var sc = $scope.scenarios[idx];
if (! prev_cls) {
prev_cls = sc.cls
}
else if (prev_cls !== sc.cls) {
$scope.nav.push({cls:prev_cls, met:met, idx:cls_idx});
prev_cls = sc.cls;
met = [];
itr = 1;
cls_idx += 1
}
if (prev_met !== sc.met) { itr = 1 };
sc.ref = $scope.location.normalize(sc.cls+"."+sc.met+(itr > 1 ? "-"+itr : ""));
$scope.scenarios_map[sc.ref] = sc;
$scope.nav_map[sc.ref] = cls_idx;
met.push({name:sc.name, itr:itr, idx:idx, ref:sc.ref});
prev_met = sc.met;
itr += 1;
}
if (met.length) {
$scope.nav.push({cls:prev_cls, met:met, idx:cls_idx})
}
/* Start */
var uri = $scope.location.uri();
uri.path = $scope.location.path();
$scope.route(uri);
$scope.$digest()
})
};
if (typeof angular === "object") {
angular.module("App", [])
.controller("Controller", ["$scope", "$location", controllerFunction])
.directive("widget", widgetDirective)
}
</script>
<style>
body { margin:0; padding:0 0 50px; font-size:14px; font-family:Helvetica,Arial,sans-serif }
a, a:active, a:focus, a:visited { text-decoration:none; outline:none }
p { margin:0; padding:5px 0 }
p.thesis { padding:10px 0 }
h1 { color:#666; margin:0 0 20px; font-size:30px; font-weight:normal }
h2, .h2 { color:#666; margin:24px 0 6px; font-size:25px; font-weight:normal }
h3, .h3 { color:#777; margin:12px 0 4px; font-size:18px; font-weight:normal }
table { border-collapse:collapse; border-spacing:0; width:100%; font-size:12px; margin:0 0 10px }
table th { text-align:left; padding:8px; color:#000; border:2px solid #ddd; border-width:0 0 2px 0 }
table th.sortable { cursor:pointer }
table td { text-align:left; border-top:1px solid #ddd; padding:8px; color:#333 }
table.compact td { padding:4px 8px }
table.striped tr:nth-child(odd) td { background:#f9f9f9 }
table.linked tbody tr:hover { background:#f9f9f9; cursor:pointer }
.pointer { cursor:pointer }
.rich, .rich td { font-weight:bold }
.oblique { font-style:italic }
.code { padding:10px; font-size:13px; color:#333; background:#f6f6f6; border:1px solid #e5e5e5; border-radius:4px }
.header { text-align:left; background:#333; font-size:18px; padding:13px 0; margin-bottom:20px; color:#fff; background-image:linear-gradient(to bottom, #444 0px, #222 100%) }
.header a, .header a:visited, .header a:focus { color:#999 }
.notify-error { padding:5px 10px; background:#fee; color:red }
.status-skip, .status-skip td { color:grey }
.status-pass, .status-pass td { color:green }
.status-fail, .status-fail td { color:red }
.capitalize { text-transform:capitalize }
.aside { margin:0 20px 0 0; display:block; width:255px; float:left }
.aside > div { margin-bottom: 15px }
.aside > div div:first-child { border-top-left-radius:4px; border-top-right-radius:4px }
.aside > div div:last-child { border-bottom-left-radius:4px; border-bottom-right-radius:4px }
.navcls { color:#678; background:#eee; border:1px solid #ddd; margin-bottom:-1px; display:block; padding:8px 9px; font-weight:bold; text-align:left; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; cursor:pointer }
.navcls.expanded { color:#469 }
.navcls.active { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff }
.navmet { color:#555; background:#fff; border:1px solid #ddd; font-size:12px; display:block; margin-bottom:-1px; padding:8px 10px; text-align:left; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; cursor:pointer }
.navmet:hover { background:#f8f8f8 }
.navmet.active, .navmet.active:hover { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff }
.buttn { color:#555; background:#fff; border:1px solid #ddd; border-radius:5px; font-size:12px; margin-bottom:-1px; padding:5px 7px; text-align:left; text-overflow:ellipsis; white-space:nowrap; overflow:hidden; cursor:pointer }
.buttn:hover { background:#f8f8f8 }
.buttn.active, .bttn.active:hover { background:#428bca; background-image:linear-gradient(to bottom, #428bca 0px, #3278b3 100%); border-color:#3278b3; color:#fff; cursor:default }
.tabs { list-style:outside none none; margin:0 0 5px; padding:0; border-bottom:1px solid #ddd }
.tabs:after { clear:both }
.tabs li { float:left; margin-bottom:-1px; display:block; position:relative }
.tabs li div { border:1px solid transparent; border-radius:4px 4px 0 0; line-height:20px; margin-right:2px; padding:10px 15px; color:#428bca }
.tabs li div:hover { border-color:#eee #eee #ddd; background:#eee; cursor:pointer; }
.tabs li.active div { background:#fff; border-color:#ddd #ddd transparent; border-style:solid; border-width:1px; color:#555; cursor:default }
.failure-mesg { color:#900 }
.failure-trace { color:#333; white-space:pre; overflow:auto }
.link { color:#428BCA; padding:5px 15px 5px 5px; text-decoration:underline; cursor:pointer }
.link.active { color:#333; text-decoration:none; cursor:default }
.chart { padding:0; margin:0; width:890px }
.chart svg { height:300px; padding:0; margin:0; overflow:visible; float:right }
.chart.lower svg { height:180px }
.chart-label-y { font-size:12px; position:relative; top:5px; padding:0; margin:0 }
.expandable { cursor:pointer }
.clearfix { clear:both }
.sortable > .arrow { display:inline-block; width:12px; height:inherit; color:#c90 }
.content-main { margin:0 5px; display:block; float:left }
.content-wrap { margin:0 auto; padding:0 5px; }
@media only screen and (min-width: 320px) { .content-wrap { width:900px } .content-main { width:600px } }
@media only screen and (min-width: 900px) { .content-wrap { width:880px } .content-main { width:590px } }
@media only screen and (min-width: 1000px) { .content-wrap { width:980px } .content-main { width:690px } }
@media only screen and (min-width: 1100px) { .content-wrap { width:1080px } .content-main { width:790px } }
@media only screen and (min-width: 1200px) { .content-wrap { width:1180px } .content-main { width:890px } }
</style>
</head>
<body ng-controller="Controller">
<div class="header" id="page-header">
<div class="content-wrap">
<a href="https://github.com/openstack/rally">Rally</a>
<span>task results</span>
</div>
</div>
<div class="content-wrap" id="page-content">
<p id="page-error" class="notify-error" style="display:none"></p>
<div id="content-nav" class="aside" ng-show="scenarios.length" ng-cloack>
<div>
<div class="navcls"
ng-class="{active:view.is_main}"
ng-click="location.path('')">Task overview</div>
<div class="navcls"
ng-class="{active:view.is_source}"
ng-click="location.path('source', '')">Input file</div>
</div>
<div>
<div class="navcls" title="{{n.cls}}"
ng-repeat-start="n in nav track by $index"
ng-click="showNav(n.idx)"
ng-class="{expanded:n.idx==nav_idx}">
<span ng-hide="n.idx==nav_idx">►</span>
<span ng-show="n.idx==nav_idx">▼</span>
{{n.cls}}</div>
<div class="navmet" title="{{m.name}}"
ng-show="n.idx==nav_idx"
ng-class="{active:m.ref==scenario.ref}"
ng-click="location.path(m.ref)"
ng-repeat="m in n.met track by $index"
ng-repeat-end>{{m.name}}</div>
</div>
</div>
<div id="content-main" class="content-main" ng-show="scenarios.length" ng-cloak>
<div ng-show="view.is_main">
<h1>Task overview</h1>
<table class="linked compact"
ng-init="ov_srt='ref'; ov_dir=false">
<thead>
<tr>
<th class="sortable"
title="Scenario name, with optional suffix of call number"
ng-click="ov_srt='ref'; ov_dir=!ov_dir">
Scenario
<span class="arrow">
<b ng-show="ov_srt=='ref' && !ov_dir">▴</b>
<b ng-show="ov_srt=='ref' && ov_dir">▾</b>
</span>
<th class="sortable"
title="How long the scenario run, without context duration"
ng-click="ov_srt='load_duration'; ov_dir=!ov_dir">
Load duration (s)
<span class="arrow">
<b ng-show="ov_srt=='load_duration' && !ov_dir">▴</b>
<b ng-show="ov_srt=='load_duration' && ov_dir">▾</b>
</span>
<th class="sortable"
title="Scenario duration plus context duration"
ng-click="ov_srt='full_duration'; ov_dir=!ov_dir">
Full duration (s)
<span class="arrow">
<b ng-show="ov_srt=='full_duration' && !ov_dir">▴</b>
<b ng-show="ov_srt=='full_duration' && ov_dir">▾</b>
</span>
<th class="sortable" title="Number of iterations"
ng-click="ov_srt='iterations_count'; ov_dir=!ov_dir">
Iterations
<span class="arrow">
<b ng-show="ov_srt=='iterations_count' && !ov_dir">▴</b>
<b ng-show="ov_srt=='iterations_count' && ov_dir">▾</b>
</span>
<th class="sortable" title="Scenario runner type"
ng-click="ov_srt='runner'; ov_dir=!ov_dir">
Runner
<span class="arrow">
<b ng-show="ov_srt=='runner' && !ov_dir">▴</b>
<b ng-show="ov_srt=='runner' && ov_dir">▾</b>
</span>
<th class="sortable" title="Number of errors occurred"
ng-click="ov_srt='errors.length'; ov_dir=!ov_dir">
Errors
<span class="arrow">
<b ng-show="ov_srt=='errors.length' && !ov_dir">▴</b>
<b ng-show="ov_srt=='errors.length' && ov_dir">▾</b>
</span>
<th class="sortable" title="Number of hooks"
ng-click="ov_srt='hooks.length'; ov_dir=!ov_dir">
Hooks
<span class="arrow">
<b ng-show="ov_srt=='hooks.length' && !ov_dir">▴</b>
<b ng-show="ov_srt=='hooks.length' && ov_dir">▾</b>
</span>
<th class="sortable" title="Whether SLA check is successful"
ng-click="ov_srt='sla_success'; ov_dir=!ov_dir">
Success (SLA)
<span class="arrow">
<b ng-show="ov_srt=='sla_success' && !ov_dir">▴</b>
<b ng-show="ov_srt=='sla_success' && ov_dir">▾</b>
</span>
<tr>
</thead>
<tbody>
<tr ng-repeat="sc in scenarios | orderBy:ov_srt:ov_dir"
ng-click="location.path(sc.ref)">
<td>{{sc.ref}}
<td>{{sc.load_duration | number:3}}
<td>{{sc.full_duration | number:3}}
<td>{{sc.iterations_count}}
<td>{{sc.runner}}
<td>{{sc.errors.length}}
<td>{{sc.hooks.length}}
<td>
<span ng-show="sc.sla_success" class="status-pass">✔</span>
<span ng-hide="sc.sla_success" class="status-fail">✖</span>
<tr>
</tbody>
</table>
</div>
<div ng-show="view.is_source">
<h1>Input file</h1>
<pre class="code">{{source}}</pre>
</div>
<div ng-show="view.is_scenario">
<h1>{{scenario.cls}}.<wbr>{{scenario.name}} ({{scenario.full_duration | number:3}}s)</h1>
<div ng-show="scenario.description" style="margin-bottom: 20px;">
<i>{{scenario.description}}</i>
</div>
<ul class="tabs">
<li ng-repeat="t in tabs"
ng-show="t.isVisible()"
ng-class="{active:t.id == tab}"
ng-click="location.hash(t.id)">
<div>{{t.name}}</div>
</li>
<div class="clearfix"></div>
</ul>
<div ng-include="tab"></div>
<script type="text/ng-template" id="overview">
<p class="thesis">
Load duration: <b>{{scenario.load_duration | number:3}} s</b>
Full duration: <b>{{scenario.full_duration | number:3}} s</b>
Iterations: <b>{{scenario.iterations_count}}</b>
Failures: <b>{{scenario.errors.length}}</b>
Started at: <b>{{scenario.created_at}}</b>
</p>
<div ng-show="scenario.sla.length">
<h2>Service-level agreement</h2>
<table class="striped">
<thead>
<tr>
<th>Criterion
<th>Detail
<th>Success
<tr>
</thead>
<tbody>
<tr class="rich"
ng-repeat="row in scenario.sla track by $index"
ng-class="{'status-fail':!row.success, 'status-pass':row.success}">
<td>{{row.criterion}}
<td>{{row.detail}}
<td class="capitalize">{{row.success}}
<tr>
</tbody>
</table>
</div>
<div widget="Table"
data="scenario.table"
lastrow-class="rich"
title="Total durations">
</div>
<div widget="StackedArea"
data="scenario.iterations.iter"
name-x="Iteration sequence number"
controls="true"
guide="true">
</div>
<div widget="StackedArea"
data="scenario.load_profile"
title="Load Profile"
title-class="h3"
name-x="Timeline (seconds)"
format-y="d"
format-x=",.2f"
class="lower">
</div>
<div widget="Pie"
data="scenario.iterations.pie"
title="Distribution"
title-class="h3"
style="float:left; width:40%; margin-top:15px">
</div>
<div widget="Histogram"
ng-if="scenario.iterations.histogram.data.length"
data="scenario.iterations.histogram.data[mainHistogram.id]"
style="float:left; width:59%; margin-top:15px; position:relative; top:40px">
</div>
<select ng-model="mainHistogram"
ng-show="scenario.iterations.histogram.data.length"
ng-options="i.name for i in scenario.iterations.histogram.views track by i.id"
style="float:right; margin:45px 35px 0">
</select>
<div class="clearfix"></div>
</script>
<script type="text/ng-template" id="details">
<div widget="StackedArea"
data="scenario.atomic.iter"
title="Atomic Action Durations"
name-x="Iteration sequence number"
controls="true"
guide="true">
</div>
<div widget="Pie"
data="scenario.atomic.pie"
title="Distribution"
title-class="h3"
style="float:left; margin-top:15px"
ng-style="compact_atomics() ? {width:'40%'} : {}">
</div>
<div widget="Histogram" data="scenario.atomic.histogram.data[atomicHistogram.id]"
ng-if="scenario.atomic.histogram.data.length"
style="float:left; position:relative; top:40px"
ng-style="compact_atomics() ? {width:'59%', 'margin-top':'15px'} : {}">
</div>
<select ng-show="scenario.atomic.histogram.data.length"
ng-model="atomicHistogram"
ng-options="i.name for i in scenario.atomic.histogram.views track by i.id"
style="float:right; margin:45px 35px 0">
</select>
<div class="clearfix"></div>
</script>
<script type="text/ng-template" id="output">
<div style="padding:10px 0 0">
<span class="link"
ng-click="location.hash('output/additive')"
ng-class="{active:scenario.output.active === 'additive'}"
ng-if="scenario.output.has_additive">Aggregated</span>
<span class="link"
ng-click="location.hash('output/complete')"
ng-class="{active:scenario.output.active === 'complete'}"
ng-if="scenario.output.has_complete">Per iteration</span>
</div>
<div ng-repeat="chart in scenario.additive_output"
ng-if="scenario.output.active === 'additive'">
<div widget="{{chart.widget}}"
title="{{chart.title}}"
description="{{chart.description}}"
name-x="{{chart.axis_label}}"
name-y="{{chart.label}}"
data="chart.data">
</div>
</div>
<div ng-if="scenario.output.active === 'complete'" style="padding:10px 0 0">
<select ng-model="outputIteration">
<option ng-repeat="i in scenario.complete_output track by $index"
value="{{$index}}">
Iteration {{$index}}
</select>
<div ng-repeat="chart in scenario.complete_output[outputIteration]">
<div widget="{{chart.widget}}"
title="{{chart.title}}"
description="{{chart.description}}"
name-x="{{chart.axis_label}}"
name-y="{{chart.label}}"
data="chart.data">
</div>
</div>
</div>
</script>
<script type="text/ng-template" id="hooks">
<div style="padding:15px 0">
<span ng-repeat="h in scenario.hooks track by $index"
class="buttn"
title="{{h.desc}}"
style="margin:0 10px 0 0"
ng-click="location.hash('hooks/'+$index)"
ng-class="{active:scenario.hook_idx===$index}">
{{h.name}}
</span>
</div>
<table class="striped" style="margin:5px 0 25px">
<thead>
<tr>
<th>Plugin
<th>Description
</thead>
<tbody>
<tr>
<td>{{scenario.hooks.cur.name}}
<td>{{scenario.hooks.cur.desc}}
</tbody>
</table>
<div>
<span class="link"
ng-click="scenario.hooks.cur.active = 'additive'"
ng-class="{active:scenario.hooks.cur.active === 'additive'}"
ng-if="scenario.hooks.cur.additive.length">Aggregated</span>
<span class="link"
ng-click="scenario.hooks.cur.active = 'complete'"
ng-class="{active:scenario.hooks.cur.active === 'complete'}"
ng-if="scenario.hooks.cur.complete.length">Per hook run</span>
</div>
<div ng-repeat="chart in scenario.hooks.cur.additive"
ng-if="scenario.hooks.cur.active === 'additive'">
<div widget="{{chart.widget}}"
title="{{chart.title}}"
description="{{chart.description}}"
name-x="{{chart.axis_label}}"
name-y="{{chart.label}}"
data="chart.data">
</div>
</div>
<div ng-if="scenario.hooks.cur.active === 'complete'" style="padding:10px 0 0">
<select ng-if="complete_hooks_as_dropdown()"
ng-model="scenario.hooks.cur.run_idx"
ng-change="set_hook_run()">
<option ng-repeat="h in scenario.hooks.cur.complete track by $index"
ng-selected="scenario.hooks.cur.run_idx == $index"
value="{{$index}}">
{{h.triggered_by}}
</select>
<div ng-if="! complete_hooks_as_dropdown()"
style="border:#ccc solid; border-width:1px 0 0; padding:5px 0 0">
<span ng-repeat="h in scenario.hooks.cur.complete track by $index"
class="link"
ng-class="{active:scenario.hooks.cur.run_idx == $index}"
ng-click="set_hook_run($index)">
{{h.triggered_by}}
</span>
</div>
<table class="striped" style="margin:15px 0 15px">
<thead>
<tr>
<th>Status
<th>Triggered by
<th>Started at
<th>Finished at
</thead>
<tbody>
<tr>
<td ng-style="scenario.hooks.cur.run.status === 'success' ? {color:'green'} : {color:'red'}">
<b>{{scenario.hooks.cur.run.status}}</b>
<td>{{scenario.hooks.cur.run.triggered_by}}
<td>{{scenario.hooks.cur.run.started_at}}
<td>{{scenario.hooks.cur.run.finished_at}}
</tbody>
</table>
<div ng-repeat="chart in scenario.hooks.cur.run.charts">
<div widget="{{chart.widget}}"
title="{{chart.title}}"
description="{{chart.description}}"
name-x="{{chart.axis_label}}"
name-y="{{chart.label}}"
data="chart.data">
</div>
</div>
</div>
</script>
<script type="text/ng-template" id="failures">
<h2>Task failures (<ng-pluralize
count="scenario.errors.length"
when="{'1': '1 iteration', 'other': '{} iterations'}"></ng-pluralize> failed)
</h2>
<table class="striped">
<thead>
<tr>
<th>
<th>Timestamp
<th>Iteration
<th>Exception type
<th>Exception message
</tr>
</thead>
<tbody>
<tr class="expandable"
ng-repeat-start="i in scenario.errors track by $index"
ng-click="i.expanded = ! i.expanded">
<td>
<span ng-hide="i.expanded">►</span>
<span ng-show="i.expanded">▼</span>
<td>{{i.timestamp}}
<td>{{i.iteration}}
<td>{{i.type}}
<td class="failure-mesg">{{i.message}}
</tr>
<tr ng-show="i.expanded" ng-repeat-end>
<td colspan="4" class="failure-trace">{{i.traceback}}
</tr>
</tbody>
</table>
</script>
<script type="text/ng-template" id="task">
<h2>The Workload Configuration</h2>
<pre class="code">{{scenario.config}}</pre>
</script>
</div>
</div>
<div class="clearfix"></div>
</div>
<script type="text/javascript">
if (! window.angular) {(function(f){
f(document.getElementById("content-nav"), "none");
f(document.getElementById("content-main"), "none");
f(document.getElementById("page-error"), "block").textContent = "Failed to load AngularJS framework"
})(function(e, s){e.style.display = s; return e})}
</script>
</body>
</html>