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 923e2ac79e Consolidate monitor status fetching into a new shared
endpoint (#6333)
923e2ac79e is described below
commit 923e2ac79e63d3edbed1e46e3d0654b706d258c3
Author: Dom G. <[email protected]>
AuthorDate: Tue Apr 28 10:04:32 2026 -0400
Consolidate monitor status fetching into a new shared endpoint (#6333)
* Consolidate monitor status fetching into a new shared endpoint
* Move status calculation into SystemInformation build step
* IDE automated cleanup reccomendations
---
.../apache/accumulo/monitor/next/Endpoints.java | 15 ++
.../accumulo/monitor/next/SystemInformation.java | 100 +++++++++++--
.../accumulo/monitor/next/views/ServersView.java | 26 ++--
.../monitor/rest/status/StatusInformation.java | 52 -------
.../monitor/rest/status/StatusResource.java | 101 -------------
.../accumulo/monitor/resources/js/compactors.js | 3 +-
.../org/apache/accumulo/monitor/resources/js/ec.js | 2 +-
.../accumulo/monitor/resources/js/functions.js | 83 ++++++-----
.../org/apache/accumulo/monitor/resources/js/gc.js | 9 +-
.../accumulo/monitor/resources/js/manager.js | 17 +--
.../apache/accumulo/monitor/resources/js/navbar.js | 159 +++++----------------
.../monitor/resources/js/server_process_common.js | 44 ++++--
.../accumulo/monitor/resources/js/sservers.js | 3 +-
.../accumulo/monitor/resources/js/tservers.js | 39 ++---
14 files changed, 262 insertions(+), 391 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 6346f22d10..a900e1c39e 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
@@ -58,6 +58,7 @@ import
org.apache.accumulo.monitor.next.SystemInformation.TimeOrderedRunningComp
import org.apache.accumulo.monitor.next.deployment.DeploymentOverview;
import org.apache.accumulo.monitor.next.ec.CompactorsSummary;
import org.apache.accumulo.monitor.next.views.ServersView;
+import org.apache.accumulo.monitor.next.views.ServersView.Status;
import io.micrometer.core.instrument.Meter.Id;
import io.micrometer.core.instrument.cumulative.CumulativeDistributionSummary;
@@ -83,6 +84,10 @@ public class Endpoints {
@Inject
private Monitor monitor;
+ public record MonitorStatus(String managerGoalState,
Map<ServerId.Type,Status> componentStatuses,
+ long timestamp) {
+ }
+
private void validateResourceGroup(String resourceGroup) {
if
(monitor.getInformationFetcher().getSummaryForEndpoint().getResourceGroups()
.contains(resourceGroup)) {
@@ -160,6 +165,16 @@ public class Endpoints {
return monitor.getInformationFetcher().getAllMetrics().asMap().get(s);
}
+ @GET
+ @Path("status")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Description("Returns status of server components")
+ public MonitorStatus getStatus() {
+ SystemInformation summary =
monitor.getInformationFetcher().getSummaryForEndpoint();
+ return new MonitorStatus(summary.getManagerGoalState(),
summary.getComponentStatuses(),
+ summary.getTimestamp());
+ }
+
@GET
@Path("instance")
@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 33493e3265..2009068829 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
@@ -33,6 +33,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -69,6 +70,7 @@ import
org.apache.accumulo.monitor.next.deployment.DeploymentOverview;
import org.apache.accumulo.monitor.next.views.ServersView;
import org.apache.accumulo.monitor.next.views.ServersView.Column;
import org.apache.accumulo.monitor.next.views.ServersView.ColumnFactory;
+import org.apache.accumulo.monitor.next.views.ServersView.Status;
import org.apache.accumulo.server.ServerContext;
import org.apache.accumulo.server.conf.TableConfiguration;
import org.apache.accumulo.server.metrics.MetricResponseWrapper;
@@ -427,9 +429,12 @@ public class SystemInformation {
private final Set<String> configuredCompactionResourceGroups =
ConcurrentHashMap.newKeySet();
private final AtomicLong timestamp = new AtomicLong(0);
+ private final EnumMap<ServerId.Type,Status> componentStatuses =
+ new EnumMap<>(ServerId.Type.class);
private final EnumMap<ServersView.ServerTable,Supplier<ServersView>>
serverMetricsView =
new EnumMap<>(ServersView.ServerTable.class);
private DeploymentOverview deploymentOverview = new DeploymentOverview(0L,
List.of());
+ private String managerGoalState;
private final int rgLongRunningCompactionSize;
public SystemInformation(Cache<ServerId,MetricResponse> allMetrics,
ServerContext ctx) {
@@ -465,6 +470,8 @@ public class SystemInformation {
tableCompactions.clear();
groupCompactions.clear();
configuredCompactionResourceGroups.clear();
+ componentStatuses.clear();
+ managerGoalState = null;
serverMetricsView.clear();
}
@@ -726,6 +733,14 @@ public class SystemInformation {
}
timestamp.set(System.currentTimeMillis());
+ componentStatuses.clear();
+ for (final ServerId.Type type : ServerId.Type.values()) {
+ if (type == ServerId.Type.MONITOR) {
+ continue;
+ }
+ componentStatuses.put(type, computeServerStatus(type));
+ }
+ managerGoalState = computeManagerGoalState();
for (Entry<TableId,LongAdder> e : runningCompactionsPerTable.entrySet()) {
TableId tid = e.getKey();
@@ -741,38 +756,34 @@ public class SystemInformation {
.forEach((k, v) -> groupCompactions.add(new CompactionGroupSummary(k,
v.sum())));
for (final ServerId.Type type : ServerId.Type.values()) {
- long problemHostCount =
- problemHosts.stream().filter(serverId -> serverId.getType() ==
type).count();
Set<ServerId> servers = new HashSet<>();
switch (type) {
case COMPACTOR:
compactors.values().forEach(servers::addAll);
- cacheServerProcessView(ServersView.ServerTable.COMPACTORS, servers,
problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.COMPACTORS, servers);
break;
case GARBAGE_COLLECTOR:
servers.add(gc.get());
- cacheServerProcessView(ServersView.ServerTable.GC_SUMMARY, servers,
problemHostCount);
- cacheServerProcessView(ServersView.ServerTable.GC_FILES, servers,
problemHostCount);
- cacheServerProcessView(ServersView.ServerTable.GC_WALS, servers,
problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.GC_SUMMARY, servers);
+ cacheServerProcessView(ServersView.ServerTable.GC_FILES, servers);
+ cacheServerProcessView(ServersView.ServerTable.GC_WALS, servers);
break;
case MANAGER:
servers.addAll(managers);
- cacheServerProcessView(ServersView.ServerTable.MANAGERS, servers,
problemHostCount);
- cacheServerProcessView(ServersView.ServerTable.MANAGER_FATE,
servers, problemHostCount);
- cacheServerProcessView(ServersView.ServerTable.MANAGER_COMPACTIONS,
servers,
- problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.MANAGERS, servers);
+ cacheServerProcessView(ServersView.ServerTable.MANAGER_FATE,
servers);
+ cacheServerProcessView(ServersView.ServerTable.MANAGER_COMPACTIONS,
servers);
ServersView coordinatorQueues =
createCompactionQueueSummary(servers);
serverMetricsView.put(ServersView.ServerTable.COORDINATOR_QUEUES,
memoize(() -> coordinatorQueues));
-
break;
case SCAN_SERVER:
sservers.values().forEach(servers::addAll);
- cacheServerProcessView(ServersView.ServerTable.SCAN_SERVERS,
servers, problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.SCAN_SERVERS,
servers);
break;
case TABLET_SERVER:
tservers.values().forEach(servers::addAll);
- cacheServerProcessView(ServersView.ServerTable.TABLET_SERVERS,
servers, problemHostCount);
+ cacheServerProcessView(ServersView.ServerTable.TABLET_SERVERS,
servers);
break;
case MONITOR:
default:
@@ -794,6 +805,64 @@ public class SystemInformation {
return this.managers;
}
+ public Status getServerStatus(ServerId.Type type) {
+ return componentStatuses.get(type);
+ }
+
+ public Map<ServerId.Type,Status> getComponentStatuses() {
+ return new EnumMap<>(componentStatuses);
+ }
+
+ public String getManagerGoalState() {
+ return managerGoalState;
+ }
+
+ private Status computeServerStatus(ServerId.Type type) {
+ Set<ServerId> servers = getServers(type);
+ long problemHostCount =
+ problemHosts.stream().filter(serverId -> serverId.getType() ==
type).count();
+ int missingMetricCount = (int) servers.stream()
+ .filter(serverId ->
!ServersView.hasMetricData(allMetrics.getIfPresent(serverId))).count();
+ return ServersView.buildStatus(servers.size(), problemHostCount,
missingMetricCount,
+ type == ServerId.Type.TABLET_SERVER);
+ }
+
+ private String computeManagerGoalState() {
+ Integer goalState = managers.stream().map(allMetrics::getIfPresent)
+ .map(response -> ServersView.metricValuesByName(response)
+ .get(Metric.MANAGER_GOAL_STATE.getName()))
+ .filter(value -> value != null && !value.isEmpty())
+ .map(value ->
value.stream().map(SystemInformation::getMetricValue).filter(Objects::nonNull)
+ .map(Number::intValue).min(Comparator.naturalOrder()).orElse(null))
+ .filter(Objects::nonNull).min(Comparator.naturalOrder()).orElse(null);
+
+ return switch (goalState == null ? -1 : goalState) {
+ case 0 -> "CLEAN_STOP";
+ case 1 -> "SAFE_MODE";
+ case 2 -> "NORMAL";
+ default -> null;
+ };
+ }
+
+ private Set<ServerId> getServers(ServerId.Type type) {
+ return switch (type) {
+ case COMPACTOR -> getAll(compactors);
+ case GARBAGE_COLLECTOR -> {
+ final var gcServer = gc.get();
+ yield gcServer == null ? Set.of() : Set.of(gcServer);
+ }
+ case MANAGER -> Set.copyOf(managers);
+ case SCAN_SERVER -> getAll(sservers);
+ case TABLET_SERVER -> getAll(tservers);
+ case MONITOR -> Set.of();
+ };
+ }
+
+ private static Set<ServerId> getAll(Map<String,Set<ServerId>>
groupedServers) {
+ return
groupedServers.values().stream().flatMap(Set::stream).collect(HashSet::new,
Set::add,
+ Set::addAll);
+ }
+
public ServerId getGarbageCollector() {
return this.gc.get();
}
@@ -880,8 +949,9 @@ public class SystemInformation {
/**
* Cache a ServersView for the given table and set of servers.
*/
- private void cacheServerProcessView(ServersView.ServerTable table,
Set<ServerId> servers,
- long problemHostCount) {
+ private void cacheServerProcessView(ServersView.ServerTable table,
Set<ServerId> servers) {
+ long problemHostCount =
+ problemHosts.stream().filter(serverId ->
servers.contains(serverId)).count();
serverMetricsView.put(table, memoize(() -> new ServersView(servers,
problemHostCount,
allMetrics.asMap(), timestamp.get(), ServersView.columnsFor(table))));
}
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 4807155ff5..cb75043752 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
@@ -29,7 +29,6 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@@ -55,7 +54,6 @@ import org.slf4j.LoggerFactory;
* columns - contains an array of column definitions that can be used to
create the table headers
* and Data Table columns
* data - an array of objects that can be used for the Data Table data
definition
- * status - overall status information, counts, warnings, etc.
* </pre>
*
* Each server-process table is identified by {@link ServerTable}. The
table-specific metric methods
@@ -101,6 +99,7 @@ public class ServersView {
}
private static final String LEVEL_OK = "OK";
+ private static final String LEVEL_ERROR = "ERROR";
private static final String LEVEL_WARN = "WARN";
public static final String RG_COL_KEY = "resourceGroup";
@@ -157,14 +156,12 @@ public class ServersView {
public final List<Map<String,Object>> data = new ArrayList<>();
public final List<Column> columns;
- public final Status status;
public final long timestamp;
public ServersView(final Set<ServerId> servers, final long
problemServerCount,
final Map<ServerId,MetricResponse> allMetrics, final long timestamp,
final List<ColumnFactory> requestedColumns) {
- AtomicInteger serversMissingMetrics = new AtomicInteger(0);
// Grab the current metrics for each server
List<ServerMetricRow> serverMetricRows =
servers.stream().sorted().map(serverId -> {
MetricResponse metricResponse = allMetrics.get(serverId);
@@ -172,10 +169,6 @@ public class ServersView {
Map<String,List<FMetric>> serverMetrics =
hasMetricData ? metricValuesByName(metricResponse) : Map.of();
- if (!hasMetricData) {
- serversMissingMetrics.incrementAndGet();
- }
-
return new ServerMetricRow(serverId, metricResponse, serverMetrics);
}).toList();
@@ -189,15 +182,26 @@ public class ServersView {
}
data.add(row);
});
- status = buildStatus(servers.size(), problemServerCount,
serversMissingMetrics.get());
this.timestamp = timestamp;
}
- private static Status buildStatus(int serverCount, long problemServerCount,
+ public static Status buildStatus(int serverCount, long problemServerCount,
int serversMissingMetrics) {
+ return buildStatus(serverCount, problemServerCount, serversMissingMetrics,
false);
+ }
+
+ public static Status buildStatus(int serverCount, long problemServerCount,
+ int serversMissingMetrics, boolean errorWhenAllServersUnavailable) {
final boolean hasServers = serverCount > 0;
final boolean hasProblemServers = problemServerCount > 0;
final boolean hasMissingMetrics = serversMissingMetrics > 0;
+ final boolean allServersUnavailable =
+ errorWhenAllServersUnavailable && hasServers && problemServerCount >=
serverCount;
+
+ if (allServersUnavailable) {
+ return new Status(true, true, hasMissingMetrics, serverCount,
problemServerCount,
+ serversMissingMetrics, LEVEL_ERROR, "ERROR: All servers are
unavailable.");
+ }
List<String> warnings = new ArrayList<>(2);
if (hasProblemServers) {
@@ -217,7 +221,7 @@ public class ServersView {
problemServerCount, serversMissingMetrics, LEVEL_WARN, message);
}
- private static boolean hasMetricData(MetricResponse mr) {
+ public static boolean hasMetricData(MetricResponse mr) {
return mr != null && mr.getMetrics() != null && !mr.getMetrics().isEmpty();
}
diff --git
a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/status/StatusInformation.java
b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/status/StatusInformation.java
deleted file mode 100644
index d35b3214bd..0000000000
---
a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/status/StatusInformation.java
+++ /dev/null
@@ -1,52 +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.rest.status;
-
-/**
- * Generates status of manager, gc, and tservers, as well as log and problem
report
- *
- * @since 2.0.0
- */
-public class StatusInformation {
-
- // Variable names become JSON keys
- public String managerStatus = null;
- public String gcStatus = null;
- public String tServerStatus = null;
- public String coordinatorStatus = null;
-
- public StatusInformation() {}
-
- /**
- * Generate the status report for the services
- *
- * @param managerStatus Status for the manager
- * @param gcStatus Status for the GC
- * @param tServerStatus Status for the tserver
- * @param coordinatorStatus Status for the Compaction Coordinator
- */
- public StatusInformation(String managerStatus, String gcStatus, String
tServerStatus,
- String coordinatorStatus) {
- this.managerStatus = managerStatus;
- this.gcStatus = gcStatus;
- this.tServerStatus = tServerStatus;
- this.coordinatorStatus = coordinatorStatus;
-
- }
-}
diff --git
a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/status/StatusResource.java
b/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/status/StatusResource.java
deleted file mode 100644
index 9ca3042bb5..0000000000
---
a/server/monitor/src/main/java/org/apache/accumulo/monitor/rest/status/StatusResource.java
+++ /dev/null
@@ -1,101 +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.rest.status;
-
-import jakarta.inject.Inject;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-
-import org.apache.accumulo.core.lock.ServiceLockPaths.ServiceLockPath;
-import org.apache.accumulo.core.manager.thrift.ManagerMonitorInfo;
-import org.apache.accumulo.monitor.Monitor;
-
-/**
- * Generates the status for manager, gc, and tservers as well as log and
problem reports
- *
- * @since 2.0.0
- */
-@Path("/status")
-@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
-public class StatusResource {
-
- @Inject
- private Monitor monitor;
-
- public enum Status {
- OK, ERROR, WARN
- }
-
- /**
- * Generates the JSON object with the status
- *
- * @return Status report
- */
- @GET
- public StatusInformation getTables() {
-
- Status managerStatus;
- Status gcStatus;
- Status tServerStatus = Status.ERROR;
- Status coordinatorStatus = monitor.getCoordinatorHost().isPresent() ?
Status.OK : Status.ERROR;
-
- ManagerMonitorInfo mmi = monitor.getMmi();
-
- if (mmi != null) {
- if (monitor.getGcStatus() != null) {
- gcStatus = Status.OK;
- } else {
- gcStatus = Status.ERROR;
- }
-
- ServiceLockPath slp =
monitor.getContext().getServerPaths().getManager(true);
- managerStatus = slp == null ? Status.ERROR : Status.OK;
-
- int tServerUp = mmi.getTServerInfoSize();
- int tServerDown = mmi.getDeadTabletServersSize();
- int tServerBad = mmi.getBadTServersSize();
-
- /*
- * If there are no dead or bad servers and there are tservers up, status
is OK, if there are
- * dead or bad servers and there is at least a tserver up, status is
WARN, otherwise, the
- * status is an error.
- */
- if ((tServerDown > 0 || tServerBad > 0) && tServerUp > 0) {
- tServerStatus = Status.WARN;
- } else if ((tServerDown == 0 || tServerBad == 0) && tServerUp > 0) {
- tServerStatus = Status.OK;
- } else if (tServerUp == 0) {
- tServerStatus = Status.ERROR;
- }
- } else {
- managerStatus = Status.ERROR;
- if (monitor.getGcStatus() == null) {
- gcStatus = Status.ERROR;
- } else {
- gcStatus = Status.OK;
- }
- tServerStatus = Status.ERROR;
- }
-
- return new StatusInformation(managerStatus.toString(), gcStatus.toString(),
- tServerStatus.toString(), coordinatorStatus.toString());
- }
-}
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/compactors.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/compactors.js
index 8ce45315b4..51be0aa1d6 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/compactors.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/compactors.js
@@ -30,8 +30,7 @@ function refresh() {
$(function () {
sessionStorage[COMPACTOR_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refreshServerInformation(getCompactorsView, htmlTable,
COMPACTOR_SERVER_PROCESS_VIEW,
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/ec.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/ec.js
index 9fcda2ec5b..41bcfd4c0f 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/ec.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/ec.js
@@ -321,7 +321,7 @@ function refreshRunningCompactions() {
*/
async function refreshManagerStatus() {
return getStatus().then(function () {
- var managerStatus = JSON.parse(sessionStorage.status).managerStatus;
+ var managerStatus = getComponentStatus(getStoredStatusData(), 'MANAGER');
if (managerStatus === 'ERROR') {
// show banner and hide tables
$('#managerBanner').show();
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 2d4a2c3260..a449eb78d5 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
@@ -23,7 +23,6 @@ var QUANTITY_SUFFIX = ['', 'K', 'M', 'B', 'T', 'e15', 'e18',
'e21'];
// Suffixes for size
var SIZE_SUFFIX = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'];
const REST_V2_PREFIX = contextPath + 'rest-v2';
-const MANAGER_GOAL_STATE_METRIC = 'accumulo.manager.goal.state';
const COMPACTOR_SERVER_PROCESS_VIEW = 'compactorsView';
const COORDINATOR_QUEUE_PROCESS_VIEW = 'coordinatorQueueView';
@@ -35,6 +34,7 @@ const MANAGER_FATE_SERVER_PROCESS_VIEW = 'managersFateView';
const MANAGER_COMPACTION_SERVER_PROCESS_VIEW = 'managersCompactionView';
const SCAN_SERVER_PROCESS_VIEW = 'sserversView';
const TABLET_SERVER_PROCESS_VIEW = 'tserversView';
+var STATUS_REQUEST = null;
const RUNNING_COMPACTIONS_BY_TABLE = 'runningCompactionsByTable';
const RUNNING_COMPACTIONS_BY_GROUP = 'runningCompactionsByGroup';
@@ -399,40 +399,6 @@ function doLoggedPostCall(call, callback, shouldSanitize) {
///// REST Calls /////////////
-/**
- * Gets the manager goal state from the cached manager response, if available.
- *
- * @return {string|null} Manager goal state (CLEAN_STOP, SAFE_MODE, NORMAL) or
null
- */
-function getManagerGoalStateFromSession() {
- var mgrs = getStoredRows(MANAGER_SERVER_PROCESS_VIEW);
- if (!Array.isArray(mgrs) || mgrs.length === 0) {
- console.debug('No manager data in session storage. Returning null.');
- return null;
- }
- // There could be multiple managers that report different goal states.
- // The goal state is stored in ZK, but it's eventually consistent.
- // Use the lowest value seen as the current state for the Monitor
- var goalState = 10;
- $.each(mgrs, function (index, mgr) {
- var stateVal = mgr[MANAGER_GOAL_STATE_METRIC];
- if (stateVal < goalState) {
- goalState = stateVal;
- }
- });
- switch (goalState) {
- case 0:
- return 'CLEAN_STOP';
- case 1:
- return 'SAFE_MODE';
- case 2:
- return 'NORMAL';
- default:
- console.debug('Manager goal state metric not found');
- return null;
- }
-}
-
/**
* REST GET call for the namespaces, stores it on a global variable
*/
@@ -534,13 +500,6 @@ function getTableServers(tableID) {
return getJSONForTable(contextPath + 'rest/tables/' + tableID,
'tableServers');
}
-/**
- * REST GET call for the server status, stores it on a sessionStorage variable
- */
-function getStatus() {
- return getJSONForTable(contextPath + 'rest/status', 'status');
-}
-
/*
* Jquery call to clear all data from cells of a table
*/
@@ -637,6 +596,46 @@ function getMetrics() {
return getJSONForTable(REST_V2_PREFIX + '/metrics', 'metrics');
}
+/**
+ * REST GET call for /status,
+ * stores it on a sessionStorage variable
+ */
+function getStatus() {
+ if (STATUS_REQUEST) {
+ return STATUS_REQUEST;
+ }
+ STATUS_REQUEST = getJSONForTable(REST_V2_PREFIX + '/status', 'status');
+ STATUS_REQUEST.always(function () {
+ STATUS_REQUEST = null;
+ });
+ return STATUS_REQUEST;
+}
+
+function getStoredStatusData() {
+ return sessionStorage.status ? JSON.parse(sessionStorage.status) : null;
+}
+
+function getComponentStatus(statusData, componentType) {
+ if (!statusData || !statusData.componentStatuses) {
+ return 'ERROR';
+ }
+
+ var status = statusData.componentStatuses[componentType];
+ if (!status || !status.hasServers) {
+ return 'ERROR';
+ }
+
+ if (status.level === 'ERROR') {
+ return 'ERROR';
+ }
+
+ if (status.level === 'WARN') {
+ return 'WARN';
+ }
+
+ return 'OK';
+}
+
/**
* REST GET call for /gc,
* stores it on a sessionStorage variable
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/gc.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/gc.js
index 95c515bdac..9e45a435c5 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/gc.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/gc.js
@@ -36,19 +36,16 @@ function refresh() {
$(function () {
sessionStorage[GC_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
sessionStorage[GC_FILE_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
sessionStorage[GC_WAL_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refreshServerInformation(getGcView, htmlTable, GC_SERVER_PROCESS_VIEW,
htmlBanner,
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/manager.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/manager.js
index 0e20a8716d..569cc3c59e 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/manager.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/manager.js
@@ -27,7 +27,8 @@ const htmlTable = '#managers'
const fateHtmlTable = '#managers_fate'
function updateManagerGoalStateBanner() {
- const goalState = getManagerGoalStateFromSession();
+ const status = sessionStorage.status ? JSON.parse(sessionStorage.status) :
null;
+ const goalState = status ? status.managerGoalState : null;
if (goalState === 'SAFE_MODE' || goalState === 'CLEAN_STOP') {
$(managerStateBannerMessage)
.removeClass('alert-danger alert-warning')
@@ -56,7 +57,7 @@ function refreshManagerBanners() {
}
function refresh() {
- $.when(getManagersView(), getManagersFateView()).then(function () {
+ $.when(getManagersView(), getManagersFateView(), getStatus()).then(function
() {
refreshTable(htmlTable, MANAGER_SERVER_PROCESS_VIEW);
refreshTable(fateHtmlTable, MANAGER_FATE_SERVER_PROCESS_VIEW);
refreshManagerBanners();
@@ -64,13 +65,11 @@ function refresh() {
}).fail(function () {
sessionStorage[MANAGER_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
sessionStorage[MANAGER_FATE_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refreshTable(htmlTable, MANAGER_SERVER_PROCESS_VIEW);
refreshTable(fateHtmlTable, MANAGER_FATE_SERVER_PROCESS_VIEW);
@@ -85,13 +84,11 @@ function refresh() {
$(function () {
sessionStorage[MANAGER_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
sessionStorage[MANAGER_FATE_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refresh();
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/navbar.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/navbar.js
index aa4a0d8a5b..ae78c821db 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/navbar.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/navbar.js
@@ -64,126 +64,43 @@ function updateElementStatus(elementId, status) {
* @param {JSON} statusData object containing the status info for the servers
*/
function updateServerNotifications(statusData) {
- const applyStatuses = function (managerGoalState) {
- const isSafeMode = managerGoalState === 'SAFE_MODE';
- const isCleanStop = managerGoalState === 'CLEAN_STOP';
-
- // setting manager status notification
- if (statusData.managerStatus === STATUS.ERROR || isCleanStop) {
- updateElementStatus('managerStatusNotification', STATUS.ERROR);
- } else if (statusData.managerStatus === STATUS.WARN || isSafeMode) {
- updateElementStatus('managerStatusNotification', STATUS.WARN);
- } else if (statusData.managerStatus === STATUS.OK) {
- updateElementStatus('managerStatusNotification', STATUS.OK);
- } else {
- console.error('Unrecognized manager state: ' + statusData.managerStatus
+ '. Could not properly set manager status notification.');
- }
-
- // setting tserver status notification
- if (statusData.tServerStatus === STATUS.OK) {
- updateElementStatus('serverStatusNotification', STATUS.OK);
- } else if (statusData.tServerStatus === STATUS.WARN) {
- updateElementStatus('serverStatusNotification', STATUS.WARN);
- } else {
- updateElementStatus('serverStatusNotification', STATUS.ERROR);
- }
-
- // setting gc status notification
- if (statusData.gcStatus === STATUS.OK) {
- updateElementStatus('gcStatusNotification', STATUS.OK);
- } else {
- updateElementStatus('gcStatusNotification', STATUS.ERROR);
- }
-
- // setting scan server status notification
- if (statusData.sServerStatus === STATUS.ERROR) {
- updateElementStatus('sserverStatusNotification', STATUS.ERROR);
- } else if (statusData.sServerStatus === STATUS.WARN) {
- updateElementStatus('sserverStatusNotification', STATUS.WARN);
- } else if (statusData.sServerStatus === STATUS.OK) {
- updateElementStatus('sserverStatusNotification', STATUS.OK);
- } else {
- console.error('Unrecognized scan server state: ' +
statusData.sServerStatus +
- '. Could not properly set scan server status notification.');
- }
-
- // setting compactor status notification
- if (statusData.compactorStatus === STATUS.OK) {
- updateElementStatus('compactorStatusNotification', STATUS.OK);
- } else {
- updateElementStatus('compactorStatusNotification', STATUS.ERROR);
- }
-
- // Setting overall servers status notification
- if ((statusData.managerStatus === STATUS.OK && !isSafeMode &&
!isCleanStop) &&
- statusData.tServerStatus === STATUS.OK &&
- statusData.gcStatus === STATUS.OK &&
- statusData.sServerStatus === STATUS.OK &&
- statusData.compactorStatus === STATUS.OK) {
- updateElementStatus('statusNotification', STATUS.OK);
- } else if (statusData.managerStatus === STATUS.ERROR || isCleanStop ||
- statusData.tServerStatus === STATUS.ERROR ||
- statusData.gcStatus === STATUS.ERROR ||
- statusData.sServerStatus === STATUS.ERROR ||
- statusData.compactorStatus === STATUS.ERROR) {
- updateElementStatus('statusNotification', STATUS.ERROR);
- } else if (statusData.managerStatus === STATUS.WARN || isSafeMode ||
- statusData.tServerStatus === STATUS.WARN ||
- statusData.gcStatus === STATUS.WARN ||
- statusData.sServerStatus === STATUS.WARN) {
- updateElementStatus('statusNotification', STATUS.WARN);
- }
- };
-
-
- getManagersView().always(function () {
- applyStatuses(getManagerGoalStateFromSession());
- });
-}
-
-/**
- * Updates the scan server notification based on REST v2 status.
- */
-function refreshSserverStatus() {
- return getSserversView().done(function () {
- var view = sessionStorage.sserversView ?
JSON.parse(sessionStorage.sserversView) : null;
- var status = view && view.status ? view.status : null;
- if (!status) {
- sessionStorage.sServerStatus = STATUS.ERROR;
- updateElementStatus('sserverStatusNotification', STATUS.ERROR);
- return;
- }
-
- if (status.hasProblemScanServers === true) {
- sessionStorage.sServerStatus = STATUS.WARN;
- updateElementStatus('sserverStatusNotification', STATUS.WARN);
- } else {
- sessionStorage.sServerStatus = STATUS.OK;
- updateElementStatus('sserverStatusNotification', STATUS.OK);
- }
- }).fail(function () {
- // else, display ERROR when call fails
- sessionStorage.sServerStatus = STATUS.ERROR;
- updateElementStatus('sserverStatusNotification', STATUS.ERROR);
- });
-}
+ const managerGoalState = statusData.managerGoalState;
+ const isSafeMode = managerGoalState === 'SAFE_MODE';
+ const isCleanStop = managerGoalState === 'CLEAN_STOP';
+ const componentStatuses = [
+ getComponentStatus(statusData, 'MANAGER'),
+ getComponentStatus(statusData, 'TABLET_SERVER'),
+ getComponentStatus(statusData, 'GARBAGE_COLLECTOR'),
+ getComponentStatus(statusData, 'SCAN_SERVER'),
+ getComponentStatus(statusData, 'COMPACTOR')
+ ];
+ const managerStatus = componentStatuses[0];
+
+ // setting manager status notification
+ if (managerStatus === STATUS.ERROR || isCleanStop) {
+ updateElementStatus('managerStatusNotification', STATUS.ERROR);
+ } else if (managerStatus === STATUS.WARN || isSafeMode) {
+ updateElementStatus('managerStatusNotification', STATUS.WARN);
+ } else if (managerStatus === STATUS.OK) {
+ updateElementStatus('managerStatusNotification', STATUS.OK);
+ } else {
+ console.error('Unrecognized manager state: ' + managerStatus +
+ '. Could not properly set manager status notification.');
+ }
-/**
- * Sets compactor menu status LED notification to OK if any compactors exist,
else ERROR
- */
-function refreshCompactorStatus() {
- return $.getJSON(REST_V2_PREFIX + '/ec/compactors').done(function (data) {
- if (Number(data?.numCompactors) > 0) {
- sessionStorage.compactorStatus = STATUS.OK;
- updateElementStatus('compactorStatusNotification', STATUS.OK);
- } else {
- sessionStorage.compactorStatus = STATUS.ERROR;
- updateElementStatus('compactorStatusNotification', STATUS.ERROR);
- }
- }).fail(function () {
- sessionStorage.compactorStatus = STATUS.ERROR;
- updateElementStatus('compactorStatusNotification', STATUS.ERROR);
- });
+ updateElementStatus('serverStatusNotification', componentStatuses[1]);
+ updateElementStatus('gcStatusNotification', componentStatuses[2]);
+ updateElementStatus('sserverStatusNotification', componentStatuses[3]);
+ updateElementStatus('compactorStatusNotification', componentStatuses[4]);
+
+ // Setting overall servers status notification
+ if (!isSafeMode && !isCleanStop && componentStatuses.every(status => status
=== STATUS.OK)) {
+ updateElementStatus('statusNotification', STATUS.OK);
+ } else if (isCleanStop || componentStatuses.some(status => status ===
STATUS.ERROR)) {
+ updateElementStatus('statusNotification', STATUS.ERROR);
+ } else if (isSafeMode || componentStatuses.some(status => status ===
STATUS.WARN)) {
+ updateElementStatus('statusNotification', STATUS.WARN);
+ }
}
/**
@@ -197,7 +114,7 @@ $(function () {
* Makes the REST call for the server status, generates the sidebar with the
new information
*/
function refreshSidebar() {
- $.when(getStatus(), refreshSserverStatus(),
refreshCompactorStatus()).always(function () {
+ getStatus().always(function () {
refreshSideBarNotifications();
});
}
@@ -218,8 +135,6 @@ function refreshSideBarNotifications() {
if (!statusData) {
return;
}
- statusData.sServerStatus = sessionStorage.sServerStatus || STATUS.OK;
- statusData.compactorStatus = sessionStorage.compactorStatus || STATUS.OK;
updateServerNotifications(statusData);
}
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server_process_common.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server_process_common.js
index fd53c76b6c..b35c694951 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server_process_common.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/server_process_common.js
@@ -48,8 +48,6 @@
* "uiClass": ""
* }
* ],
- * "status": {
- * },
* timestamp: long
* }
*
@@ -98,11 +96,36 @@ function getStoredRows(storageKey) {
}
/**
- * This function returns the stats object from the entire response
+ * This function returns the status object for a server process table.
*/
function getStoredStatus(storageKey) {
- var view = getStoredView(storageKey);
- return view.status || null;
+ var status = sessionStorage.status ? JSON.parse(sessionStorage.status) :
null;
+ var statusKey = getComponentStatusKey(storageKey);
+ if (!status || !status.componentStatuses || !statusKey) {
+ return null;
+ }
+ return status.componentStatuses[statusKey] || null;
+}
+
+function getComponentStatusKey(storageKey) {
+ switch (storageKey) {
+ case COMPACTOR_SERVER_PROCESS_VIEW:
+ return 'COMPACTOR';
+ case GC_SERVER_PROCESS_VIEW:
+ case GC_FILE_SERVER_PROCESS_VIEW:
+ case GC_WAL_SERVER_PROCESS_VIEW:
+ return 'GARBAGE_COLLECTOR';
+ case MANAGER_SERVER_PROCESS_VIEW:
+ case MANAGER_FATE_SERVER_PROCESS_VIEW:
+ case MANAGER_COMPACTION_SERVER_PROCESS_VIEW:
+ return 'MANAGER';
+ case SCAN_SERVER_PROCESS_VIEW:
+ return 'SCAN_SERVER';
+ case TABLET_SERVER_PROCESS_VIEW:
+ return 'TABLET_SERVER';
+ default:
+ return null;
+ }
}
/**
@@ -176,6 +199,12 @@ function refreshBanner(banner, bannerMsg, status) {
.addClass('alert-warning')
.text(status.message || 'WARN: server status warning.');
$(banner).show();
+ } else if (status && status.level === 'ERROR') {
+ $(bannerMsg)
+ .removeClass('alert-warning')
+ .addClass('alert-danger')
+ .text(status.message || 'ERROR: server status error.');
+ $(banner).show();
} else {
$(banner).hide();
}
@@ -200,14 +229,13 @@ function showBannerError(banner, bannerMsg) {
* bannerMsg - reference to the HTML object that is the banner
*/
function refreshServerInformation(callback, table, storageKey, banner,
bannerMsg) {
- callback().then(function () {
+ $.when(callback(), getStatus()).then(function () {
refreshTable(table, storageKey);
refreshBanner(banner, bannerMsg, getStoredStatus(storageKey));
}).fail(function () {
sessionStorage[storageKey] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refreshTable(table, storageKey);
showBannerError(banner, bannerMsg);
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/sservers.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/sservers.js
index 5107b01e97..cf2a118111 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/sservers.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/sservers.js
@@ -30,8 +30,7 @@ function refresh() {
$(function () {
sessionStorage[SCAN_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refreshServerInformation(getSserversView, htmlTable,
SCAN_SERVER_PROCESS_VIEW, htmlBanner,
diff --git
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/tservers.js
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/tservers.js
index b222870c1b..80259f8f87 100644
---
a/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/tservers.js
+++
b/server/monitor/src/main/resources/org/apache/accumulo/monitor/resources/js/tservers.js
@@ -63,27 +63,29 @@ function refreshRecoveryList() {
* Show a page banner that matches the tablet server status shown in the
navbar.
*/
function refreshTServersBanner() {
- var statusData = JSON.parse(sessionStorage.status);
- if (statusData.managerStatus === 'ERROR') {
- $('#tserversManagerBanner').show();
- $('#tserversWarnBanner').hide();
- $('#tserversErrorBanner').hide();
- $('#tservers_wrapper').hide();
- $('#recovery-caption').hide();
- } else {
- $('#tserversManagerBanner').hide();
- $('#tservers_wrapper').show();
- if (statusData.tServerStatus === 'ERROR') {
+ getStatus().then(function () {
+ var statusData = getStoredStatusData();
+ if (getComponentStatus(statusData, 'MANAGER') === 'ERROR') {
+ $('#tserversManagerBanner').show();
$('#tserversWarnBanner').hide();
- $('#tserversErrorBanner').show();
- } else if (statusData.tServerStatus === 'WARN') {
- $('#tserversWarnBanner').show();
$('#tserversErrorBanner').hide();
+ $('#tservers_wrapper').hide();
+ $('#recovery-caption').hide();
} else {
- $('#tserversWarnBanner').hide();
- $('#tserversErrorBanner').hide();
+ $('#tserversManagerBanner').hide();
+ $('#tservers_wrapper').show();
+ if (getComponentStatus(statusData, 'TABLET_SERVER') === 'ERROR') {
+ $('#tserversWarnBanner').hide();
+ $('#tserversErrorBanner').show();
+ } else if (getComponentStatus(statusData, 'TABLET_SERVER') === 'WARN') {
+ $('#tserversWarnBanner').show();
+ $('#tserversErrorBanner').hide();
+ } else {
+ $('#tserversWarnBanner').hide();
+ $('#tserversErrorBanner').hide();
+ }
}
- }
+ });
}
@@ -100,8 +102,7 @@ $(function () {
sessionStorage[TABLET_SERVER_PROCESS_VIEW] = JSON.stringify({
data: [],
- columns: [],
- status: null
+ columns: []
});
refreshServerInformation(getTserversView, htmlTable,
TABLET_SERVER_PROCESS_VIEW, htmlBanner,