diff --git a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/table.js b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/table.js
index 0dd150c89e9..198ea151328 100644
--- a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/table.js
+++ b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/table.js
@@ -19,13 +19,75 @@
"use strict";
var tableServersTable;
+var tabletServersTable;
var tabletsTable;
+var tabletsUrl;
/**
* Makes the REST calls, generates the tables with the new information
*/
function refreshTable() {
- ajaxReloadTable(tableServersTable);
+ if (tableServersTable) {
+ ajaxReloadTable(tableServersTable);
+ }
+ if (tabletsUrl && tabletServersTable && tabletsTable) {
+ refreshTabletTables();
+ }
+}
+
+/**
+ * @returns {String} the tablet server host and port parsed from the given location string, or "UNASSIGNED" if unavailable
+ */
+function tabletServerFromLocation(location) {
+ if (!location) {
+ return 'UNASSIGNED';
+ }
+
+ if (location.startsWith('CURRENT:')) {
+ return location.substring('CURRENT:'.length);
+ }
+
+ if (location.startsWith('FUTURE:')) {
+ return location.substring('FUTURE:'.length);
+ }
+
+ const separator = location.indexOf(':');
+ if (separator < 0 || separator + 1 >= location.length) {
+ return location;
+ }
+
+ return location.substring(separator + 1);
+}
+
+/**
+ * Roll up per-tablet counts by tablet server.
+ */
+function summarizeTabletsByServer(tablets) {
+ const summaries = new Map();
+
+ tablets.forEach(function (tablet) {
+ const server = tabletServerFromLocation(tablet.location);
+ let summary = summaries.get(server);
+ if (summary === undefined) {
+ summary = {
+ tabletServer: server,
+ tabletCount: 0,
+ estimatedEntries: 0,
+ estimatedSize: 0,
+ numFiles: 0,
+ numWalLogs: 0
+ };
+ summaries.set(server, summary);
+ }
+
+ summary.tabletCount += 1;
+ summary.estimatedEntries += tablet.estimatedEntries ?? 0;
+ summary.estimatedSize += tablet.estimatedSize ?? 0;
+ summary.numFiles += tablet.numFiles ?? 0;
+ summary.numWalLogs += tablet.numWalLogs ?? 0;
+ });
+
+ return Array.from(summaries.values());
}
/**
@@ -38,15 +100,27 @@ function refresh() {
/**
* Makes the REST call to fetch tablet details and render them.
*/
-function initTabletsTable(tableId) {
- var tabletsUrl = contextPath + 'rest-v2/tables/' + tableId + '/tablets';
+function refreshTabletTables() {
console.debug('Fetching tablets info from: ' + tabletsUrl);
+ $.getJSON(tabletsUrl, function (data) {
+ var tablets = Array.isArray(data) ? data : [];
+
+ tabletServersTable.clear();
+ tabletServersTable.rows.add(summarizeTabletsByServer(tablets));
+ tabletServersTable.draw(false);
+
+ tabletsTable.clear();
+ tabletsTable.rows.add(tablets);
+ tabletsTable.draw(false);
+ });
+}
+
+/**
+ * Initializes the tablet details table.
+ */
+function initTabletsTable() {
tabletsTable = $('#tabletsList').DataTable({
- "ajax": {
- "url": tabletsUrl,
- "dataSrc": ""
- },
"stateSave": true,
"columnDefs": [{
"targets": "big-num",
@@ -99,6 +173,65 @@ function initTabletsTable(tableId) {
});
}
+/**
+ * Initializes the tablet server rollup table.
+ */
+function initTabletServersTable() {
+ tabletServersTable = $('#tabletServersList').DataTable({
+ "stateSave": true,
+ "searching": false,
+ "paging": false,
+ "info": false,
+ "order": [
+ [0, 'asc']
+ ],
+ "columnDefs": [{
+ "targets": "big-num",
+ "render": function (data, type) {
+ if (type === 'display') {
+ data = bigNumberForQuantity(data);
+ }
+ return data;
+ }
+ },
+ {
+ "targets": "big-size",
+ "render": function (data, type) {
+ if (type === 'display') {
+ data = bigNumberForSize(data);
+ }
+ return data;
+ }
+ }
+ ],
+ "columns": [{
+ "data": "tabletCount",
+ "title": "Tablet Count"
+ },
+ {
+ "data": "tabletServer",
+ "title": "Tablet Server"
+ },
+ {
+ "data": "estimatedEntries",
+ "title": "Estimated Entries"
+ },
+ {
+ "data": "estimatedSize",
+ "title": "Estimated Size"
+ },
+ {
+ "data": "numFiles",
+ "title": "Files"
+ },
+ {
+ "data": "numWalLogs",
+ "title": "WALs"
+ }
+ ]
+ });
+}
+
/**
* Initialize the table
*
@@ -106,6 +239,7 @@ function initTabletsTable(tableId) {
*/
function initTableServerTable(tableId) {
const url = contextPath + 'rest-v2/tables/' + tableId;
+ tabletsUrl = contextPath + 'rest-v2/tables/' + tableId + '/tablets';
console.debug('REST url used to fetch summary data: ' + url);
tableServersTable = $('#participatingTServers').DataTable({
@@ -194,6 +328,7 @@ function initTableServerTable(tableId) {
]
});
- refreshTable();
- initTabletsTable(tableId);
+ initTabletServersTable();
+ initTabletsTable();
+ refreshTabletTables();
}
diff --git a/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/table.ftl b/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/table.ftl
index 5c034e432e0..458e5989382 100644
--- a/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/table.ftl
+++ b/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/table.ftl
@@ -57,6 +57,25 @@
+
| Tablet Count | +Tablet Server | +Estimated Entries | +Estimated Size | +Files | +WALs | +
|---|