aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrice Buriez <patrice.buriez@intel.com>2018-12-17 19:22:16 +0100
committerPatrice Buriez <patrice.buriez@intel.com>2018-12-21 19:07:59 +0100
commit855e0532f9a58986fbb95e19ac42e90b53f031b3 (patch)
treea0362a42deaa5275f9cf73deef0375b86744785a
parent6ab3d996abb23e4cd47dbaa8591577e019a84541 (diff)
Additional rework of NSB report
- Make format_for_jstree expect a list of metric names - Avoid displaying timestamps twice in initial data table - Sort metrics in initial data table - Display testcase name - Fix styling - Make better use of JS and jQuery features - Move event handler to JS file - Avoid adding multiple tbody elements into data table - Adjust unit tests and functional tests accordingly JIRA: YARDSTICK-1367 Topic: report/html_table (12 of 12) Change-Id: I85d853f8e392953cace67e94fa0af2e2492a2b86 Signed-off-by: Patrice Buriez <patrice.buriez@intel.com>
-rw-r--r--yardstick/benchmark/core/report.py29
-rw-r--r--yardstick/common/nsb_report.css34
-rw-r--r--yardstick/common/nsb_report.html.j255
-rw-r--r--yardstick/common/nsb_report.js90
-rw-r--r--yardstick/tests/functional/benchmark/core/test_report.py40
-rw-r--r--yardstick/tests/unit/benchmark/core/test_report.py26
6 files changed, 129 insertions, 145 deletions
diff --git a/yardstick/benchmark/core/report.py b/yardstick/benchmark/core/report.py
index 17a9fe40c..0819cd497 100644
--- a/yardstick/benchmark/core/report.py
+++ b/yardstick/benchmark/core/report.py
@@ -54,11 +54,9 @@ class JSTree(object):
def format_for_jstree(self, data):
"""Format the data into the required format for jsTree.
- The data format expected is a list of key-value pairs which represent
- the data and label for each metric e.g.:
+ The data format expected is a list of metric names e.g.:
- [{'data': [0, ], 'label': 'tg__0.DropPackets'},
- {'data': [548, ], 'label': 'tg__0.LatencyAvg.5'},]
+ ['tg__0.DropPackets', 'tg__0.LatencyAvg.5']
This data is converted into the format required for jsTree to group and
display the metrics in a hierarchial fashion, including creating a
@@ -75,8 +73,8 @@ class JSTree(object):
self._created_nodes = ['#']
self.jstree_data = []
- for item in data:
- self._create_node(item["label"])
+ for metric in data:
+ self._create_node(metric)
return self.jstree_data
@@ -230,8 +228,14 @@ class Report(object):
@cliargs("yaml_name", type=str, help=" Yaml file Name", nargs=1)
def generate_nsb(self, args):
"""Start NSB report generation."""
- datasets, table_vals = self._generate_common(args)
- jstree_data = JSTree().format_for_jstree(datasets)
+ _, report_data = self._generate_common(args)
+ report_time = report_data.pop('Timestamp')
+ report_keys = sorted(report_data, key=str.lower)
+ report_tree = JSTree().format_for_jstree(report_keys)
+ report_meta = {
+ "testcase": self.yaml_name,
+ "task_id": self.task_id,
+ }
template_dir = consts.YARDSTICK_ROOT_PATH + "yardstick/common"
template_environment = jinja2.Environment(
@@ -240,10 +244,11 @@ class Report(object):
lstrip_blocks=True)
context = {
- "Timestamps": self.Timestamp,
- "task_id": self.task_id,
- "table": table_vals,
- "jstree_nodes": jstree_data,
+ "report_meta": report_meta,
+ "report_data": report_data,
+ "report_time": report_time,
+ "report_keys": report_keys,
+ "report_tree": report_tree,
}
template_html = template_environment.get_template("nsb_report.html.j2")
diff --git a/yardstick/common/nsb_report.css b/yardstick/common/nsb_report.css
index 235321441..667f865a5 100644
--- a/yardstick/common/nsb_report.css
+++ b/yardstick/common/nsb_report.css
@@ -9,38 +9,26 @@
******************************************************************************/
body {
- font-size: 16pt;
-}
-
-table {
- overflow-y: scroll;
- height: 360px;
- display: block;
- width: 100%;
+ font-family: Frutiger, "Helvetica Neue", Helvetica, Arial, sans-serif;
}
header {
- font-family: Frutiger, "Helvetica Neue", Helvetica, Arial, sans-serif;
- clear: left;
+ padding-top: 5px;
text-align: center;
-}
-
-h1 {
- font-size: 20pt;
font-weight: bold;
- height: 20px;
- margin: 0px 0px;
}
-h4 {
- font-size: 13pt;
- height: 1px;
- margin-bottom: 0px;
+#tblMetrics {
+ overflow-y: scroll;
+ height: 360px;
+ display: block;
}
-.control-pane {
- font-size: 10pt;
+#cnvGraph {
+ width: 100%;
+ height: 500px;
}
-.data-pane {
+#divTree {
+ font-size: 10pt;
}
diff --git a/yardstick/common/nsb_report.html.j2 b/yardstick/common/nsb_report.html.j2
index 6523fd16f..aa90253f8 100644
--- a/yardstick/common/nsb_report.html.j2
+++ b/yardstick/common/nsb_report.html.j2
@@ -31,56 +31,43 @@
<body>
<div class="container-fluid">
<div class="row">
- <header class="jumbotron">
- <h1>Yardstick User Interface</h1>
- <h4>Report of {{task_id}} Generated</h4>
+ <header>
+ Testcase: {{report_meta.testcase}}<br>
+ Task-ID: {{report_meta.task_id}}<br>
</header>
</div>
<div class="row">
- <div class="col-md-2 control-pane">
- <div id="data_selector"></div>
+ <div class="col-md-2">
+ <div id="divTree"></div>
</div>
- <div class="col-md-10 data-pane">
- <canvas id="cnvGraph" style="width: 100%; height: 500px"></canvas>
+ <div class="col-md-10">
+ <canvas id="cnvGraph"></canvas>
</div>
</div>
<div class="row">
<div class="col-md-12 table-responsive">
- <table class="table table-hover"></table>
+ <table id="tblMetrics" class="table table-condensed table-hover"></table>
</div>
</div>
</div>
<script>
- var arr, jstree_data, timestamps;
- arr = {{table|safe}};
- timestamps = {{Timestamps|safe}};
- jstree_data = {{jstree_nodes|safe}};
+ // Injected metrics, timestamps, keys and hierarchy
+ var report_data = {{report_data|safe}};
+ var report_time = {{report_time|safe}};
+ var report_keys = {{report_keys|safe}};
+ var report_tree = {{report_tree|safe}};
+ // Wait for DOM to be loaded
$(function() {
- create_table(arr, timestamps);
- create_tree(jstree_data);
- var objGraph = create_graph($('#cnvGraph'), timestamps);
+ var tblMetrics = $('#tblMetrics');
+ var cnvGraph = $('#cnvGraph');
+ var divTree = $('#divTree');
- $('#data_selector').on('check_node.jstree uncheck_node.jstree', function(e, data) {
- var selected_datasets = [];
- var new_arr = {};
- deleteRows();
- 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);
- // Create new array for table to show only subset of metrics
- new_arr[node.id] = arr[node.id];
- }
- }
- create_table(new_arr, timestamps);
- update_graph(objGraph, selected_datasets);
- });
+ create_table(tblMetrics, report_data, report_time, report_keys);
+ var objGraph = create_graph(cnvGraph, report_time);
+ create_tree(divTree, report_tree);
+ handle_tree(divTree, tblMetrics, objGraph, report_data, report_time);
});
</script>
</body>
diff --git a/yardstick/common/nsb_report.js b/yardstick/common/nsb_report.js
index 4bff15b5a..4de1c8e78 100644
--- a/yardstick/common/nsb_report.js
+++ b/yardstick/common/nsb_report.js
@@ -10,9 +10,9 @@
var None = null;
-function create_tree(jstree_data)
+function create_tree(divTree, jstree_data)
{
- $('#data_selector').jstree({
+ divTree.jstree({
plugins: ['checkbox'],
checkbox: {
three_state: false,
@@ -29,55 +29,33 @@ function create_tree(jstree_data)
});
}
-function create_table(table_data, timestamps)
+function create_table(tblMetrics, table_data, timestamps, table_keys)
{
- var tab, tr, td, tn, tbody, keys, key, curr_data, val;
- // create table
- tab = document.getElementsByTagName('table')[0];
- tbody = document.createElement('tbody');
+ var tbody = $('<tbody></tbody>');
+ var tr0 = $('<tr></tr>');
+ var th0 = $('<th></th>');
+ var td0 = $('<td></td>');
+ var tr;
+
// create table headings using timestamps
- tr = document.createElement('tr');
- td = document.createElement('td');
- tn = document.createTextNode('Timestamps');
- td.appendChild(tn);
- tr.appendChild(td);
- for (var k = 0; k < timestamps.length; k++) {
- td = document.createElement('td');
- tn = document.createTextNode(timestamps[k]);
- td.appendChild(tn);
- tr.appendChild(td);
- }
- tbody.appendChild(tr);
+ tr = tr0.clone().append(th0.clone().text('Timestamp'));
+ timestamps.forEach(function(t) {
+ tr.append(th0.clone().text(t));
+ });
+ tbody.append(tr);
+
// for each metric
- keys = Object.keys(table_data);
- for (var i = 0; i < keys.length; i++) {
- key = keys[i];
- tr = document.createElement('tr');
- td = document.createElement('td');
- tn = document.createTextNode(key);
- td.appendChild(tn);
- tr.appendChild(td);
+ table_keys.forEach(function(key) {
+ tr = tr0.clone().append(td0.clone().text(key));
// add each piece of data as its own column
- curr_data = table_data[key];
- for (var j = 0; j < curr_data.length; j++) {
- val = curr_data[j];
- td = document.createElement('td');
- tn = document.createTextNode(val === None ? '' : val);
- td.appendChild(tn);
- tr.appendChild(td);
- }
- tbody.appendChild(tr);
- }
- tab.appendChild(tbody);
-}
+ table_data[key].forEach(function(val) {
+ tr.append(td0.clone().text(val === None ? '' : val));
+ });
+ tbody.append(tr);
+ });
-function deleteRows()
-{
- // delete rows of the table
- var tab = document.getElementsByTagName('table')[0];
- for (var i = tab.rows.length - 1; i >= 0; i--) {
- tab.deleteRow(i);
- }
+ // re-create table
+ tblMetrics.empty().append(tbody);
}
function create_graph(cnvGraph, timestamps)
@@ -165,3 +143,23 @@ function update_graph(objGraph, datasets)
objGraph.data.datasets = datasets;
objGraph.update();
}
+
+function handle_tree(divTree, tblMetrics, objGraph, table_data, timestamps)
+{
+ divTree.on('check_node.jstree uncheck_node.jstree', function(e, data) {
+ var selected_keys = [];
+ var selected_datasets = [];
+ data.selected.forEach(function(sel) {
+ var node = data.instance.get_node(sel);
+ if (node.children.length == 0) {
+ selected_keys.push(node.id);
+ selected_datasets.push({
+ label: node.id,
+ data: table_data[node.id],
+ });
+ }
+ });
+ create_table(tblMetrics, table_data, timestamps, selected_keys);
+ update_graph(objGraph, selected_datasets);
+ });
+}
diff --git a/yardstick/tests/functional/benchmark/core/test_report.py b/yardstick/tests/functional/benchmark/core/test_report.py
index 401b97da9..5f060dd1e 100644
--- a/yardstick/tests/functional/benchmark/core/test_report.py
+++ b/yardstick/tests/functional/benchmark/core/test_report.py
@@ -23,9 +23,9 @@ GOOD_YAML_NAME = 'fake_name'
GOOD_TASK_ID = "9cbe74b6-df09-4535-8bdc-dc3a43b8a4e2"
GOOD_DB_FIELDKEYS = [
{u'fieldKey': u'metric1', u'fieldType': u'integer'},
+ {u'fieldKey': u'metric4', u'fieldType': u'integer'},
{u'fieldKey': u'metric2', u'fieldType': u'integer'},
{u'fieldKey': u'metric3', u'fieldType': u'integer'},
- {u'fieldKey': u'metric4', u'fieldType': u'integer'},
]
GOOD_DB_METRICS = [
{u'time': u'2018-08-20T16:49:26.372662016Z',
@@ -73,28 +73,42 @@ class ReportTestCase(unittest.TestCase):
with mock.patch.object(report.consts, 'DEFAULT_HTML_FILE', tmpfile.name):
report.Report().generate_nsb(params)
+ data_act = None
+ time_act = None
+ keys_act = None
+ tree_act = None
with open(tmpfile.name) as f:
for l in f.readlines():
- if " arr = {" in l:
- arr_act = ast.literal_eval(l.strip()[6:-1])
- elif " jstree_data = [" in l:
- jstree_data_act = ast.literal_eval(l.strip()[14:-1])
-
- arr_exp = {
- 'Timestamp':
- ['16:49:26.372662', '16:49:27.374208', '16:49:28.375742',
- '16:49:29.377299', '16:49:30.378252', '16:49:30.379359'],
+ if "var report_data = {" in l:
+ data_act = ast.literal_eval(l.strip()[18:-1])
+ elif "var report_time = [" in l:
+ time_act = ast.literal_eval(l.strip()[18:-1])
+ elif "var report_keys = [" in l:
+ keys_act = ast.literal_eval(l.strip()[18:-1])
+ elif "var report_tree = [" in l:
+ tree_act = ast.literal_eval(l.strip()[18:-1])
+
+ data_exp = {
'metric1': [1, 1, 2, 3, 5, 8],
'metric2': [0, 1, 2, 3, 4, 5],
'metric3': [8, 5, 3, 2, 1, 1],
'metric4': [5, 4, 3, 2, 1, 0],
}
- jstree_data_exp = [
+ time_exp = [
+ '16:49:26.372662', '16:49:27.374208', '16:49:28.375742',
+ '16:49:29.377299', '16:49:30.378252', '16:49:30.379359',
+ ]
+ keys_exp = [
+ 'metric1', 'metric2', 'metric3', 'metric4',
+ ]
+ tree_exp = [
{'parent': '#', 'text': 'metric1', 'id': 'metric1'},
{'parent': '#', 'text': 'metric2', 'id': 'metric2'},
{'parent': '#', 'text': 'metric3', 'id': 'metric3'},
{'parent': '#', 'text': 'metric4', 'id': 'metric4'},
]
- self.assertEqual(arr_exp, arr_act)
- self.assertEqual(jstree_data_exp, jstree_data_act)
+ self.assertEqual(data_exp, data_act)
+ self.assertEqual(time_exp, time_act)
+ self.assertEqual(keys_exp, keys_act)
+ self.assertEqual(tree_exp, tree_act)
diff --git a/yardstick/tests/unit/benchmark/core/test_report.py b/yardstick/tests/unit/benchmark/core/test_report.py
index 41991ddd4..4683c26b0 100644
--- a/yardstick/tests/unit/benchmark/core/test_report.py
+++ b/yardstick/tests/unit/benchmark/core/test_report.py
@@ -117,23 +117,15 @@ class JSTreeTestCase(unittest.TestCase):
def test_format_for_jstree(self):
data = [
- {'data': [0, ], 'label': 'tg__0.DropPackets'},
- {'data': [548, ], 'label': 'tg__0.LatencyAvg.5'},
- {'data': [1172, ], 'label': 'tg__0.LatencyAvg.6'},
- {'data': [1001, ], 'label': 'tg__0.LatencyMax.5'},
- {'data': [1468, ], 'label': 'tg__0.LatencyMax.6'},
- {'data': [18.11, ], 'label': 'tg__0.RxThroughput'},
- {'data': [18.11, ], 'label': 'tg__0.TxThroughput'},
- {'data': [0, ], 'label': 'tg__1.DropPackets'},
- {'data': [548, ], 'label': 'tg__1.LatencyAvg.5'},
- {'data': [1172, ], 'label': 'tg__1.LatencyAvg.6'},
- {'data': [1001, ], 'label': 'tg__1.LatencyMax.5'},
- {'data': [1468, ], 'label': 'tg__1.LatencyMax.6'},
- {'data': [18.1132084505, ], 'label': 'tg__1.RxThroughput'},
- {'data': [18.1157260383, ], 'label': 'tg__1.TxThroughput'},
- {'data': [9057888, ], 'label': 'vnf__0.curr_packets_in'},
- {'data': [0, ], 'label': 'vnf__0.packets_dropped'},
- {'data': [617825443, ], 'label': 'vnf__0.packets_fwd'},
+ 'tg__0.DropPackets',
+ 'tg__0.LatencyAvg.5', 'tg__0.LatencyAvg.6',
+ 'tg__0.LatencyMax.5', 'tg__0.LatencyMax.6',
+ 'tg__0.RxThroughput', 'tg__0.TxThroughput',
+ 'tg__1.DropPackets',
+ 'tg__1.LatencyAvg.5', 'tg__1.LatencyAvg.6',
+ 'tg__1.LatencyMax.5', 'tg__1.LatencyMax.6',
+ 'tg__1.RxThroughput', 'tg__1.TxThroughput',
+ 'vnf__0.curr_packets_in', 'vnf__0.packets_dropped', 'vnf__0.packets_fwd',
]
expected_output = [