diff --git a/server/monitor/pom.xml b/server/monitor/pom.xml
index 89a2597f9e8..089502e40c3 100644
--- a/server/monitor/pom.xml
+++ b/server/monitor/pom.xml
@@ -54,10 +54,6 @@
com.github.ben-manes.caffeinecaffeine
-
- com.google.code.gson
- gson
- com.google.guavaguava
@@ -246,26 +242,6 @@
-
- org.codehaus.mojo
- exec-maven-plugin
-
-
- metrics-javascript
-
- java
-
- prepare-package
-
- org.apache.accumulo.monitor.next.views.ColumnJsGen
- compile
-
- ${project.build.directory}/classes/org/apache/accumulo/monitor/resources/js/columns.js
-
-
-
-
- org.apache.maven.pluginsmaven-resources-plugin
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 a0b4971413d..f570d1ecbfa 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
@@ -32,6 +32,7 @@
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.MatrixParam;
import jakarta.ws.rs.NotFoundException;
@@ -66,11 +67,6 @@ public class Endpoints {
*/
private static final String GROUP_PARAM_KEY = "group";
- /**
- * A {@code String} constant representing the supplied server type in path parameter.
- */
- private static final String SERVER_TYPE_KEY = "serverType";
-
/**
* A {@code String} constant representing the supplied tableId in path parameter.
*/
@@ -254,13 +250,15 @@ public Map getScanServerAllMetricSummary() {
@GET
@Path("servers/view")
@Produces(MediaType.APPLICATION_JSON)
- @Description("Returns a UI-ready view model for server processes. Add ';serverType=' to URL")
- public ServersView getServerProcessView(@MatrixParam(SERVER_TYPE_KEY) ServerId.Type serverType) {
+ @Description("Returns a UI-ready table model for server process pages. Add ';table=' to URL")
+ public ServersView getServerProcessView(@MatrixParam("table") ServersView.ServerTable table) {
+ if (table == null) {
+ throw new BadRequestException("A 'table' parameter is required");
+ }
ServersView view =
- monitor.getInformationFetcher().getSummaryForEndpoint().getServerProcessView(serverType);
+ monitor.getInformationFetcher().getSummaryForEndpoint().getServerProcessView(table);
if (view == null) {
- throw new NotFoundException(
- "ServersView object for server type " + serverType.name() + " not found");
+ throw new NotFoundException("ServersView object for table " + table.name() + " not found");
}
return view;
}
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 3c5c4f44758..db9e077f9ed 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
@@ -413,8 +413,8 @@ public Stream stream() {
private final Set configuredCompactionResourceGroups = ConcurrentHashMap.newKeySet();
private final AtomicLong timestamp = new AtomicLong(0);
- private EnumMap> serverMetricsView =
- new EnumMap<>(ServerId.Type.class);
+ private final EnumMap> serverMetricsView =
+ new EnumMap<>(ServersView.ServerTable.class);
private DeploymentOverview deploymentOverview = new DeploymentOverview(0L, List.of());
private final int rgLongRunningCompactionSize;
@@ -658,28 +658,28 @@ public void finish() {
switch (type) {
case COMPACTOR:
compactors.values().forEach(servers::addAll);
- serverMetricsView.put(type, memoize(
- () -> new ServersView(servers, problemHostCount, allMetrics, timestamp.get())));
+ cacheServerProcessView(ServersView.ServerTable.COMPACTORS, servers, problemHostCount);
break;
case GARBAGE_COLLECTOR:
servers.add(gc.get());
- serverMetricsView.put(type, memoize(
- () -> new ServersView(servers, problemHostCount, allMetrics, timestamp.get())));
+ cacheServerProcessView(ServersView.ServerTable.GC_SUMMARY, servers, problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.GC_FILES, servers, problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.GC_WALS, servers, problemHostCount);
break;
case MANAGER:
servers.addAll(managers);
- serverMetricsView.put(type, memoize(
- () -> new ServersView(servers, problemHostCount, allMetrics, timestamp.get())));
+ cacheServerProcessView(ServersView.ServerTable.MANAGERS, servers, problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.MANAGER_FATE, servers, problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.MANAGER_COMPACTIONS, servers,
+ problemHostCount);
break;
case SCAN_SERVER:
sservers.values().forEach(servers::addAll);
- serverMetricsView.put(type, memoize(
- () -> new ServersView(servers, problemHostCount, allMetrics, timestamp.get())));
+ cacheServerProcessView(ServersView.ServerTable.SCAN_SERVERS, servers, problemHostCount);
break;
case TABLET_SERVER:
tservers.values().forEach(servers::addAll);
- serverMetricsView.put(type, memoize(
- () -> new ServersView(servers, problemHostCount, allMetrics, timestamp.get())));
+ cacheServerProcessView(ServersView.ServerTable.TABLET_SERVERS, servers, problemHostCount);
break;
case MONITOR:
default:
@@ -776,8 +776,17 @@ public long getTimestamp() {
return this.timestamp.get();
}
- public ServersView getServerProcessView(ServerId.Type type) {
- Supplier view = this.serverMetricsView.get(type);
+ /**
+ * Cache a ServersView for the given table and set of servers.
+ */
+ private void cacheServerProcessView(ServersView.ServerTable table, Set servers,
+ long problemHostCount) {
+ serverMetricsView.put(table, memoize(() -> new ServersView(servers, problemHostCount,
+ allMetrics, timestamp.get(), ServersView.columnsFor(table))));
+ }
+
+ public ServersView getServerProcessView(ServersView.ServerTable table) {
+ Supplier view = this.serverMetricsView.get(table);
if (view != null) {
return view.get();
}
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ColumnJsGen.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ColumnJsGen.java
deleted file mode 100644
index b2593dc6b48..00000000000
--- a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ColumnJsGen.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.accumulo.monitor.next.views;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.accumulo.core.util.LazySingletons.GSON;
-import static org.apache.accumulo.monitor.next.views.ServersView.ADDR_COL_NAME;
-import static org.apache.accumulo.monitor.next.views.ServersView.RG_COL_NAME;
-import static org.apache.accumulo.monitor.next.views.ServersView.TIME_COL_NAME;
-import static org.apache.accumulo.monitor.next.views.ServersView.TYPE_COL_NAME;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.stream.Collectors;
-
-import org.apache.accumulo.core.metrics.Metric;
-import org.apache.accumulo.core.metrics.Metric.MonitorCssClass;
-
-/**
- * This class generates a map of metric name to column information for the Monitor
- */
-public class ColumnJsGen {
-
- public record ColumnInformation(String header, String description, String classes) {
- };
-
- private static void printHeader(PrintStream out) {
- final String hdr = """
- /*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
- "use strict";
-
- const COLUMN_MAP = new Map([""";
- out.println(hdr);
- }
-
- private static void printMetrics(PrintStream out) {
-
- // Put in tree map to sort metrics by name in the output
- Map output = new TreeMap<>();
- for (Metric m : Metric.values()) {
- MonitorCssClass[] classes = m.getColumnClasses();
- String css =
- Arrays.stream(classes).map(c -> c.getCssClass()).collect(Collectors.joining(" "));
- output.put(m.getName(),
- new ColumnInformation(m.getColumnHeader(), m.getColumnDescription(), css));
- }
-
- // Add non-metric columns that are part of the ServersView
- // object that is returned from the Monitor endpoint
- output.put(ADDR_COL_NAME, new ColumnInformation(ADDR_COL_NAME, "Server Address", "firstcell"));
- output.put(RG_COL_NAME,
- new ColumnInformation(RG_COL_NAME, "Resource Group Name", "resource-group"));
- output.put(TIME_COL_NAME,
- new ColumnInformation(TIME_COL_NAME, "Last Contact Time", "duration"));
- output.put(TYPE_COL_NAME,
- new ColumnInformation(TYPE_COL_NAME, "Server Process Type", "server-type"));
-
- final Set keys = output.keySet();
- final int numKeys = keys.size();
- int counter = 0;
- for (String key : keys) {
- counter++;
- out.println(" [\"%s\", %s]%s".formatted(key, GSON.get().toJson(output.get(key)),
- counter == numKeys ? "" : ","));
-
- }
- }
-
- private static void printFooter(PrintStream out) {
- final String footer = """
- ]);
- """;
- out.println(footer);
- }
-
- public static void main(String args[]) throws IOException {
- if (args.length != 1) {
- throw new IllegalArgumentException(
- "Usage: " + ColumnJsGen.class.getName() + " ");
- }
- try (var printStream = new PrintStream(args[0], UTF_8)) {
- printHeader(printStream);
- printMetrics(printStream);
- printFooter(printStream);
- }
- }
-
-}
diff --git a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ServersView.java b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ServersView.java
index 6b476c4ad3f..4705ae33d8f 100644
--- a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ServersView.java
+++ b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/views/ServersView.java
@@ -19,16 +19,18 @@
package org.apache.accumulo.monitor.next.views;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
import org.apache.accumulo.core.client.admin.servers.ServerId;
+import org.apache.accumulo.core.metrics.Metric;
+import org.apache.accumulo.core.metrics.Metric.MetricDocSection;
import org.apache.accumulo.core.metrics.flatbuffers.FMetric;
import org.apache.accumulo.core.metrics.flatbuffers.FTag;
import org.apache.accumulo.core.process.thrift.MetricResponse;
@@ -48,6 +50,11 @@
* data - an array of objects that can be used for the Data Table data definition
* status - overall status information, counts, warnings, etc.
*
+ *
+ * Each server-process table is identified by {@link ServerTable}. The table-specific metric methods
+ * define the metrics for each table, {@link #columnsFor(ServerTable)} converts those metrics to
+ * column definitions. The frontend uses the returned column definitions to build the table headers
+ * and DataTables column configuration.
*/
public class ServersView {
@@ -59,54 +66,96 @@ public record Status(boolean hasServers, boolean hasProblemServers, boolean hasM
String message) {
}
- public static final String TYPE_COL_NAME = "Server Type";
- public static final String RG_COL_NAME = "Resource Group";
- public static final String ADDR_COL_NAME = "Server Address";
- public static final String TIME_COL_NAME = "Last Contact";
+ /**
+ * Definition of a column to be rendered in the UI
+ */
+ public record Column(String key, String label, String description, String uiClass) {
+ }
+
+ private record ServerMetricRow(ServerId server, MetricResponse response,
+ Map metrics) {
+ }
+
+ /**
+ * Server-process table identifiers accepted by /rest-v2/servers/view. These enum names are used
+ * directly as the frontend table parameter values.
+ */
+ public enum ServerTable {
+ COMPACTORS,
+ GC_SUMMARY,
+ GC_FILES,
+ GC_WALS,
+ MANAGERS,
+ MANAGER_FATE,
+ MANAGER_COMPACTIONS,
+ SCAN_SERVERS,
+ TABLET_SERVERS
+ }
private static final String LEVEL_OK = "OK";
private static final String LEVEL_WARN = "WARN";
+ public static final String RG_COL_KEY = "resourceGroup";
+ public static final String ADDR_COL_KEY = "serverAddress";
+ public static final String TIME_COL_KEY = "lastContact";
+
+ /**
+ * Common columns that are included in every ServersView table
+ */
+ private static final List COMMON_COLUMNS = List.of(
+ new Column(TIME_COL_KEY, "Last Contact",
+ "Time since the server last responded to the monitor", "duration"),
+ new Column(RG_COL_KEY, "Resource Group", "Resource Group", ""),
+ new Column(ADDR_COL_KEY, "Server Address", "Server address", ""));
+
public final List