Improve slow query handler and show datatable error messages

Fixes #2211
This commit is contained in:
emanuele-f 2018-12-14 17:04:06 +01:00
parent 7f21b11dfb
commit 93db5ebb38
8 changed files with 134 additions and 44 deletions

View file

@ -26,6 +26,7 @@
var DataTable = function ( element, options ) {
this.$element = $(element);
this.options = options;
this.pendingRequest = null;
this.enabled = true;
this.columns = [];
this.rows = [];
@ -44,9 +45,7 @@
this.$default = this.$element.children().length ?
this.$element.children() :
$("<div></div>")
// ------------- Start ntop Patch ---------------
.addClass("alert alert-danger")
// ------------- End ntop Patch ---------------
.html(i18n.no_results_found);
this.$element.addClass("clearfix");
@ -109,9 +108,11 @@
if(o.url !== "") {
var req_data = (typeof o.post === "function") ? o.post() : o.post;
$.ajax({
if(this.pendingRequest)
this.pendingRequest.abort();
this.pendingRequest = $.ajax({
url: o.url
// ------------- Start ntop Patch ---------------
, type: "GET"
, dataType: "json"
, data: $.extend({}, req_data, {
@ -119,17 +120,16 @@
, perPage: o.perPage
, sortColumn: (o.sort.length > 0) ? o.sort[0][0] : null
, sortOrder: (o.sort.length > 0) ? o.sort[0][1] : null
// ------------- End ntop Patch -----------------
, filter: o.filter
})
, success: function( res ) {
, success: function(res, status, xhr) {
that.pendingRequest = null;
if(o.dataAdapter)
res = o.dataAdapter(res, o);
that.resultset = res;
// ------------- Start ntop Patch ---------------
if(!res || res === undefined || !res.data || (res.data.length == 0 && !o.forceTable) ) {
// ------------- End ntop Patch -----------------
showError.call(that, res);
return;
}
@ -169,9 +169,7 @@
that.$bottom_details.append(that.pagination().clone(true));
// update the details for the results
// ------------- Start ntop Patch ---------------
if(! o.hideDetails) that.details();
// ------------- End ntop Patch ---------------
// initialize the toolbar
_initToolbar.call(that);
@ -182,9 +180,10 @@
that.loading( false );
}
, error: function( e ) {
if(o.debug) console.log(e);
showError.call(that, null);
, error: function(xhr, status, e) {
that.pendingRequest = null;
console.error("Datatable: error while loading data: " + e);
showError.call(that, null, status, e);
that.loading( false );
}
@ -211,13 +210,11 @@
})
.append(
$("<div></div>")
// ------------- Start ntop Patch ---------------
.addClass("progress progress-striped")
.append(
$("<div></div>")
.addClass("progress-bar progress-bar-info")
.attr('style', "width: 40%")
// ------------- End ntop Patch -----------------
)
)
.appendTo(document.body)
@ -671,9 +668,7 @@
var o = this.options;
// create the perpage dropdown
// ------------- Start ntop Patch ---------------
if(! o.hidePerPage) _initPerPage.call(this);
// ------------- End ntop Patch ---------------
// handle filter options
if(o.filterModal) _initFilterModal.call(this);
@ -1045,7 +1040,7 @@
return false;
}
function showError(data) {
function showError(data, status, err_msg) {
var o = this.options
, $e = this.$element;
@ -1067,10 +1062,20 @@
if(custom_no_res) {
$e.append(custom_no_res);
} else if(err_msg && (status != "abort")) {
$e.append($("<div></div>")
.addClass("alert alert-danger")
.html(err_msg));
} else if(data && typeof data.error === "string") {
$e.append($("<div></div>")
.addClass("alert alert-danger")
.html(data.error));
} else if(o.noResultsMessage) {
var msg = o.noResultsMessage(this, data);
$e.append($("<div></div>")
.addClass("alert alert-danger")
.html(msg));
} else if(this.$default)
$e.append(this.$default);
}

View file

@ -297,18 +297,18 @@ function fixJumpButtons(epoch_end) {
$("#btn-jump-time-ahead").removeClass("disabled");
}
function queryNoTimeout() {
$("#query-slow-alert").hide();
location.href = location.href + "&no_timeout=1";
}
function showQuerySlow() {
$("#query-slow-alert").show();
}
function hideQuerySlow() {
$("#query-slow-alert").hide();
}
// add a new updateStackedChart function
function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id, params, step, align_step, show_all_smooth, initial_range) {
var pending_request = null;
var pending_chart_request = null;
var pending_table_request = null;
var d3_sel = d3.select(chart_id);
var $chart = $(chart_id);
var $zoom_reset = $(zoom_reset_id);
@ -322,6 +322,10 @@ function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id,
var manual_trigger_cmp_serie = false;
var datetime_format = "dd/MM/yyyy hh:mm:ss";
var max_over_total_ratio = 3;
var query_timer = null;
var seconds_before_query_slow = 6;
var query_completed = 0;
var query_was_aborted = false;
chart.is_zoomed = ((current_zoom_level > 0) || has_initial_zoom());
//var spinner = $("<img class='chart-loading-spinner' src='" + spinner_url + "'/>");
@ -348,7 +352,6 @@ function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id,
d3_sel.datum(new_data).transition().call(chart);
nv.utils.windowResize(chart.update);
pending_request = null;
spinner.remove();
}
@ -453,6 +456,51 @@ function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id,
$zoom_reset.hide();
}
function checkQueryCompleted() {
var flows_dt = $("#chart1-flows");
var wait_num_queries = flows_dt.data("datatable") ? 2 : 1;
query_completed += 1;
if(query_completed >= wait_num_queries) {
if(query_timer) {
clearInterval(query_timer);
query_timer = null;
}
hideQuerySlow();
}
}
chart.queryWasAborted = function() {
return query_was_aborted;
}
chart.abortQuery = function() {
query_was_aborted = true;
if(pending_chart_request) {
pending_chart_request.abort();
chart.noData(i18n.query_was_aborted);
update_chart_data([]);
}
if(pending_table_request)
pending_table_request.abort();
if(query_timer) {
clearInterval(query_timer);
query_timer = null;
}
hideQuerySlow();
}
chart.tableRequestCompleted = function() {
checkQueryCompleted();
pending_table_request = null;
}
var old_start, old_end, old_interval;
/* Returns false if zoom update is rejected. */
@ -504,8 +552,11 @@ function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id,
old_start = params.epoch_begin;
old_end = params.epoch_end;
if(pending_request)
pending_request.abort();
if(pending_table_request)
pending_table_request.abort();
if(pending_chart_request)
pending_chart_request.abort();
else if(!no_spinner)
spinner.appendTo($chart.parent());
@ -515,14 +566,19 @@ function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id,
.maxDate(new Date($.now()))
.date(new Date(Math.min(params.epoch_end * 1000, $.now())));
// Load data via ajax
pending_request = $.get(url, params, function(data) {
if(data && data.error) {
chart.noData(data.error);
if(query_timer)
clearInterval(query_timer);
if(data.tsLastError == "OPERATION_TOO_SLOW")
showQuerySlow();
}
query_timer = setInterval(showQuerySlow, seconds_before_query_slow * 1000);
query_completed = 0;
query_was_aborted = false;
chart.noData(i18n.no_data_available);
hideQuerySlow();
// Load data via ajax
pending_chart_request = $.get(url, params, function(data) {
if(data && data.error)
chart.noData(data.error);
if(!data || !data.series || !data.series.length || !checkSeriesConsinstency(schema_name, data.count, data.series)) {
update_chart_data([]);
@ -780,17 +836,31 @@ function attachStackedChartCallback(chart, schema_name, chart_id, zoom_reset_id,
}
console.error("Error while retrieving the timeseries data [" + status + "]: " + error);
chart.noData(error);
update_chart_data([]);
}).always(function(data, status, xhr) {
checkQueryCompleted();
pending_chart_request = null;
});
if(first_load) {
first_load = false;
/* Wait for page load because datatable is not instantiated yet right now */
$(function() {
var flows_dt = $("#chart1-flows").data("datatable");
if(flows_dt)
pending_table_request = flows_dt.pendingRequest;
});
} else {
var flows_dt = $("#chart1-flows");
/* Reload datatable */
if(flows_dt.data("datatable"))
if(flows_dt.data("datatable")) {
/* note: flows_dt.data("datatable") will change after this call */
updateGraphsTableView(null, params);
pending_table_request = flows_dt.data("datatable").pendingRequest;
}
}
if(typeof on_load_callback === "function")
@ -874,6 +944,10 @@ function updateGraphsTableView(view, graph_params, has_nindex, nindex_query, per
css: {width: "1%", "white-space": "nowrap", "text-align": "center"},
});
var old_dt = graph_table.data("datatable");
if(old_dt && old_dt.pendingRequest)
old_dt.pendingRequest.abort();
/* Force reinstantiation */
graph_table.removeData('datatable');
graph_table.html("");
@ -882,6 +956,12 @@ function updateGraphsTableView(view, graph_params, has_nindex, nindex_query, per
title: "",
url: url,
perPage: per_page,
noResultsMessage: function() {
if(ts_chart.queryWasAborted())
return i18n.query_was_aborted;
else
return i18n.no_results_found;
},
post: function() {
var params = $.extend({}, graph_params);
delete params.ts_compare;
@ -898,6 +978,12 @@ function updateGraphsTableView(view, graph_params, has_nindex, nindex_query, per
buttons: view.nindex_view ? [nindex_buttons, ] : [],
tableCallback: function() {
var data = this.resultset;
ts_chart.tableRequestCompleted();
if(!data) {
// error
return;
}
/* The user changed page */
if(data.currentPage > 1)
@ -916,9 +1002,6 @@ function updateGraphsTableView(view, graph_params, has_nindex, nindex_query, per
stats_div.show();
} else
stats_div.hide();
if(data && data.tsLastError == "OPERATION_TOO_SLOW")
showQuerySlow();
}, rowCallback: function(row, row_data) {
if((typeof row_data.tags === "object") && (
(params_obj.category && (row_data.tags.category === params_obj.category)) ||

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long