Skip to content

Commit 0a5a97f

Browse files
georges-armTamarChristinaArm
authored andcommitted
Sort results in async report by descending severity.
Previously we just added results to the result table in whatever order they were received from the server. This commit changes that to regenerate the entire table on each new fetch result, and to sort the results first in descending absolute percentage delta. This isn't quite identical to the non-async version, but it's much closer than what we had before. Change-Id: I97866743fb347e9f16f2ba71be4389bc69de29da
1 parent ba327c3 commit 0a5a97f

File tree

1 file changed

+87
-36
lines changed

1 file changed

+87
-36
lines changed

lnt/server/ui/templates/reporting/daily_report_async.html

Lines changed: 87 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,14 @@ <h3>Result Table ({{ field.display_name }})</h3>
268268
return ret;
269269
}
270270

271+
const MACHINES = {
272+
{% for machine in report.reporting_machines %}
273+
{{ machine.id }}: {
274+
name: "{{ machine.name }}",
275+
},
276+
{% endfor %}
277+
};
278+
271279
const FIELDS = [
272280
{% for field in report.fields|reverse %}
273281
{
@@ -277,6 +285,76 @@ <h3>Result Table ({{ field.display_name }})</h3>
277285
{% endfor %}
278286
];
279287

288+
// this is filled in asynchronously and used to regenerate the result table.
289+
// we cannot just append to the DOM directly since we want the result table
290+
// to be sorted by some priority metric (largest abs percentage delta).
291+
var KEY_RUNS = {}; // { machine.id -> run.id }
292+
var RESULTS = {}; // { field.display_name -> { test.id -> { name, results: { machine.id -> day results }}}}
293+
294+
function test_priority_compare(a, b) {
295+
const a_res = a[1].results;
296+
const b_res = b[1].results;
297+
var a_max_delta = 0;
298+
var b_max_delta = 0;
299+
for (const [machine_id, rt_day_results] of Object.entries(a[1].results)) {
300+
a_max_delta = Math.max(a_max_delta, Math.abs(rt_day_results[0].pct_delta));
301+
}
302+
for (const [machine_id, rt_day_results] of Object.entries(b[1].results)) {
303+
b_max_delta = Math.max(b_max_delta, Math.abs(rt_day_results[0].pct_delta));
304+
}
305+
// descending order, higher deltas first.
306+
return b_max_delta - a_max_delta;
307+
}
308+
309+
function regenerate_results_tables_for_field(field, results) {
310+
var rt_table_id = "rt-" + field.display_name;
311+
var rt_table = document.getElementById(rt_table_id);
312+
rt_table.innerHTML = '';
313+
for (const [rt_test_id, rt_value] of Object.entries(results).sort(test_priority_compare)) {
314+
var rt_test_name = rt_value.name;
315+
// make the test header (used for multiple machines)
316+
var rt_header_str = '';
317+
rt_header_str += '<tr>';
318+
rt_header_str += ' <td style="{{ styles.td }}" colspan=2><b>' + rt_test_name + '</b></td>';
319+
rt_header_str += ' <td style="{{ styles.td }}" colspan="{{report.num_prior_days_to_include + 1}}">&nbsp;</td>';
320+
rt_header_str += '</tr>'
321+
rt_table.insertAdjacentHTML('beforeend', rt_header_str);
322+
// actually write each result
323+
for (const [machine_id, rt_day_results] of Object.entries(rt_value.results)) {
324+
const machine_name = MACHINES[machine_id].name;
325+
const today_key_run = KEY_RUNS[machine_id];
326+
var rt_detail_str = '';
327+
rt_detail_str += '<tr class="searchable">';
328+
rt_detail_str += ' <td style="{{ styles.td }}">&nbsp;</td>';
329+
rt_detail_str += ' <td class="machine-name" style="{{ styles.td }}">';
330+
// e.g. http://base_url/db_default/v4/db_name/graph?plot=29.348.0&highlight_run=8122
331+
rt_detail_str += ' <a href="{{ ts_url }}/graph?plot=' + machine_id + '.' + rt_test_id + '.' + field.index + '&highlight_run=' + today_key_run + '">' + machine_name + '</a>';
332+
rt_detail_str += ' </td>';
333+
var first = true;
334+
for (var i={{ report.num_prior_days_to_include }}-1; i>=0; i--) {
335+
const rt_day_val = rt_day_results[i];
336+
if (!rt_day_val) {
337+
rt_detail_str += ' <td style="{{ styles.td }}">-</td>';
338+
} else if (first) {
339+
rt_detail_str += get_initial_cell_value(rt_day_val);
340+
first = false;
341+
} else {
342+
rt_detail_str += get_cell_value(rt_day_val);
343+
}
344+
}
345+
rt_detail_str += ' <td>' + spark_plot(rt_day_results) + '</td>';
346+
rt_detail_str += '</tr>';
347+
rt_table.insertAdjacentHTML('beforeend', rt_detail_str);
348+
}
349+
}
350+
}
351+
352+
function regenerate_results_tables() {
353+
for (const field of FIELDS) {
354+
regenerate_results_tables_for_field(field, RESULTS[field.display_name]);
355+
}
356+
}
357+
280358
function handle_async_populate_result(res) {
281359
for (const machine of Object.values(res.data.reporting_machines)) {
282360
for (var i=0; i<{{ report.num_prior_days_to_include }}; i++) {
@@ -297,50 +375,23 @@ <h3>Result Table ({{ field.display_name }})</h3>
297375
}
298376
var today_key_run = res.data.machine_runs['' + machine.id]["0"];
299377
if (today_key_run) {
378+
KEY_RUNS[machine.id] = today_key_run.id;
379+
// RESULTS: { field.display_name -> { test.id -> { name, results: { machine.id -> day results }}}}
300380
for (const field of FIELDS) {
301-
var rt_table_id = "rt-" + field.display_name;
302-
var rt_table = document.getElementById(rt_table_id);
381+
RESULTS[field.display_name] = RESULTS[field.display_name] || {};
382+
var field_results = RESULTS[field.display_name];
383+
// merge new data into (possibly pre-existing from other results) field_results object.
303384
var rt_data = res.data['result_table'][field.display_name]
304385
for (const [rt_test_id, rt_value] of Object.entries(rt_data)) {
305-
var rt_header_id = rt_table_id + '-' + rt_test_id;
306386
var rt_test_name = res.data.reporting_tests['' + rt_test_id].name;
307-
// merge the same test id under a common header if it already exists.
308-
var rt_header = document.getElementById(rt_header_id);
309-
if (!rt_header) {
310-
var rt_header_str = '';
311-
rt_header_str += '<tr id="' + rt_header_id + '">';
312-
rt_header_str += ' <td style="{{ styles.td }}" colspan=2><b>' + rt_test_name + '</b></td>';
313-
rt_header_str += ' <td style="{{ styles.td }}" colspan="{{report.num_prior_days_to_include + 1}}">&nbsp;</td>';
314-
rt_header_str += '</tr>'
315-
rt_table.insertAdjacentHTML('beforeend', rt_header_str);
316-
rt_header = document.getElementById(rt_header_id);
317-
}
318-
var rt_detail_str = '';
319-
rt_detail_str += '<tr class="searchable">';
320-
rt_detail_str += ' <td style="{{ styles.td }}">&nbsp;</td>';
321-
rt_detail_str += ' <td class="machine-name" style="{{ styles.td }}">';
322-
// e.g. http://base_url/db_default/v4/db_name/graph?plot=29.348.0&highlight_run=8122
323-
rt_detail_str += ' <a href="{{ ts_url }}/graph?plot=' + machine.id + '.' + rt_test_id + '.' + field.index + '&highlight_run=' + today_key_run.id + '">' + machine.name + '</a>';
324-
rt_detail_str += ' </td>';
325-
var first = true;
326-
for (var i={{ report.num_prior_days_to_include }}-1; i>=0; i--) {
327-
const rt_day_val = rt_value['' + machine.id][i];
328-
if (!rt_day_val) {
329-
rt_detail_str += ' <td style="{{ styles.td }}">-</td>';
330-
} else if (first) {
331-
rt_detail_str += get_initial_cell_value(rt_day_val);
332-
first = false;
333-
} else {
334-
rt_detail_str += get_cell_value(rt_day_val);
335-
}
336-
}
337-
rt_detail_str += ' <td>' + spark_plot(rt_value['' + machine.id]) + '</td>';
338-
rt_detail_str += '</tr>';
339-
rt_header.insertAdjacentHTML('afterend', rt_detail_str);
387+
field_results[rt_test_id] = field_results[rt_test_id] || { name: rt_test_name, results: {} };
388+
field_results[rt_test_id].results[machine.id] = rt_value['' + machine.id];
340389
}
341390
}
342391
}
343392
}
393+
// now that we've updated the RESULTS object, regenerate any results tables.
394+
regenerate_results_tables();
344395
}
345396

346397
async function populate_table(res) {

0 commit comments

Comments
 (0)