This is an automated email from the ASF dual-hosted git repository. domgarguilo pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/accumulo.git
The following commit(s) were added to refs/heads/main by this push: new 7f42c7d72a Convert monitor tables in server.js to DataTables (#2725) 7f42c7d72a is described below commit 7f42c7d72ac8115a933b0e961c6f687c15360543 Author: Dom G <dominic.gargu...@gmail.com> AuthorDate: Fri Jun 3 13:42:10 2022 -0400 Convert monitor tables in server.js to DataTables (#2725) * Convert all tables in server.js to DataTables Co-authored-by: Christopher Tubbs <ctubb...@apache.org> --- .../apache/accumulo/monitor/resources/js/server.js | 340 ++++++++++++++++----- .../apache/accumulo/monitor/templates/server.ftl | 118 ++----- 2 files changed, 278 insertions(+), 180 deletions(-) diff --git a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server.js b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server.js index af539d0d00..54ade81ca5 100644 --- a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server.js +++ b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server.js @@ -18,18 +18,16 @@ */ "use strict"; -var serv; -var tabletResults; +var detailTable, historyTable, currentTable, resultsTable; + /** * Makes the REST calls, generates the tables with the new information */ function refreshServer() { - getTServer(serv).then(function () { - refreshDetailTable(); - refreshHistoryTable(); - refreshCurrentTable(); - refreshResultsTable(); - }); + ajaxReloadTable(detailTable); + ajaxReloadTable(historyTable); + ajaxReloadTable(currentTable); + ajaxReloadTable(resultsTable); } /** @@ -40,91 +38,265 @@ function refresh() { } /** - * Populates the server details table - */ -function refreshDetailTable() { - var data = sessionStorage.server === undefined ? [] : JSON.parse(sessionStorage.server); - if (data.length === 0 || data.details === undefined) { - clearAllTableCells("tServerDetail"); - } else { - $("#hostedTablets").text(bigNumberForQuantity(data.details.hostedTablets)); - $("#entries").text(bigNumberForQuantity(data.details.entries)); - $("#minors").text(bigNumberForQuantity(data.details.minors)); - $("#majors").text(bigNumberForQuantity(data.details.majors)); - $("#splits").text(bigNumberForQuantity(data.details.splits)); - } -} - -/** - * Populates the All Time Tablet Operations table + * Initializes all of the DataTables for the given hostname + * + * @param {String} serv the tserver hostname */ -function refreshHistoryTable() { - var data = sessionStorage.server === undefined ? [] : JSON.parse(sessionStorage.server); +function initServerTables(serv) { - if (data.length === 0 || data.allTimeTabletResults === undefined) { - clearAllTableCells("opHistoryDetails"); - } else { - var totalTimeSpent = 0; - $.each(data.allTimeTabletResults, function (key, val) { - totalTimeSpent += val.timeSpent; - }); + const url = '/rest/tservers/' + serv; + console.debug('REST url used to fetch data for server.js DataTables: ' + url); - $.each(data.allTimeTabletResults, function (key, val) { - // use the first 5 characters of the operation for the jquery selector - var rowId = "#" + val.operation.slice(0, 5) + "Row"; - console.log("Populating rowId " + rowId + " with " + val.operation + " data"); + // Create a table for details on the current server + detailTable = $('#tServerDetail').DataTable({ + "ajax": { + "url": url, + "dataSrc": function (data) { + // the data needs to be in an array to work with DataTables + var arr = []; + if (data.details === undefined) { + console.warn('the value of "details" is undefined'); + } else { + arr = [data.details]; + } - $(rowId).append("<td>" + val.operation + "</td>"); - $(rowId).append("<td>" + bigNumberForQuantity(val.success) + "</td>"); - $(rowId).append("<td>" + bigNumberForQuantity(val.failure) + "</td>"); + return arr; + } + }, + "stateSave": true, + "searching": false, + "paging": false, + "info": false, + "columnDefs": [{ + "targets": "big-num", + "render": function (data, type) { + if (type === 'display') { + data = bigNumberForQuantity(data); + } + return data; + } + }], + "columns": [{ + "data": "hostedTablets" + }, + { + "data": "entries" + }, + { + "data": "minors" + }, + { + "data": "majors" + }, + { + "data": "splits" + } + ] + }); - appendDurationToRow(rowId, val.avgQueueTime); - appendDurationToRow(rowId, val.queueStdDev); - appendDurationToRow(rowId, val.avgTime); - appendDurationToRow(rowId, val.stdDev); + // Create a table for all time tablet operations + historyTable = $('#opHistoryDetails').DataTable({ + "ajax": { + "url": url, + "dataSrc": "allTimeTabletResults" + }, + "stateSave": true, + "searching": false, + "paging": false, + "info": false, + "columnDefs": [{ + "targets": "big-num", + "render": function (data, type) { + if (type === 'display') { + data = bigNumberForQuantity(data); + } + return data; + } + }, + { + "targets": "duration", + "render": function (data, type) { + if (type === 'display') { + if (data === null) { + data = '-'; + } else { + data = timeDuration(data * 1000.0); + } + } + return data; + } + } + ], + "columns": [{ + "data": "operation" + }, + { + "data": "success" + }, + { + "data": "failure" + }, + { + "data": "avgQueueTime" + }, + { + "data": "queueStdDev" + }, + { + "data": "avgTime" + }, + { + "data": "stdDev" + }, + { + "data": "timeSpent" // placeholder for percent column, replaced below + } + ], + // calculate and fill percent column each time table is drawn + "drawCallback": function () { + var totalTime = 0; + var api = this.api(); - var percent = Math.floor((val.timeSpent / totalTimeSpent) * 100); - var progressBarCell = '<td><div class="progress"><div class="progress-bar"' + - ' role="progressbar" style="min-width: 2em; width:' + percent + '%;">' + - percent + '%</div></div></td>'; - console.log("Time spent percent = " + val.timeSpent + "/" + totalTimeSpent + " " + percent); + // calculate total duration of all tablet operations + api.rows().every(function () { + totalTime += this.data().timeSpent; + }); - $(rowId).append(progressBarCell); - }); - } -} + const percentColumnIndex = 7; + api.rows().every(function (rowIdx) { + // calculate the percentage of time taken for each row (each tablet op) + var currentPercent = (this.data().timeSpent / totalTime) * 100; + currentPercent = Math.round(currentPercent); + if (isNaN(currentPercent)) { + currentPercent = 0; + } + // insert the percentage bar into the current row and percent column + var newData = `<div class="progress"><div class="progress-bar" role="progressbar" style="min-width: 2em; width:${currentPercent}%;">${currentPercent}%</div></div>` + api.cell(rowIdx, percentColumnIndex).data(newData); + }); + } + }); -/** - * Populates the current tablet operations results table - */ -function refreshCurrentTable() { - var data = sessionStorage.server === undefined ? [] : JSON.parse(sessionStorage.server); + // Create a table for tablet operations on the current server + currentTable = $('#currentTabletOps').DataTable({ + "ajax": { + "url": url, + "dataSrc": function (data) { + // the data needs to be in an array to work with DataTables + var arr = []; + if (data.currentTabletOperationResults === undefined) { + console.warn('the value of "currentTabletOperationResults" is undefined'); + } else { + arr = [data.currentTabletOperationResults]; + } - if (data.length === 0 || data.currentTabletOperationResults === undefined) { - clearAllTableCells("currentTabletOps"); - } else { - var current = data.currentTabletOperationResults; - $("#currentMinorAvg").html(timeDuration(current.currentMinorAvg * 1000.0)); - $("#currentMinorStdDev").html(timeDuration(current.currentMinorStdDev * 1000.0)); - $("#currentMajorAvg").html(timeDuration(current.currentMajorAvg * 1000.0)); - $("#currentMajorStdDev").html(timeDuration(current.currentMajorStdDev * 1000.0)); - } -} + return arr; + } + }, + "stateSave": true, + "searching": false, + "paging": false, + "info": false, + "columnDefs": [{ + "targets": "duration", + "render": function (data, type) { + if (type === 'display') { + data = timeDuration(data * 1000.0); + } + return data; + } + }], + "columns": [{ + "data": "currentMinorAvg" + }, + { + "data": "currentMinorStdDev" + }, + { + "data": "currentMajorAvg" + }, + { + "data": "currentMajorStdDev" + } + ] + }); -/** - * Generates the server results table - */ -function refreshResultsTable() { - tabletResults.ajax.reload(null, false); // user paging is not reset on reload -} + // Create a table for detailed tablet operations + resultsTable = $('#perTabletResults').DataTable({ + "ajax": { + "url": url, + "dataSrc": "currentOperations" + }, + "stateSave": true, + "dom": 't<"align-left"l>p', + "columnDefs": [{ + "targets": "big-num", + "render": function (data, type) { + if (type === 'display') { + data = bigNumberForQuantity(data); + } + return data; + } + }, + { + "targets": "duration", + "render": function (data, type) { + if (type === 'display') { + data = timeDuration(data); + } + return data; + } + } + ], + "columns": [{ + "data": "name", + "type": "html", + "render": function (data, type, row) { + if (type === 'display') { + data = `<a href="/tables/${row.tableID}">${data}</a>`; + } + return data; + } + }, + { + "data": "tablet", + "type": "html", + "render": function (data, type) { + if (type === 'display') { + data = `<code>${data}</code>`; + } + return data; + } + }, + { + "data": "entries" + }, + { + "data": "ingest" + }, + { + "data": "query" + }, + { + "data": "minorAvg" + }, + { + "data": "minorStdDev" + }, + { + "data": "minorAvgES" + }, + { + "data": "majorAvg" + }, + { + "data": "majorStdDev" + }, + { + "data": "majorAvgES" + } + ] + }); -/* - * Appends a table cell containing value to the rowId, if value is not null - */ -function appendDurationToRow(rowId, value) { - let v = EMPTY_CELL; - if (value != null) { - v = "<td>" + timeDuration(value * 1000.0) + "</td>"; - } - $(rowId).append(v); + refreshServer(); } diff --git a/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/server.ftl b/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/server.ftl index fc16786ee6..3d9428ed39 100644 --- a/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/server.ftl +++ b/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/server.ftl @@ -19,65 +19,10 @@ --> <script> - /** - * Creates a DataTable for tablet details. The "dom" option tells DataTables to only - * show the table(t), length selector(l) aligned to the left and pagination(p). - */ - $(document).ready(function() { - // Global constant for the page - serv = '${server}'; - - // Create a table for tserver list - tabletResults = $('#perTabletResults').DataTable({ - "ajax": { - "url": '/rest/tservers/${server}', - "dataSrc": "currentOperations" - }, - "stateSave": true, - "dom": 't<"align-left"l>p', - "columnDefs": [ - { "targets": "big-num", - "render": function ( data, type, row ) { - if(type === 'display') data = bigNumberForQuantity(data); - return data; - } - }, - { "targets": "duration", - "render": function ( data, type, row ) { - if(type === 'display') data = timeDuration(data); - return data; - } - } - ], - "columns": [ - { "data": "name", - "type": "html", - "render": function ( data, type, row, meta ) { - if(type === 'display') data = '<a href="/tables/' + row.tableID + '">' + data + '</a>'; - return data; - } - }, - { "data": "tablet", - "type": "html", - "render": function ( data, type, row, meta ) { - if(type === 'display') data = '<code>' + data + '</code>'; - return data; - } - }, - { "data": "entries" }, - { "data": "ingest" }, - { "data": "query" }, - { "data": "minorAvg" }, - { "data": "minorStdDev" }, - { "data": "minorAvgES" }, - { "data": "majorAvg" }, - { "data": "majorStdDev" }, - { "data": "majorAvgES" } - ] + $(document).ready(function() { + // initialize DataTables + initServerTables('${server}'); }); - refreshServer(); - }); - </script> <div class="row"> <div class="col-xs-12"> @@ -90,22 +35,14 @@ <caption><span class="table-caption">${server}</span></caption> <thead> <tr> - <th class="firstcell">Hosted Tablets </th> - <th>Entries </th> - <th>Minor Compacting </th> - <th>Major Compacting </th> - <th>Splitting </th> + <th class="big-num">Hosted Tablets </th> + <th class="big-num">Entries </th> + <th class="big-num">Minor Compacting </th> + <th class="big-num">Major Compacting </th> + <th class="big-num">Splitting </th> </tr> </thead> - <tbody> - <tr> - <td id="hostedTablets"></td> - <td id="entries"></td> - <td id="minors"></td> - <td id="majors"></td> - <td id="splits"></td> - </tr> - </tbody> + <tbody></tbody> </table> </div> </div> @@ -115,21 +52,17 @@ <caption><span class="table-caption">All-Time Tablet Operation Results</span></caption> <thead> <tr> - <th class="firstcell">Operation </th> - <th>Success </th> - <th>Failure </th> - <th>Average<br/>Queue Time </th> - <th>Std. Dev.<br/>Queue Time </th> - <th>Average<br/>Time </th> - <th>Std. Dev.<br/>Time </th> + <th>Operation </th> + <th class="big-num">Success </th> + <th class="big-num">Failure </th> + <th class="duration">Average<br/>Queue Time </th> + <th class="duration">Std. Dev.<br/>Queue Time </th> + <th class="duration">Average<br/>Time </th> + <th class="duration">Std. Dev.<br/>Time </th> <th>Percentage Time Spent </th> </tr> </thead> - <tbody> - <tr id="MinorRow"></tr> - <tr id="MajorRow"></tr> - <tr id="SplitRow"></tr> - </tbody> + <tbody></tbody> </table> </div> </div> @@ -139,20 +72,13 @@ <caption><span class="table-caption">Current Tablet Operation Results</span></caption> <thead> <tr> - <th class="firstcell">Minor Average </th> - <th>Minor Std Dev </th> - <th>Major Avg </th> - <th>Major Std Dev </th> + <th class="duration">Minor Average </th> + <th class="duration">Minor Std Dev </th> + <th class="duration">Major Avg </th> + <th class="duration">Major Std Dev </th> </tr> </thead> - <tbody> - <tr> - <td id="currentMinorAvg"></td> - <td id="currentMinorStdDev"></td> - <td id="currentMajorAvg"></td> - <td id="currentMajorStdDev"></td> - </tr> - </tbody> + <tbody></tbody> </table> </div> </div>