This is an automated email from the ASF dual-hosted git repository.

dlmarion 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 aecf542795 Added overview tables to main page (#6388)
aecf542795 is described below

commit aecf54279503a24e6df0e7e7b2c9c334de93ccb9
Author: Dave Marion <[email protected]>
AuthorDate: Fri May 29 07:51:31 2026 -0400

    Added overview tables to main page (#6388)
    
    Added cards that show general instance information plus
    global ingest, scan, and compaction activity.
    
    
    Co-authored-by: Dom G. <[email protected]>
---
 .../apache/accumulo/monitor/next/Endpoints.java    |  11 +-
 .../accumulo/monitor/next/SystemInformation.java   | 303 ++++++++++++++++++++-
 .../accumulo/monitor/resources/js/functions.js     |  13 +-
 .../accumulo/monitor/resources/js/overview.js      | 102 ++++++-
 .../apache/accumulo/monitor/templates/overview.ftl |  76 +++++-
 5 files changed, 475 insertions(+), 30 deletions(-)

diff --git 
a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/Endpoints.java 
b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/Endpoints.java
index 23c6211a38..255930d5b9 100644
--- 
a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/Endpoints.java
+++ 
b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/Endpoints.java
@@ -62,6 +62,7 @@ import 
org.apache.accumulo.monitor.next.SystemInformation.CompactionGroupSummary
 import 
org.apache.accumulo.monitor.next.SystemInformation.CompactionTableSummary;
 import org.apache.accumulo.monitor.next.SystemInformation.FateTransaction;
 import org.apache.accumulo.monitor.next.SystemInformation.FetchCycleTimes;
+import org.apache.accumulo.monitor.next.SystemInformation.InstanceOverview;
 import org.apache.accumulo.monitor.next.SystemInformation.RecoveryInformation;
 import org.apache.accumulo.monitor.next.SystemInformation.Scan;
 import org.apache.accumulo.monitor.next.SystemInformation.TableSummary;
@@ -188,7 +189,7 @@ public class Endpoints {
   }
 
   @GET
-  @Path("instance")
+  @Path("instance/info")
   @Produces(MediaType.APPLICATION_JSON)
   @Description("Returns the instance name, instance id, version, zookeepers, 
and volumes")
   public InstanceSummary getInstanceSummary() {
@@ -200,6 +201,14 @@ public class Endpoints {
         Constants.VERSION);
   }
 
+  @GET
+  @Path("instance/overview")
+  @Produces(MediaType.APPLICATION_JSON)
+  @Description("Returns an overview of instance level activity")
+  public InstanceOverview getInstanceOverview() {
+    return 
monitor.getInformationFetcher().getSummaryForEndpoint().getInstanceOverview();
+  }
+
   @GET
   @Path("compactors/detail/{" + GROUP_PARAM_KEY + "}")
   @Produces(MediaType.APPLICATION_JSON)
diff --git 
a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/SystemInformation.java
 
b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/SystemInformation.java
index efd7ab0590..0f2006fd6c 100644
--- 
a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/SystemInformation.java
+++ 
b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/SystemInformation.java
@@ -55,6 +55,8 @@ import java.util.function.Supplier;
 import java.util.stream.Stream;
 
 import org.apache.accumulo.core.Constants;
+import org.apache.accumulo.core.client.AccumuloException;
+import org.apache.accumulo.core.client.AccumuloSecurityException;
 import org.apache.accumulo.core.client.TableNotFoundException;
 import org.apache.accumulo.core.client.admin.TabletAvailability;
 import org.apache.accumulo.core.client.admin.TabletInformation;
@@ -111,6 +113,159 @@ import 
io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
 
 public class SystemInformation {
 
+  public static class InstanceOverview {
+    private final AtomicLong numKVs = new AtomicLong(0);
+    private final AtomicLong numFiles = new AtomicLong(0);
+    private final AtomicLong numTables = new AtomicLong(0);
+    private final AtomicLong numNamespaces = new AtomicLong(0);
+    private final AtomicLong numTablets = new AtomicLong(0);
+    private final AtomicLong totalFileSize = new AtomicLong(0);
+    private final AtomicLong tabletsAssignedToDeadTServers = new AtomicLong(0);
+    private final AtomicLong totalSuspendedTablets = new AtomicLong(0);
+    private final AtomicLong tabletsNeedingRecovery = new AtomicLong(0);
+    private final AtomicLong compactionsQueued = new AtomicLong(0);
+    private final AtomicLong compactionsDequeued = new AtomicLong(0);
+    private final AtomicLong compactionsRunning = new AtomicLong(0);
+    private final AtomicLong compactionsFailed = new AtomicLong(0);
+    private final AtomicLong scansTotalInProgress = new AtomicLong(0);
+    private final AtomicLong scanTotalOpenFiles = new AtomicLong(0);
+    private final AtomicLong scansTotalKvScanned = new AtomicLong(0);
+    private final AtomicLong scansTotalKvReturned = new AtomicLong(0);
+    private final AtomicLong scansTotalKvReturnedBytes = new AtomicLong(0);
+    private final AtomicLong ingestTotalEntries = new AtomicLong(0);
+    private final AtomicLong ingestTotalEntriesBytes = new AtomicLong(0);
+    private final AtomicLong ingestNumTServersHolding = new AtomicLong(0);
+    private final AtomicLong ingestTotalEntriesInMem = new AtomicLong(0);
+    private final AtomicLong ingestBulkImportQueued = new AtomicLong(0);
+    private final AtomicLong ingestBulkImportRunning = new AtomicLong(0);
+    private final AtomicLong totalMinCQueued = new AtomicLong(0);
+    private final AtomicLong totalMinCRunning = new AtomicLong(0);
+    private final AtomicLong totalMinCCompleted = new AtomicLong(0);
+    private final AtomicLong totalFateSubmitted = new AtomicLong(0);
+    private final AtomicLong totalFateRunning = new AtomicLong(0);
+    private final AtomicLong totalServersLowMem = new AtomicLong(0);
+
+    public AtomicLong getNumKVs() {
+      return numKVs;
+    }
+
+    public AtomicLong getNumFiles() {
+      return numFiles;
+    }
+
+    public AtomicLong getNumTablets() {
+      return numTablets;
+    }
+
+    public AtomicLong getNumTables() {
+      return numTables;
+    }
+
+    public AtomicLong getNumNamespaces() {
+      return numNamespaces;
+    }
+
+    public AtomicLong getTotalFileSize() {
+      return totalFileSize;
+    }
+
+    public AtomicLong getTabletsAssignedToDeadTServers() {
+      return tabletsAssignedToDeadTServers;
+    }
+
+    public AtomicLong getTotalSuspendedTablets() {
+      return totalSuspendedTablets;
+    }
+
+    public AtomicLong getTabletsNeedingRecovery() {
+      return tabletsNeedingRecovery;
+    }
+
+    public AtomicLong getCompactionsQueued() {
+      return compactionsQueued;
+    }
+
+    public AtomicLong getCompactionsDequeued() {
+      return compactionsDequeued;
+    }
+
+    public AtomicLong getCompactionsRunning() {
+      return compactionsRunning;
+    }
+
+    public AtomicLong getCompactionsFailed() {
+      return compactionsFailed;
+    }
+
+    public AtomicLong getScansTotalInProgress() {
+      return scansTotalInProgress;
+    }
+
+    public AtomicLong getScanTotalOpenFiles() {
+      return scanTotalOpenFiles;
+    }
+
+    public AtomicLong getScansTotalKvScanned() {
+      return scansTotalKvScanned;
+    }
+
+    public AtomicLong getScansTotalKvReturned() {
+      return scansTotalKvReturned;
+    }
+
+    public AtomicLong getScansTotalKvReturnedBytes() {
+      return scansTotalKvReturnedBytes;
+    }
+
+    public AtomicLong getIngestTotalEntries() {
+      return ingestTotalEntries;
+    }
+
+    public AtomicLong getIngestTotalEntriesBytes() {
+      return ingestTotalEntriesBytes;
+    }
+
+    public AtomicLong getIngestNumTServersHolding() {
+      return ingestNumTServersHolding;
+    }
+
+    public AtomicLong getIngestTotalEntriesInMem() {
+      return ingestTotalEntriesInMem;
+    }
+
+    public AtomicLong getIngestBulkImportQueued() {
+      return ingestBulkImportQueued;
+    }
+
+    public AtomicLong getIngestBulkImportRunning() {
+      return ingestBulkImportRunning;
+    }
+
+    public AtomicLong getTotalMinCQueued() {
+      return totalMinCQueued;
+    }
+
+    public AtomicLong getTotalMinCRunning() {
+      return totalMinCRunning;
+    }
+
+    public AtomicLong getTotalMinCCompleted() {
+      return totalMinCCompleted;
+    }
+
+    public AtomicLong getTotalFateSubmitted() {
+      return totalFateSubmitted;
+    }
+
+    public AtomicLong getTotalFateRunning() {
+      return totalFateRunning;
+    }
+
+    public AtomicLong getTotalServersLowMem() {
+      return totalServersLowMem;
+    }
+  }
+
   public static class ObfuscatedTabletId extends TabletIdImpl {
 
     public ObfuscatedTabletId(KeyExtent ke) {
@@ -261,12 +416,16 @@ public class SystemInformation {
       return tableName;
     }
 
-    public void addTablet(TabletInformation info) {
+    public void addTablet(TabletInformation info, InstanceOverview io) {
       totalEntries.addAndGet(info.getEstimatedEntries());
+      io.getNumKVs().addAndGet(info.getEstimatedEntries());
       totalSizeOnDisk.addAndGet(info.getEstimatedSize());
+      io.getTotalFileSize().addAndGet(info.getEstimatedSize());
       totalFiles.addAndGet(info.getNumFiles());
+      io.getNumFiles().addAndGet(info.getNumFiles());
       totalWals.addAndGet(info.getNumWalLogs());
       totalTablets.addAndGet(1);
+      io.getNumTablets().incrementAndGet();
       switch (info.getTabletAvailability()) {
         case HOSTED:
           availableAlways.addAndGet(1);
@@ -288,12 +447,14 @@ public class SystemInformation {
           break;
         case ASSIGNED_TO_DEAD_SERVER:
           totalAssignedToDeadServerTablets.addAndGet(1);
+          io.getTabletsAssignedToDeadTServers().incrementAndGet();
           break;
         case HOSTED:
           totalHostedTablets.addAndGet(1);
           break;
         case SUSPENDED:
           totalSuspendedTablets.addAndGet(1);
+          io.getTotalSuspendedTablets().incrementAndGet();
           break;
         case UNASSIGNED:
           totalUnassignedTablets.addAndGet(1);
@@ -559,6 +720,8 @@ public class SystemInformation {
   private final int rgLongRunningCompactionSize;
   private FetchCycleTimes timing = null;
 
+  private final InstanceOverview instanceOverview = new InstanceOverview();
+
   public SystemInformation(Cache<ServerId,MetricResponse> allMetrics, 
ServerContext ctx) {
     this.allMetrics = allMetrics;
     this.ctx = ctx;
@@ -827,13 +990,23 @@ public class SystemInformation {
         for (ByteBuffer binary : response.getMetrics()) {
           flatbuffer = FMetric.getRootAsFMetric(binary, flatbuffer);
           final String metricName = flatbuffer.name();
-          if 
(metricName.equals(Metric.COMPACTOR_MAJC_FAILURES_CONSECUTIVE.getName())) {
+          if (metricName.equals(Metric.COMPACTOR_MAJC_IN_PROGRESS.getName())) {
+            long running = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getCompactionsRunning().addAndGet(running);
+          } else if 
(metricName.equals(Metric.COMPACTOR_MAJC_FAILED.getName())) {
+            long failed = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getCompactionsFailed().addAndGet(failed);
+          } else if (metricName.equals(Metric.LOW_MEMORY.getName())) {
+            long lowMem = getMetricValue(flatbuffer).longValue();
+            if (lowMem > 0) {
+              this.instanceOverview.getTotalServersLowMem().incrementAndGet();
+            }
+          } else if 
(metricName.equals(Metric.COMPACTOR_MAJC_FAILURES_CONSECUTIVE.getName())) {
             boolean failures = getMetricValue(flatbuffer).longValue() > 0;
             if (failures) {
               addAlert(Info, Resource,
                   "Compactor has had " + failures + " consecutive failures: " 
+ server.toString());
             }
-            break;
           }
         }
         break;
@@ -841,6 +1014,17 @@ public class SystemInformation {
         if (gc.get() == null || !gc.get().equals(server)) {
           gc.set(server);
         }
+        for (ByteBuffer binary : response.getMetrics()) {
+          flatbuffer = FMetric.getRootAsFMetric(binary, flatbuffer);
+          final String metricName = flatbuffer.name();
+          if (metricName.equals(Metric.LOW_MEMORY.getName())) {
+            long lowMem = getMetricValue(flatbuffer).longValue();
+            if (lowMem > 0) {
+              this.instanceOverview.getTotalServersLowMem().incrementAndGet();
+            }
+            break;
+          }
+        }
         break;
       case MANAGER:
         managers.add(server);
@@ -851,11 +1035,13 @@ public class SystemInformation {
             boolean recovering = getMetricValue(flatbuffer).longValue() > 0;
             this.recoveries.getOverview().setRootTabletRecovering(recovering);
             if (recovering) {
+              
this.instanceOverview.getTabletsNeedingRecovery().incrementAndGet();
               addAlert(Critical, Table, "The root table requires recovery");
             }
           } else if 
(metricName.equals(Metric.MANAGER_META_TGW_RECOVERY.getName())) {
             long tablets = getMetricValue(flatbuffer).longValue();
             
this.recoveries.getOverview().setMetadataTabletsRecovering(tablets);
+            
this.instanceOverview.getTabletsNeedingRecovery().addAndGet(tablets);
             if (tablets > 0) {
               addAlert(Critical, Table,
                   "At least " + tablets + " metadata table tablets require 
recovery");
@@ -863,6 +1049,7 @@ public class SystemInformation {
           } else if 
(metricName.equals(Metric.MANAGER_USER_TGW_RECOVERY.getName())) {
             long tablets = getMetricValue(flatbuffer).longValue();
             this.recoveries.getOverview().setUserTabletsRecovering(tablets);
+            
this.instanceOverview.getTabletsNeedingRecovery().addAndGet(tablets);
             if (tablets > 0) {
               addAlert(High, Table, "At least " + tablets + " user table 
tablets require recovery");
             }
@@ -874,6 +1061,18 @@ public class SystemInformation {
               addAlert(Critical, Configuration,
                   "A compaction service configuration is invalid. Check the 
Manager log.");
             }
+          } else if 
(metricName.equals(Metric.COMPACTOR_JOB_PRIORITY_QUEUE_JOBS_QUEUED.getName())) {
+            long queued = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getCompactionsQueued().addAndGet(queued);
+          } else if (metricName
+              
.equals(Metric.COMPACTOR_JOB_PRIORITY_QUEUE_JOBS_DEQUEUED.getName())) {
+            long dequeued = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getCompactionsDequeued().addAndGet(dequeued);
+          } else if (metricName.equals(Metric.LOW_MEMORY.getName())) {
+            long lowMem = getMetricValue(flatbuffer).longValue();
+            if (lowMem > 0) {
+              this.instanceOverview.getTotalServersLowMem().incrementAndGet();
+            }
           }
         }
         break;
@@ -881,11 +1080,78 @@ public class SystemInformation {
         sservers.computeIfAbsent(response.getResourceGroup(), (rg) -> 
ConcurrentHashMap.newKeySet())
             .add(server);
         updateAggregates(response, totalSServerMetrics, rgSServerMetrics);
+        for (ByteBuffer binary : response.getMetrics()) {
+          flatbuffer = FMetric.getRootAsFMetric(binary, flatbuffer);
+          final String metricName = flatbuffer.name();
+          if (metricName.equals(Metric.SCAN_OPEN_FILES.getName())) {
+            long files = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getScanTotalOpenFiles().addAndGet(files);
+          } else if (metricName.equals(Metric.SCAN_SCANNED_ENTRIES.getName())) 
{
+            long scanned = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getScansTotalKvScanned().addAndGet(scanned);
+          } else if 
(metricName.equals(Metric.SCAN_QUERY_SCAN_RESULTS.getName())) {
+            long results = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getScansTotalKvReturned().addAndGet(results);
+          } else if 
(metricName.equals(Metric.SCAN_QUERY_SCAN_RESULTS_BYTES.getName())) {
+            long resultSize = getMetricValue(flatbuffer).longValue();
+            
this.instanceOverview.getScansTotalKvReturnedBytes().addAndGet(resultSize);
+          } else if (metricName.equals(Metric.LOW_MEMORY.getName())) {
+            long lowMem = getMetricValue(flatbuffer).longValue();
+            if (lowMem > 0) {
+              this.instanceOverview.getTotalServersLowMem().incrementAndGet();
+            }
+          }
+        }
         break;
       case TABLET_SERVER:
         tservers.computeIfAbsent(response.getResourceGroup(), (rg) -> 
ConcurrentHashMap.newKeySet())
             .add(server);
         updateAggregates(response, totalTServerMetrics, rgTServerMetrics);
+        for (ByteBuffer binary : response.getMetrics()) {
+          flatbuffer = FMetric.getRootAsFMetric(binary, flatbuffer);
+          final String metricName = flatbuffer.name();
+          if (metricName.equals(Metric.SCAN_OPEN_FILES.getName())) {
+            long files = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getScanTotalOpenFiles().addAndGet(files);
+          } else if (metricName.equals(Metric.SCAN_SCANNED_ENTRIES.getName())) 
{
+            long scanned = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getScansTotalKvScanned().addAndGet(scanned);
+          } else if 
(metricName.equals(Metric.SCAN_QUERY_SCAN_RESULTS.getName())) {
+            long results = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getScansTotalKvReturned().addAndGet(results);
+          } else if 
(metricName.equals(Metric.SCAN_QUERY_SCAN_RESULTS_BYTES.getName())) {
+            long resultSize = getMetricValue(flatbuffer).longValue();
+            
this.instanceOverview.getScansTotalKvReturnedBytes().addAndGet(resultSize);
+          } else if (metricName.equals(Metric.TSERVER_HOLD.getName())) {
+            long held = getMetricValue(flatbuffer).longValue();
+            if (held > 0) {
+              this.instanceOverview.ingestNumTServersHolding.incrementAndGet();
+            }
+          } else if 
(metricName.equals(Metric.TSERVER_INGEST_ENTRIES.getName())) {
+            long ingestEntries = getMetricValue(flatbuffer).longValue();
+            
this.instanceOverview.getIngestTotalEntries().addAndGet(ingestEntries);
+          } else if (metricName.equals(Metric.TSERVER_INGEST_BYTES.getName())) 
{
+            long ingestEntriesBytes = getMetricValue(flatbuffer).longValue();
+            
this.instanceOverview.getIngestTotalEntriesBytes().addAndGet(ingestEntriesBytes);
+          } else if (metricName.equals(Metric.TSERVER_MEM_ENTRIES.getName())) {
+            long entriesInMem = getMetricValue(flatbuffer).longValue();
+            
this.instanceOverview.getIngestTotalEntriesInMem().addAndGet(entriesInMem);
+          } else if (metricName.equals(Metric.TSERVER_MINC_QUEUED.getName())) {
+            long mincQueued = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getTotalMinCQueued().addAndGet(mincQueued);
+          } else if (metricName.equals(Metric.TSERVER_MINC_RUNNING.getName())) 
{
+            long mincRunning = getMetricValue(flatbuffer).longValue();
+            this.instanceOverview.getTotalMinCRunning().addAndGet(mincRunning);
+          } else if (metricName.equals(Metric.TSERVER_MINC_TOTAL.getName())) {
+            long mincCompleted = getMetricValue(flatbuffer).longValue();
+            
this.instanceOverview.getTotalMinCCompleted().addAndGet(mincCompleted);
+          } else if (metricName.equals(Metric.LOW_MEMORY.getName())) {
+            long lowMem = getMetricValue(flatbuffer).longValue();
+            if (lowMem > 0) {
+              this.instanceOverview.getTotalServersLowMem().incrementAndGet();
+            }
+          }
+        }
         break;
       default:
         LOG.error("Unhandled server type in fetch metric response: {}", 
response.serverType);
@@ -917,7 +1183,8 @@ public class SystemInformation {
     final SanitizedTabletInformation sti = new 
SanitizedTabletInformation(info);
     tablets.computeIfAbsent(tableId, (t) -> Collections.synchronizedList(new 
ArrayList<>()))
         .add(sti);
-    tables.computeIfAbsent(tableId, (t) -> new 
TableSummary(tableName)).addTablet(sti);
+    tables.computeIfAbsent(tableId, (t) -> new 
TableSummary(tableName)).addTablet(sti,
+        instanceOverview);
     if (sti.getNumWalLogs() > 0) {
       String loc = sti.getLocation().orElse("");
       int idx = loc.indexOf(':');
@@ -959,9 +1226,22 @@ public class SystemInformation {
 
   public void processFateTransactions(List<TransactionStatus> transactions) {
     transactions.forEach(t -> {
+      FateOperation op = t.getFateOp();
+      TStatus status = t.getStatus();
+      if (status == TStatus.SUBMITTED) {
+        instanceOverview.getTotalFateSubmitted().incrementAndGet();
+        if (op == FateOperation.TABLE_BULK_IMPORT2) {
+          instanceOverview.getIngestBulkImportQueued().incrementAndGet();
+        }
+      } else if (status == TStatus.IN_PROGRESS) {
+        instanceOverview.getTotalFateRunning().incrementAndGet();
+        if (op == FateOperation.TABLE_BULK_IMPORT2) {
+          instanceOverview.getIngestBulkImportRunning().incrementAndGet();
+        }
+      }
       fateTransactions
-          .add(new FateTransaction(t.getInstanceType(), t.getFateOp(), 
t.getFateId().getTxUUIDStr(),
-              t.getStatus(), t.getTimeCreated(), t.getHeldLocks(), 
t.getWaitingLocks(),
+          .add(new FateTransaction(t.getInstanceType(), op, 
t.getFateId().getTxUUIDStr(), status,
+              t.getTimeCreated(), t.getHeldLocks(), t.getWaitingLocks(),
               t.getLockRange().isInfinite() ? LockRangeType.FULL : 
LockRangeType.PARTIAL));
     });
   }
@@ -981,6 +1261,7 @@ public class SystemInformation {
       activeScans.add(new Scan(server.toHostPortString(), 
server.getType().name(),
           server.getResourceGroup().canonical(), s.getTableId(), 
s.getScanId(), s.getClient(),
           s.getUser(), s.getState().name(), s.getType().name(), s.getAge(), 
s.getIdleTime()));
+      instanceOverview.getScansTotalInProgress().incrementAndGet();
     });
   }
 
@@ -1266,6 +1547,12 @@ public class SystemInformation {
           break;
       }
     }
+    try {
+      
this.instanceOverview.getNumNamespaces().set(ctx.namespaceOperations().list().size());
+    } catch (AccumuloException | AccumuloSecurityException e1) {
+      LOG.error("Error getting list of namespaces for Monitor overview", e1);
+    }
+    this.instanceOverview.getNumTables().set(this.tables.size());
     deploymentOverview = DeploymentOverview.fromSummary(deployment);
     computeAlertCounts();
     long fetchCycleFinish = System.currentTimeMillis();
@@ -1457,6 +1744,10 @@ public class SystemInformation {
     return this.timing;
   }
 
+  public InstanceOverview getInstanceOverview() {
+    return this.instanceOverview;
+  }
+
   /**
    * Cache a ServersView for the given table and set of servers.
    */
diff --git 
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/functions.js
 
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/functions.js
index b8c265ed4e..dafc9c68c1 100644
--- 
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/functions.js
+++ 
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/functions.js
@@ -43,6 +43,7 @@ const ALERT_CATEGORIES = 'alertCategories';
 const ALERTS = 'alerts';
 const ALERT_COUNTS = 'alertCounts';
 const RECOVERY = 'recovery';
+const INSTANCE_OVERVIEW = 'instanceOverview';
 const SCANS = 'scans';
 const LAST_UPDATE = 'lastUpdate';
 
@@ -793,11 +794,19 @@ function getTserversSummary() {
 }
 
 /**
- * REST GET call for /instance,
+ * REST GET call for /instance/info,
  * stores it on a sessionStorage variable
  */
 function getInstanceInfo() {
-  return getJSONForTable(REST_V2_PREFIX + '/instance', 'instance');
+  return getJSONForTable(REST_V2_PREFIX + '/instance/info', 'instance');
+}
+
+/**
+ * REST GET call for /instance/overview,
+ * stores it on a sessionStorage variable
+ */
+function getInstanceOverview() {
+  return getJSONForTable(REST_V2_PREFIX + '/instance/overview', 
INSTANCE_OVERVIEW);
 }
 
 /**
diff --git 
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/overview.js
 
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/overview.js
index e0f7bc4390..0ceade4d69 100644
--- 
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/overview.js
+++ 
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/overview.js
@@ -35,7 +35,10 @@ $(function () {
  * Makes the REST calls, generates the table with the new information
  */
 function refreshOverview() {
-  refreshDeploymentTables();
+  $.when(getDeployment(), getInstanceOverview()).then(function () {
+    refreshInstanceOverviewTables();
+    refreshDeploymentTables();
+  });
 }
 
 /**
@@ -45,24 +48,95 @@ function refresh() {
   refreshOverview();
 }
 
+function refreshInstanceOverviewTables() {
+  var data = getStoredJson(INSTANCE_OVERVIEW, {});
+
+  renderOverviewList('#instance-overview-list', [
+    ["Namespaces", bigNumberForQuantity(data.numNamespaces || 0)],
+    ["Tables", bigNumberForQuantity(data.numTables || 0)],
+    ["Tablets", bigNumberForQuantity(data.numTablets || 0)],
+    ["Entries", bigNumberForQuantity(data.numKVs || 0)],
+    ["Files", bigNumberForQuantity(data.numFiles || 0)],
+    ["File Size", bigNumberForSize(data.totalFileSize || 0)],
+    ["Dead TServer Tablets", 
bigNumberForQuantity(data.tabletsAssignedToDeadTServers || 0)],
+    ["Suspended Tablets", bigNumberForQuantity(data.totalSuspendedTablets || 
0)],
+    ["Recovery Tablets", bigNumberForQuantity(data.tabletsNeedingRecovery || 
0)],
+    ["Fate Tx Queued", bigNumberForQuantity(data.totalFateSubmitted || 0)],
+    ["Fate Tx Running", bigNumberForQuantity(data.totalFateRunning || 0)],
+    ["Servers Low On Memory", bigNumberForQuantity(data.totalServersLowMem || 
0)]
+  ]);
+
+  renderOverviewList('#ingest-overview-list', [
+    ["Entries", bigNumberForQuantity(data.ingestTotalEntries || 0)],
+    ["Bytes", bigNumberForSize(data.ingestTotalEntriesBytes || 0)],
+    ["Entries In Memory", bigNumberForQuantity(data.ingestTotalEntriesInMem || 
0)],
+    ["TServers Holding For MinC", 
bigNumberForQuantity(data.ingestNumTServersHolding || 0)],
+    ["MinC Queued", bigNumberForQuantity(data.totalMinCQueued || 0)],
+    ["MinC Running", bigNumberForQuantity(data.totalMinCRunning || 0)],
+    ["MinC Completed", bigNumberForQuantity(data.totalMinCCompleted || 0)],
+    ["Bulk Imports Queued", bigNumberForQuantity(data.ingestBulkImportQueued 
|| 0)],
+    ["Bulk Imports Running", bigNumberForQuantity(data.ingestBulkImportRunning 
|| 0)]
+  ]);
+
+  renderOverviewList('#scan-overview-list', [
+    ["Scans In Progress", bigNumberForQuantity(data.scansTotalInProgress || 
0)],
+    ["Entries Scanned", bigNumberForQuantity(data.scansTotalKvScanned || 0)],
+    ["Entries Returned", bigNumberForQuantity(data.scansTotalKvReturned || 0)],
+    ["Bytes Returned", bigNumberForSize(data.scansTotalKvReturnedBytes || 0)],
+    ["Open Files", bigNumberForQuantity(data.scanTotalOpenFiles || 0)]
+  ]);
+
+  renderOverviewList('#compaction-overview-list', [
+    ["MajC Queued", bigNumberForQuantity(data.compactionsQueued || 0)],
+    ["MajC Dequeued", bigNumberForQuantity(data.compactionsDequeued || 0)],
+    ["MajC Running", bigNumberForQuantity(data.compactionsRunning || 0)],
+    ["MajC Failed", bigNumberForQuantity(data.compactionsFailed || 0)]
+  ]);
+}
+
+function renderOverviewList(selector, rows) {
+  var list = $(selector);
+  list.empty();
+
+  list.append(rows.map(function (row) {
+    const name = row[0];
+    const value = row[1];
+    return createOverviewListItem(name, value);
+  }));
+}
+
+function createOverviewListItem(name, rowValue) {
+  var item = $(document.createElement("li"));
+  item.addClass("list-group-item d-flex justify-content-between 
align-items-center");
+
+  var label = $(document.createElement("span"));
+  label.text(name);
+  item.append(label);
+
+  var value = $(document.createElement("strong"));
+  value.addClass("text-end text-nowrap");
+  value.text(rowValue);
+  item.append(value);
+
+  return item;
+}
+
 /**
  * Refreshes the deployment overview tables
  */
 function refreshDeploymentTables() {
-  getDeployment().then(function () {
-    var data = JSON.parse(sessionStorage.deployment);
-    var breakdown = Array.isArray(data.breakdown) ? data.breakdown : [];
-    deploymentBreakdown = breakdown;
-
-    if (breakdown.length === 0) {
-      $('#deploymentWarning').html('<div class="alert alert-warning" 
role="alert">' +
-        'No deployment data is currently available.</div>');
-    } else {
-      $('#deploymentWarning').empty();
-    }
+  var data = JSON.parse(sessionStorage.deployment);
+  var breakdown = Array.isArray(data.breakdown) ? data.breakdown : [];
+  deploymentBreakdown = breakdown;
 
-    renderDeploymentMatrix(breakdown);
-  });
+  if (breakdown.length === 0) {
+    $('#deploymentWarning').html('<div class="alert alert-warning" 
role="alert">' +
+      'No deployment data is currently available.</div>');
+  } else {
+    $('#deploymentWarning').empty();
+  }
+
+  renderDeploymentMatrix(breakdown);
 }
 
 function renderDeploymentMatrix(breakdown) {
diff --git 
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/overview.ftl
 
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/overview.ftl
index ada148dddf..a06db21105 100644
--- 
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/overview.ftl
+++ 
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/templates/overview.ftl
@@ -24,13 +24,75 @@
         </div>
       </div>
       <div class="row d-flex justify-content-center">
-        <div class="col-xs-12" id="deploymentOverview">
-          <div id="deploymentWarning"></div>
-          <div class="deployment-overview-content">
-            <div class="table-responsive">
-              <table id="deployment-table" class="table table-bordered 
table-sm align-middle deployment-matrix-table mb-0">
-                <#include "table_loading.ftl" >
-              </table>
+        <div class="col-xs-12">
+          <div class="row mb-4">
+            <div id="deploymentWarning"></div>
+            <div class="col">
+              <div class="card">
+                <div class="card-header fw-semibold">Server Deployment</div>
+                <div class="card-body">
+                  <div class="deployment-overview-content">
+                    <div class="table-responsive">
+                      <table id="deployment-table" class="table table-bordered 
table-sm align-middle deployment-matrix-table mb-0">
+                        <#include "table_loading.ftl" >
+                      </table>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+
+          <div class="row row-cols-1 row-cols-lg-2 row-cols-xxl-3 g-3 mb-4">
+            <div class="col">
+              <div class="card h-100">
+                <div class="card-header fw-semibold">Instance</div>
+                <ul id="instance-overview-list" class="list-group 
list-group-flush">
+                  <li class="list-group-item text-center">
+                    <div class="spinner-border spinner-border-sm" 
role="status">
+                      <span class="visually-hidden">Loading...</span>
+                    </div>
+                    <span>Loading...</span>
+                  </li>
+                </ul>
+              </div>
+            </div>
+            <div class="col">
+              <div class="card h-100">
+                <div class="card-header fw-semibold">Ingest</div>
+                <ul id="ingest-overview-list" class="list-group 
list-group-flush">
+                  <li class="list-group-item text-center">
+                    <div class="spinner-border spinner-border-sm" 
role="status">
+                      <span class="visually-hidden">Loading...</span>
+                    </div>
+                    <span>Loading...</span>
+                  </li>
+                </ul>
+              </div>
+            </div>
+            <div class="col d-flex flex-column gap-3">
+              <div class="card">
+                <div class="card-header fw-semibold">Scan</div>
+                <ul id="scan-overview-list" class="list-group 
list-group-flush">
+                  <li class="list-group-item text-center">
+                    <div class="spinner-border spinner-border-sm" 
role="status">
+                      <span class="visually-hidden">Loading...</span>
+                    </div>
+                    <span>Loading...</span>
+                  </li>
+                </ul>
+              </div>
+              <div class="card">
+                <div class="card-header fw-semibold">Compaction</div>
+                <ul id="compaction-overview-list" class="list-group 
list-group-flush">
+                  <li class="list-group-item text-center">
+                    <div class="spinner-border spinner-border-sm" 
role="status">
+                      <span class="visually-hidden">Loading...</span>
+                    </div>
+                    <span>Loading...</span>
+                  </li>
+                </ul>
+              </div>
             </div>
           </div>
         </div>

Reply via email to