aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrice Buriez <patrice.buriez@intel.com>2018-11-30 12:16:43 +0100
committerPatrice Buriez <patrice.buriez@intel.com>2018-12-19 09:13:11 +0100
commit02dbbd651c64623eb4f6d808ede0b938ca8787ed (patch)
tree7b5873188b6ec4a79f4984fb10334557e97e5a8d
parentb122686cb06e89420e9d8141df535f6c43de29ab (diff)
Use Chart.js for graphs in HTML reports
This JavaScript library is available under MIT license. Also adjusted version for jQuery and jsTree, and added fallback font-family names. JIRA: YARDSTICK-1367 Topic: report/html_table (6 of 12) Change-Id: Ibe8b7e3d1f1365d2cbc019bfc22762aaa365a4e1 Signed-off-by: Patrice Buriez <patrice.buriez@intel.com>
-rw-r--r--docs/testing/user/userguide/10-yardstick-user-interface.rst4
-rw-r--r--yardstick/benchmark/core/report.py11
-rw-r--r--yardstick/common/nsb_report.css2
-rw-r--r--yardstick/common/nsb_report.html.j2153
-rw-r--r--yardstick/common/report.html.j2133
5 files changed, 196 insertions, 107 deletions
diff --git a/docs/testing/user/userguide/10-yardstick-user-interface.rst b/docs/testing/user/userguide/10-yardstick-user-interface.rst
index 76890b29a..5f9414974 100644
--- a/docs/testing/user/userguide/10-yardstick-user-interface.rst
+++ b/docs/testing/user/userguide/10-yardstick-user-interface.rst
@@ -27,8 +27,8 @@ Description
The graph is framed with Timestamp on x-axis and output values
(differ from testcase to testcase) on y-axis with the help of
-`Highcharts`_.
+`Chart.js`_.
.. _InfluxDB: https://www.influxdata.com/time-series-platform/influxdb/
.. _Jinja2: http://jinja.pocoo.org/docs/2.10/
-.. _Highcharts: https://www.highcharts.com/products/highcharts/
+.. _Chart.js: https://www.chartjs.org/
diff --git a/yardstick/benchmark/core/report.py b/yardstick/benchmark/core/report.py
index a484a49f3..530fbf165 100644
--- a/yardstick/benchmark/core/report.py
+++ b/yardstick/benchmark/core/report.py
@@ -135,7 +135,7 @@ class Report(object):
self.db_task = self._get_tasks()
field_keys = []
- temp_series = []
+ datasets = []
table_vals = {}
field_keys = [encodeutils.to_utf8(field['fieldKey'])
@@ -143,7 +143,6 @@ class Report(object):
for key in field_keys:
self.Timestamp = []
- series = {}
values = []
for task in self.db_task:
task_time = encodeutils.to_utf8(task['time'])
@@ -155,16 +154,14 @@ class Report(object):
task_time = head + "." + tail[:6]
self.Timestamp.append(task_time)
if task[key] is None:
- values.append('')
+ values.append(None)
elif isinstance(task[key], (int, float)) is True:
values.append(task[key])
else:
values.append(ast.literal_eval(task[key]))
+ datasets.append({'label': key, 'data': values})
table_vals['Timestamp'] = self.Timestamp
table_vals[key] = values
- series['name'] = key
- series['data'] = values
- temp_series.append(series)
template_dir = consts.YARDSTICK_ROOT_PATH + "yardstick/common"
template_environment = jinja2.Environment(
@@ -173,7 +170,7 @@ class Report(object):
trim_blocks=False)
context = {
- "series": temp_series,
+ "datasets": datasets,
"Timestamps": self.Timestamp,
"task_id": self.task_id,
"table": table_vals,
diff --git a/yardstick/common/nsb_report.css b/yardstick/common/nsb_report.css
index 0c47791e2..2beb91c53 100644
--- a/yardstick/common/nsb_report.css
+++ b/yardstick/common/nsb_report.css
@@ -19,7 +19,7 @@ table {
}
header {
- font-family: Frutiger;
+ font-family: Frutiger, "Helvetica Neue", Helvetica, Arial, sans-serif;
clear: left;
text-align: center;
}
diff --git a/yardstick/common/nsb_report.html.j2 b/yardstick/common/nsb_report.html.j2
index f1b4ae1c2..0b4719b09 100644
--- a/yardstick/common/nsb_report.html.j2
+++ b/yardstick/common/nsb_report.html.j2
@@ -15,12 +15,12 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.5/themes/default/style.min.css">
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/themes/default/style.min.css">
<link rel="stylesheet" href="{{template_dir}}/nsb_report.css">
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
- <script src="https://code.highcharts.com/highcharts.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
</head>
<body>
@@ -31,12 +31,12 @@
<h4>Report of {{task_id}} Generated</h4>
</header>
</div>
- <div class="row" style="height:500px">
+ <div class="row">
<div class="col-md-2 control-pane">
<div id="data_selector"></div>
</div>
<div class="col-md-10 data-pane">
- <div id="graph"></div>
+ <canvas id="cnvGraph" style="width: 100%; height: 500px"></canvas>
</div>
</div>
<div class="row">
@@ -47,7 +47,8 @@
</div>
<script>
- var arr, tab, tr, td, tbody, keys, key, curr_data;
+ var None = null;
+ var arr, tab, tr, td, tbody, keys, key, curr_data, val;
arr = {{table|safe}};
tab = document.getElementsByTagName('table')[0];
@@ -63,8 +64,9 @@
curr_data = arr[key];
// add each piece of data as its own column
for (var j = 0; j < curr_data.length; j++) {
+ val = curr_data[j];
td = document.createElement('td');
- td.append(curr_data[j]);
+ td.append(val === None ? '' : val);
tr.append(td);
}
tbody.append(tr);
@@ -88,71 +90,98 @@
},
});
- $('#data_selector').on('check_node.jstree uncheck_node.jstree', function(e, data) {
- var selected_leaves = [];
- for (var i = 0; i < data.selected.length; i++) {
- var node = data.instance.get_node(data.selected[i]);
- if (node.children.length == 0) {
- var point = {name: node.id, data: arr[node.id]};
- selected_leaves.push(point);
- }
- }
-
- $('#graph').highcharts({
- title: {
- text: 'Yardstick Graphs',
- x: -20, //center
- },
- chart: {
- marginLeft: 400,
- zoomType: 'x',
- type: 'spline',
- },
- xAxis: {
- crosshair: {
- width: 1,
- color: 'black',
- },
- title: {
- text: 'Timestamp',
+ var objGraph = new Chart($('#cnvGraph'), {
+ type: 'line',
+ data: {
+ labels: {{Timestamps|safe}},
+ datasets: [],
+ },
+ options: {
+ elements: {
+ line: {
+ borderWidth: 2,
+ fill: false,
+ tension: 0,
},
- categories: {{Timestamps|safe}},
},
- yAxis: {
- crosshair: {
- width: 1,
- color: 'black',
- },
- plotLines: [{
- value: 0,
- width: 1,
- color: '#808080',
+ scales: {
+ xAxes: [{
+ type: 'category',
+ }],
+ yAxes: [{
+ type: 'linear',
}],
},
- plotOptions: {
- series: {
- showCheckbox: false,
- visible: false,
- },
+ tooltips: {
+ mode: 'point',
+ intersect: true,
},
- tooltip: {
- valueSuffix: '',
+ hover: {
+ mode: 'index',
+ intersect: false,
+ animationDuration: 0,
},
legend: {
- enabled: true,
+ position: 'bottom',
+ labels: {
+ usePointStyle: true,
+ },
},
- series: selected_leaves,
- });
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ responsiveAnimationDuration: 0,
+ maintainAspectRatio: false,
+ },
+ });
- var chart = $('#graph').highcharts();
- for (var i = 0; i < chart.series.length; i++) {
- var series = chart.series[i];
- if (series.visible) {
- series.hide();
- } else {
- series.show();
+ $('#data_selector').on('check_node.jstree uncheck_node.jstree', function(e, data) {
+ var selected_datasets = [];
+ for (var i = 0; i < data.selected.length; i++) {
+ var node = data.instance.get_node(data.selected[i]);
+ if (node.children.length == 0) {
+ var dataset = {
+ label: node.id,
+ data: arr[node.id],
+ };
+ selected_datasets.push(dataset);
}
}
+
+ var colors = [
+ '#FF0000', // Red
+ '#228B22', // ForestGreen
+ '#FF8C00', // DarkOrange
+ '#00008B', // DarkBlue
+ '#FF00FF', // Fuchsia
+ '#9ACD32', // YellowGreen
+ '#FFD700', // Gold
+ '#4169E1', // RoyalBlue
+ '#A0522D', // Sienna
+ '#20B2AA', // LightSeaGreen
+ '#8A2BE2', // BlueViolet
+ ];
+
+ var points = [
+ {s: 'circle', r: 3},
+ {s: 'rect', r: 4},
+ {s: 'triangle', r: 4},
+ {s: 'star', r: 4},
+ {s: 'rectRot', r: 5},
+ ];
+
+ selected_datasets.forEach(function(d, i) {
+ var color = colors[i % colors.length];
+ var point = points[i % points.length];
+ d.borderColor = color;
+ d.backgroundColor = color;
+ d.pointStyle = point.s;
+ d.pointRadius = point.r;
+ d.pointHoverRadius = point.r + 1;
+ });
+ objGraph.data.datasets = selected_datasets;
+ objGraph.update();
});
});
</script>
diff --git a/yardstick/common/report.html.j2 b/yardstick/common/report.html.j2
index ab76510ca..1dc7b1db1 100644
--- a/yardstick/common/report.html.j2
+++ b/yardstick/common/report.html.j2
@@ -15,9 +15,9 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
- <script src="https://code.highcharts.com/highcharts.js"></script>
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.min.js"></script>
<style>
table {
@@ -26,7 +26,7 @@
display: block;
}
header {
- font-family: Frutiger;
+ font-family: Frutiger, "Helvetica Neue", Helvetica, Arial, sans-serif;
clear: left;
text-align: center;
}
@@ -47,13 +47,14 @@
</div>
</div>
<div class="col-md-8">
- <div id="container"></div>
+ <canvas id="cnvGraph" style="width: 100%; height: 500px"></canvas>
</div>
</div>
</div>
<script>
- var arr, tab, th, tr, td, tn, row, col, thead, tbody;
+ var None = null;
+ var arr, tab, th, tr, td, tn, row, col, thead, tbody, val;
arr = {{table|safe}};
tab = document.getElementsByTagName('table')[0];
@@ -64,16 +65,17 @@
tn = document.createTextNode(Object.keys(arr).sort()[col]);
th.appendChild(tn);
tr.appendChild(th);
- thead.appendChild(tr);
}
+ thead.appendChild(tr);
tab.appendChild(thead);
tbody = document.createElement('tbody');
for (row = 0; row < arr[Object.keys(arr)[0]].length; row++) {
tr = document.createElement('tr');
for (col = 0; col < Object.keys(arr).length; col++) {
+ val = arr[Object.keys(arr).sort()[col]][row];
td = document.createElement('td');
- tn = document.createTextNode(arr[Object.keys(arr).sort()[col]][row]);
+ tn = document.createTextNode(val === None ? '' : val);
td.appendChild(tn);
tr.appendChild(td);
}
@@ -82,38 +84,99 @@
tab.appendChild(tbody);
$(function() {
- $('#container').highcharts({
- title: {
- text: 'Yardstick test results',
- x: -20, //center
- },
- subtitle: {
- text: 'Report of {{task_id}} Task Generated',
- x: -20,
+ var datasets = {{datasets|safe}};
+
+ var colors = [
+ '#FF0000', // Red
+ '#228B22', // ForestGreen
+ '#FF8C00', // DarkOrange
+ '#00008B', // DarkBlue
+ '#FF00FF', // Fuchsia
+ '#9ACD32', // YellowGreen
+ '#FFD700', // Gold
+ '#4169E1', // RoyalBlue
+ '#A0522D', // Sienna
+ '#20B2AA', // LightSeaGreen
+ '#8A2BE2', // BlueViolet
+ ];
+
+ var points = [
+ {s: 'circle', r: 3},
+ {s: 'rect', r: 4},
+ {s: 'triangle', r: 4},
+ {s: 'star', r: 4},
+ {s: 'rectRot', r: 5},
+ ];
+
+ datasets.forEach(function(d, i) {
+ var color = colors[i % colors.length];
+ var point = points[i % points.length];
+ d.borderColor = color;
+ d.backgroundColor = color;
+ d.pointStyle = point.s;
+ d.pointRadius = point.r;
+ d.pointHoverRadius = point.r + 1;
+ });
+
+ new Chart($('#cnvGraph'), {
+ type: 'line',
+ data: {
+ labels: {{Timestamps|safe}},
+ datasets: datasets,
},
- xAxis: {
+ options: {
+ elements: {
+ line: {
+ borderWidth: 2,
+ fill: false,
+ tension: 0,
+ },
+ },
title: {
- text: 'Timestamp',
+ text: [
+ 'Yardstick test results',
+ 'Report of {{task_id}} Task Generated',
+ ],
+ display: true,
},
- categories: {{Timestamps|safe}},
- },
- yAxis: {
- plotLines: [{
- value: 0,
- width: 1,
- color: '#808080',
- }],
- },
- tooltip: {
- valueSuffix: '',
- },
- legend: {
- layout: 'vertical',
- align: 'right',
- verticalAlign: 'middle',
- borderWidth: 0,
+ scales: {
+ xAxes: [{
+ type: 'category',
+ scaleLabel: {
+ display: true,
+ labelString: 'Timestamp',
+ },
+ }],
+ yAxes: [{
+ type: 'linear',
+ scaleLabel: {
+ display: true,
+ labelString: 'Values',
+ },
+ }],
+ },
+ tooltips: {
+ mode: 'point',
+ intersect: true,
+ },
+ hover: {
+ mode: 'index',
+ intersect: false,
+ animationDuration: 0,
+ },
+ legend: {
+ position: 'right',
+ labels: {
+ usePointStyle: true,
+ },
+ },
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ responsiveAnimationDuration: 0,
+ maintainAspectRatio: false,
},
- series: {{series|safe}},
});
});
</script>