diff options
-rw-r--r-- | yardstick/benchmark/core/report.py | 29 | ||||
-rw-r--r-- | yardstick/common/nsb_report.css | 34 | ||||
-rw-r--r-- | yardstick/common/nsb_report.html.j2 | 55 | ||||
-rw-r--r-- | yardstick/common/nsb_report.js | 90 | ||||
-rw-r--r-- | yardstick/tests/functional/benchmark/core/test_report.py | 40 | ||||
-rw-r--r-- | yardstick/tests/unit/benchmark/core/test_report.py | 26 |
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 = [ |