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 8f252bbdad Migrate Scan Server monitor page to use backend-derived DTO
(#6165)
8f252bbdad is described below
commit 8f252bbdada829c6a486138ab59268ab17d2c7a6
Author: Dom G. <[email protected]>
AuthorDate: Wed Mar 4 12:24:53 2026 -0500
Migrate Scan Server monitor page to use backend-derived DTO (#6165)
* replaces the complex javascript parsing of raw metrics with a
backend-built Data Transfer Object (DTO) which is consumed by the ScanServer
monitor page UI.
---
.../apache/accumulo/monitor/next/Endpoints.java | 15 +-
.../accumulo/monitor/next/SystemInformation.java | 15 ++
.../monitor/next/sservers/ScanServerView.java | 183 ++++++++++++++++
.../accumulo/monitor/resources/js/functions.js | 17 +-
.../apache/accumulo/monitor/resources/js/navbar.js | 31 +--
.../accumulo/monitor/resources/js/sservers.js | 236 ++++-----------------
6 files changed, 264 insertions(+), 233 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 8eeecd71c3..4785dabcf0 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
@@ -60,6 +60,7 @@ import org.apache.accumulo.monitor.next.ec.CompactorsSummary;
import org.apache.accumulo.monitor.next.ec.CoordinatorSummary;
import org.apache.accumulo.monitor.next.ec.RunningCompactionDetails;
import org.apache.accumulo.monitor.next.ec.RunningCompactionsSummary;
+import org.apache.accumulo.monitor.next.sservers.ScanServerView;
import io.micrometer.core.instrument.Meter.Id;
import io.micrometer.core.instrument.cumulative.CumulativeDistributionSummary;
@@ -238,7 +239,7 @@ public class Endpoints {
@GET
@Path("sservers/detail/{" + GROUP_PARAM_KEY + "}")
@Produces(MediaType.APPLICATION_JSON)
- @Description("Returns the metric responses for the ScanServers in the
supplied resource group")
+ @Description("Returns raw metric responses for the ScanServers in the
supplied resource group")
public Collection<MetricResponse>
getScanServers(@PathParam(GROUP_PARAM_KEY) String resourceGroup) {
validateResourceGroup(resourceGroup);
@@ -253,7 +254,7 @@ public class Endpoints {
@GET
@Path("sservers/summary/{" + GROUP_PARAM_KEY + "}")
@Produces(MediaType.APPLICATION_JSON)
- @Description("Returns an aggregate view of the metric responses for the
ScanServers in the supplied resource group")
+ @Description("Returns an aggregate raw metric summary for the ScanServers in
the supplied resource group (diagnostic endpoint)")
public Map<Id,CumulativeDistributionSummary>
getScanServerResourceGroupMetricSummary(@PathParam(GROUP_PARAM_KEY)
String resourceGroup) {
validateResourceGroup(resourceGroup);
@@ -268,11 +269,19 @@ public class Endpoints {
@GET
@Path("sservers/summary")
@Produces(MediaType.APPLICATION_JSON)
- @Description("Returns an aggregate view of the metric responses for all
ScanServers")
+ @Description("Returns an aggregate raw metric summary for all ScanServers
(diagnostic endpoint)")
public Map<Id,CumulativeDistributionSummary> getScanServerAllMetricSummary()
{
return
monitor.getInformationFetcher().getSummaryForEndpoint().getSServerAllMetricSummary();
}
+ @GET
+ @Path("sservers/view")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Description("Returns a UI-ready view model for the Scan Server status page")
+ public ScanServerView getScanServerPageView() {
+ return
monitor.getInformationFetcher().getSummaryForEndpoint().getScanServerView();
+ }
+
@GET
@Path("tservers/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 89297e98bf..7e2037530d 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
@@ -23,6 +23,7 @@ import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -51,6 +52,7 @@ import org.apache.accumulo.core.metrics.flatbuffers.FMetric;
import org.apache.accumulo.core.metrics.flatbuffers.FTag;
import org.apache.accumulo.core.process.thrift.MetricResponse;
import org.apache.accumulo.core.spi.balancer.TableLoadBalancer;
+import org.apache.accumulo.monitor.next.sservers.ScanServerView;
import org.apache.accumulo.server.ServerContext;
import org.apache.accumulo.server.conf.TableConfiguration;
import org.apache.accumulo.server.metrics.MetricResponseWrapper;
@@ -348,6 +350,7 @@ public class SystemInformation {
private final Set<String> suggestions = new ConcurrentSkipListSet<>();
private long timestamp = 0;
+ private ScanServerView scanServerView;
public SystemInformation(Cache<ServerId,MetricResponse> allMetrics,
ServerContext ctx) {
this.allMetrics = allMetrics;
@@ -371,6 +374,7 @@ public class SystemInformation {
tablets.clear();
deployment.clear();
suggestions.clear();
+ scanServerView = null;
}
private void updateAggregates(final MetricResponse response,
@@ -510,7 +514,14 @@ public class SystemInformation {
+ " group " + balancerRG + ", but there are no TabletServers.");
}
}
+ Set<ServerId> scanServers = new HashSet<>();
+ sservers.values().forEach(scanServers::addAll);
+ int problemScanServerCount = (int) problemHosts.stream()
+ .filter(serverId -> serverId.getType() ==
ServerId.Type.SCAN_SERVER).count();
+ var responses = allMetrics.getAllPresent(scanServers).values();
timestamp = System.currentTimeMillis();
+ scanServerView = ScanServerView.fromMetrics(responses, scanServers.size(),
+ problemScanServerCount, timestamp);
}
public Set<String> getResourceGroups() {
@@ -617,4 +628,8 @@ public class SystemInformation {
return this.timestamp;
}
+ public ScanServerView getScanServerView() {
+ return this.scanServerView;
+ }
+
}
diff --git
a/server/monitor/src/main/java/org/apache/accumulo/monitor/next/sservers/ScanServerView.java
b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/sservers/ScanServerView.java
new file mode 100644
index 0000000000..a212424877
--- /dev/null
+++
b/server/monitor/src/main/java/org/apache/accumulo/monitor/next/sservers/ScanServerView.java
@@ -0,0 +1,183 @@
+/*
+ * 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.sservers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import org.apache.accumulo.core.metrics.Metric;
+import org.apache.accumulo.core.metrics.flatbuffers.FMetric;
+import org.apache.accumulo.core.metrics.flatbuffers.FTag;
+import org.apache.accumulo.core.process.thrift.MetricResponse;
+import org.apache.accumulo.server.metrics.MetricResponseWrapper;
+
+/**
+ * Data Transfer Object (DTO) for the Monitor Scan Servers page. It transforms
backend metrics into
+ * a UI-ready JSON response consumed by the frontend; each record component is
serialized as a JSON
+ * field.
+ */
+public record ScanServerView(long lastUpdate, List<Row> servers, Status
status) {
+
+ /**
+ * all the data needed for a row in the table in monitor
+ */
+ public record Row(String host, String resourceGroup, long lastContact,
boolean metricsAvailable,
+ Number openFiles, Number queries, Number scannedEntries, Number
queryResults,
+ Number queryResultBytes, Number busyTimeouts, Number
reservationConflicts,
+ Number zombieThreads, Number serverIdle, Number lowMemoryDetected,
+ Number scansPausedForMemory, Number scansReturnedEarlyForMemory) {
+ }
+
+ /**
+ * all the data needed for the ScanServer status indicator(s)
+ */
+ public record Status(boolean hasScanServers, boolean hasProblemScanServers,
+ boolean hasMissingMetrics, int scanServerCount, int
problemScanServerCount,
+ long missingMetricServerCount, String level, String message) {
+ }
+
+ private static final String LEVEL_OK = "OK";
+ private static final String LEVEL_WARN = "WARN";
+
+ public static ScanServerView fromMetrics(Collection<MetricResponse>
responses,
+ int scanServerCount, int problemScanServerCount, long snapshotTime) {
+ var rows = rows(responses, snapshotTime);
+ Status status = buildStatus(scanServerCount, problemScanServerCount, rows);
+ return new ScanServerView(snapshotTime, rows, status);
+ }
+
+ private static List<Row> rows(Collection<MetricResponse> responses, long
nowMs) {
+ if (responses == null) {
+ return List.of();
+ }
+ return responses.stream().map(response -> toRow(response, nowMs))
+
.sorted(Comparator.comparing(Row::resourceGroup).thenComparing(Row::host)).toList();
+ }
+
+ private static Status buildStatus(int scanServerCount, int
problemScanServerCount,
+ List<Row> rows) {
+ long missingMetricServerCount = rows.stream().filter(row ->
!row.metricsAvailable()).count();
+ boolean hasScanServers = scanServerCount > 0;
+ boolean hasProblemScanServers = problemScanServerCount > 0;
+ boolean hasMissingMetrics = missingMetricServerCount > 0;
+
+ List<String> warnings = new ArrayList<>(2);
+ if (hasProblemScanServers) {
+ warnings.add("one or more scan servers are unavailable");
+ }
+ if (hasMissingMetrics) {
+ warnings.add("ScanServer metrics are not present (are metrics
enabled?)");
+ }
+
+ if (warnings.isEmpty()) {
+ // no warnings, set status to OK
+ return new Status(hasScanServers, false, false, scanServerCount, 0, 0,
LEVEL_OK, null);
+ }
+
+ final String message = "WARN: " + String.join("; ", warnings) + ".";
+ return new Status(hasScanServers, hasProblemScanServers,
hasMissingMetrics, scanServerCount,
+ problemScanServerCount, missingMetricServerCount, LEVEL_WARN, message);
+ }
+
+ private static Row toRow(MetricResponse response, long nowMs) {
+ if (response == null) {
+ return new Row(null, null, 0, false, null, null, null, null, null, null,
null, null, null,
+ null, null, null);
+ }
+
+ var values = metricValuesByName(response);
+ var openFiles = values.get(Metric.SCAN_OPEN_FILES.getName());
+ var queries = values.get(Metric.SCAN_QUERIES.getName());
+ var scannedEntries = values.get(Metric.SCAN_SCANNED_ENTRIES.getName());
+ var queryResults = values.get(Metric.SCAN_QUERY_SCAN_RESULTS.getName());
+ var queryResultBytes =
values.get(Metric.SCAN_QUERY_SCAN_RESULTS_BYTES.getName());
+ var busyTimeouts = values.get(Metric.SCAN_BUSY_TIMEOUT_COUNT.getName());
+ var reservationConflicts =
values.get(Metric.SCAN_RESERVATION_CONFLICT_COUNTER.getName());
+ var zombieThreads = values.get(Metric.SCAN_ZOMBIE_THREADS.getName());
+ var serverIdle = values.get(Metric.SERVER_IDLE.getName());
+ var lowMemoryDetected = values.get(Metric.LOW_MEMORY.getName());
+ var scansPausedForMemory =
values.get(Metric.SCAN_PAUSED_FOR_MEM.getName());
+ var scansReturnedEarlyForMemory =
values.get(Metric.SCAN_RETURN_FOR_MEM.getName());
+
+ boolean allMetricsPresent =
+ Stream.of(openFiles, queries, scannedEntries, queryResults,
queryResultBytes, busyTimeouts,
+ reservationConflicts, zombieThreads, serverIdle, lowMemoryDetected,
+ scansPausedForMemory,
scansReturnedEarlyForMemory).allMatch(Objects::nonNull);
+
+ long lastContact = Math.max(0, nowMs - response.getTimestamp());
+
+ return new Row(response.getServer(), response.getResourceGroup(),
lastContact,
+ allMetricsPresent, openFiles, queries, scannedEntries, queryResults,
queryResultBytes,
+ busyTimeouts, reservationConflicts, zombieThreads, serverIdle,
lowMemoryDetected,
+ scansPausedForMemory, scansReturnedEarlyForMemory);
+ }
+
+ private static Map<String,Number> metricValuesByName(MetricResponse
response) {
+ var values = new HashMap<String,Number>();
+ if (response == null || response.getMetrics() == null ||
response.getMetrics().isEmpty()) {
+ return values;
+ }
+
+ for (var binary : response.getMetrics()) {
+ var metric = FMetric.getRootAsFMetric(binary);
+ var metricStatistic = extractStatistic(metric);
+ if (metricStatistic == null || metricStatistic.equals("value")
+ || metricStatistic.equals("count")) {
+ values.putIfAbsent(metric.name(), metricNumericValue(metric));
+ }
+ }
+ return values;
+ }
+
+ private static String extractStatistic(FMetric metric) {
+ for (int i = 0; i < metric.tagsLength(); i++) {
+ FTag tag = metric.tags(i);
+ if (MetricResponseWrapper.STATISTIC_TAG.equals(tag.key())) {
+ return normalizeStatistic(tag.value());
+ }
+ }
+ return null;
+ }
+
+ private static String normalizeStatistic(String statistic) {
+ if (statistic == null) {
+ return null;
+ }
+ return statistic.toLowerCase();
+ }
+
+ private static Number metricNumericValue(FMetric metric) {
+ if (metric.ivalue() != 0) {
+ return metric.ivalue();
+ }
+ if (metric.lvalue() != 0L) {
+ return metric.lvalue();
+ }
+ if (metric.dvalue() != 0.0d) {
+ return metric.dvalue();
+ }
+ return 0;
+ }
+}
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 44b8305719..2d7457f01e 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
@@ -586,14 +586,6 @@ function getCompactorsSummary(group) {
return getJSONForTable(url, sessionDataVar);
}
-/**
- * REST GET call for /sservers/summary,
- * stores it on a sessionStorage variable
- */
-function getSserversSummary() {
- return getJSONForTable(REST_V2_PREFIX + '/sservers/summary',
'sserversSummary');
-}
-
/**
* REST GET call for /tables/{name}/tablets,
* stores it on a sessionStorage variable
@@ -657,14 +649,11 @@ function getDeployment() {
}
/**
- * REST GET call for /sservers/summary/{group},
+ * REST GET call for /sservers/view,
* stores it on a sessionStorage variable
- * @param {string} group Group name
*/
-function getSserversSummaryGroup(group) {
- const url = `${REST_V2_PREFIX}/sservers/summary/${group}`;
- const sessionDataVar = `sserversSummary_${group}`;
- return getJSONForTable(url, sessionDataVar);
+function getSserversView() {
+ return getJSONForTable(REST_V2_PREFIX + '/sservers/view', 'sserversView');
}
/**
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 23dc40e9b7..206302b4a6 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
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-/*global REST_V2_PREFIX */
+/*global getSserversView */
"use strict";
/**
@@ -138,27 +138,18 @@ function updateServerNotifications(statusData) {
* Updates the scan server notification based on REST v2 metrics status.
*/
function refreshSserverStatus() {
- return $.when(
- $.getJSON(REST_V2_PREFIX + '/sservers/summary'),
- $.getJSON(REST_V2_PREFIX + '/problems')
- ).done(function (summaryResp, problemsResp) {
- var summary = summaryResp && summaryResp[0] ? summaryResp[0] : {};
- var problems = problemsResp && problemsResp[0] ? problemsResp[0] : [];
-
- var hasSservers = summary && Object.keys(summary).length > 0;
- var hasProblemSserver = problems.some(function (problem) {
- return problem.type === 'SCAN_SERVER' || problem.serverType ===
'SCAN_SERVER';
- });
-
- // 1) Display WARN when problem entries show any scan servers
- if (hasProblemSserver) {
+ 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.level === STATUS.WARN) {
sessionStorage.sServerStatus = STATUS.WARN;
updateElementStatus('sserverStatusNotification', STATUS.WARN);
- // 2) Display OK when there are no scan servers reported
- } else if (!hasSservers) {
- sessionStorage.sServerStatus = STATUS.OK;
- updateElementStatus('sserverStatusNotification', STATUS.OK);
- // 3) Display OK when scan servers exist and no problems
} else {
sessionStorage.sServerStatus = STATUS.OK;
updateElementStatus('sserverStatusNotification', STATUS.OK);
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 6b8ac2ae83..2ba580d472 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
@@ -19,227 +19,68 @@
/* JSLint global definitions */
/*global
$, sessionStorage, timeDuration, bigNumberForQuantity, bigNumberForSize,
ajaxReloadTable,
- getGroups, getSserversDetail, REST_V2_PREFIX
+ getSserversView
*/
"use strict";
var sserversTable;
-var SSERVERS_SESSION_KEY = 'sservers';
+var SSERVERS_VIEW_SESSION_KEY = 'sserversView';
-var METRICS = {
- OPEN_FILES: 'accumulo.scan.files.open',
- QUERIES: 'accumulo.scan.queries',
- SCANNED_ENTRIES: 'accumulo.scan.query.scanned.entries',
- QUERY_RESULTS: 'accumulo.scan.query.results',
- QUERY_RESULTS_BYTES: 'accumulo.scan.query.results.bytes',
- BUSY_TIMEOUTS: 'accumulo.scan.busy.timeout.count',
- RESERVATION_CONFLICTS: 'accumulo.scan.reservation.conflict.count',
- ZOMBIE_THREADS: 'accumulo.scan.zombie.threads',
- SERVER_IDLE: 'accumulo.server.idle',
- LOW_MEMORY_DETECTED: 'accumulo.detected.low.memory',
- SCANS_PAUSED_FOR_MEMORY: 'accumulo.scan.paused.for.memory',
- SCANS_RETURNED_EARLY_FOR_MEMORY: 'accumulo.scan.return.early.for.memory'
-};
-
-function normalizeStatistic(value) {
- if (value === null || value === undefined) {
- return null;
- }
- return String(value).toLowerCase();
-}
-
-function extractStatistic(tags) {
- if (!tags) {
- return null;
- }
- for (var i = 0; i < tags.length; i++) {
- var tag = tags[i];
- for (var key in tag) {
- if (Object.prototype.hasOwnProperty.call(tag, key) && key ===
'statistic') {
- return normalizeStatistic(tag[key]);
- }
- }
- }
- return null;
-}
-
-function getMetricValue(metrics, name, statistic) {
- if (!metrics) {
- console.warn('Missing scan-server metrics array when reading metric: ' +
name);
- return 0;
- }
- var desiredStatistic = normalizeStatistic(statistic);
- for (var i = 0; i < metrics.length; i++) {
- var metric = metrics[i];
- if (metric.name !== name) {
- continue;
- }
- var metricStatistic = extractStatistic(metric.tags);
- if (!desiredStatistic) {
- if (metricStatistic === null || metricStatistic === 'value' ||
metricStatistic === 'count') {
- return metric.value;
- }
- } else if (metricStatistic === desiredStatistic) {
- return metric.value;
- }
- }
- console.warn('Missing expected scan-server metric: ' + name);
- return 0;
-}
-
-function buildScanServerRow(response) {
- var metrics = response.metrics || [];
- var hasMetrics = Array.isArray(metrics) && metrics.length > 0;
- var row = {
- host: response.host,
- resourceGroup: response.resourceGroup,
- lastContact: Date.now() - response.timestamp
- };
-
- if (!hasMetrics) {
- row.openFiles = null;
- row.queries = null;
- row.scannedEntries = null;
- row.queryResults = null;
- row.queryResultBytes = null;
- row.busyTimeouts = null;
- row.reservationConflicts = null;
- row.zombieThreads = null;
- row.serverIdle = null;
- row.lowMemoryDetected = null;
- row.scansPausedForMemory = null;
- row.scansReturnedEarlyForMemory = null;
- return row;
+function getStoredView() {
+ if (!sessionStorage[SSERVERS_VIEW_SESSION_KEY]) {
+ return {};
}
-
- row.openFiles = getMetricValue(metrics, METRICS.OPEN_FILES);
- row.queries = getMetricValue(metrics, METRICS.QUERIES);
- row.scannedEntries = getMetricValue(metrics, METRICS.SCANNED_ENTRIES);
- row.queryResults = getMetricValue(metrics, METRICS.QUERY_RESULTS);
- row.queryResultBytes = getMetricValue(metrics, METRICS.QUERY_RESULTS_BYTES);
- row.busyTimeouts = getMetricValue(metrics, METRICS.BUSY_TIMEOUTS);
- row.reservationConflicts = getMetricValue(metrics,
METRICS.RESERVATION_CONFLICTS);
- row.zombieThreads = getMetricValue(metrics, METRICS.ZOMBIE_THREADS);
- row.serverIdle = getMetricValue(metrics, METRICS.SERVER_IDLE);
- row.lowMemoryDetected = getMetricValue(metrics, METRICS.LOW_MEMORY_DETECTED);
- row.scansPausedForMemory = getMetricValue(metrics,
METRICS.SCANS_PAUSED_FOR_MEMORY);
- row.scansReturnedEarlyForMemory = getMetricValue(metrics,
METRICS.SCANS_RETURNED_EARLY_FOR_MEMORY);
- return row;
+ return JSON.parse(sessionStorage[SSERVERS_VIEW_SESSION_KEY]);
}
function getStoredRows() {
- if (!sessionStorage[SSERVERS_SESSION_KEY]) {
+ var view = getStoredView();
+ if (!Array.isArray(view.servers)) {
return [];
}
- return JSON.parse(sessionStorage[SSERVERS_SESSION_KEY]).servers;
+ return view.servers;
}
-function setStoredRows(rows) {
- sessionStorage[SSERVERS_SESSION_KEY] = JSON.stringify({
- servers: rows
- });
-}
-
-function buildRowsFromSessionStorage(groups) {
- var rows = [];
- var metricsUnavailable = false;
-
- groups.forEach(function (group) {
- var sessionKey = 'sserversDetail_' + group;
- if (!sessionStorage[sessionKey]) {
- return;
- }
- var responses = JSON.parse(sessionStorage[sessionKey]);
- if (!Array.isArray(responses)) {
- return;
- }
- for (var i = 0; i < responses.length; i++) {
- if (!Array.isArray(responses[i].metrics) || responses[i].metrics.length
=== 0) {
- metricsUnavailable = true;
- break;
- }
- }
- rows = rows.concat(responses.map(buildScanServerRow));
- });
-
- return {
- rows: rows,
- metricsUnavailable: metricsUnavailable
- };
+function getStoredStatus() {
+ var view = getStoredView();
+ return view.status || null;
}
function refreshScanServersTable() {
ajaxReloadTable(sserversTable);
}
-function refreshSserversBanner(metricsUnavailable) {
- return $.when(
- $.getJSON(REST_V2_PREFIX + '/sservers/summary'),
- $.getJSON(REST_V2_PREFIX + '/problems')
- ).done(function (summaryResp, problemsResp) {
- var summary = summaryResp && summaryResp[0] ? summaryResp[0] : {};
- var problems = problemsResp && problemsResp[0] ? problemsResp[0] : [];
- var hasSservers = summary && Object.keys(summary).length > 0;
- var hasProblemSserver = problems.some(function (problem) {
- return problem.type === 'SCAN_SERVER' || problem.serverType ===
'SCAN_SERVER';
- });
-
- if (metricsUnavailable || hasProblemSserver) {
- var warnings = [];
- if (hasProblemSserver) {
- warnings.push('one or more scan servers are unavailable');
- }
- if (metricsUnavailable) {
- warnings.push('scan-server metrics are not present (are metrics
enabled?)');
- }
- $('#sservers-banner-message')
- .removeClass('alert-danger')
- .addClass('alert-warning')
- .text('WARN: ' + warnings.join('; ') + '.');
- $('#sserversStatusBanner').show();
- } else if (!hasSservers) {
- $('#sserversStatusBanner').hide();
- } else {
- $('#sserversStatusBanner').hide();
- }
- }).fail(function () {
+function refreshSserversBanner(status) {
+ if (status && status.level === 'WARN') {
$('#sservers-banner-message')
- .removeClass('alert-warning')
- .addClass('alert-danger')
- .text('ERROR: unable to retrieve scan-server status.');
+ .removeClass('alert-danger')
+ .addClass('alert-warning')
+ .text(status.message || 'WARN: scan-server status warning.');
$('#sserversStatusBanner').show();
- });
+ } else {
+ $('#sserversStatusBanner').hide();
+ }
}
-function refreshScanServers() {
- getGroups().then(function () {
- var groupList = JSON.parse(sessionStorage.groups || '[]');
-
- if (!Array.isArray(groupList) || groupList.length === 0) {
- setStoredRows([]);
- refreshScanServersTable();
- refreshSserversBanner(false);
- return;
- }
-
- var requests = $.map(groupList, function (group) {
- return getSserversDetail(group);
- });
+function showSserversBannerError() {
+ $('#sservers-banner-message')
+ .removeClass('alert-warning')
+ .addClass('alert-danger')
+ .text('ERROR: unable to retrieve scan-server status.');
+ $('#sserversStatusBanner').show();
+}
- $.when.apply($, requests).done(function () {
- var detailData = buildRowsFromSessionStorage(groupList);
- setStoredRows(detailData.rows);
- refreshScanServersTable();
- refreshSserversBanner(detailData.metricsUnavailable);
- }).fail(function () {
- setStoredRows([]);
- refreshScanServersTable();
- refreshSserversBanner(false);
- });
+function refreshScanServers() {
+ getSserversView().then(function () {
+ refreshScanServersTable();
+ refreshSserversBanner(getStoredStatus());
}).fail(function () {
- setStoredRows([]);
+ sessionStorage[SSERVERS_VIEW_SESSION_KEY] = JSON.stringify({
+ servers: [],
+ status: null
+ });
refreshScanServersTable();
- refreshSserversBanner(false);
+ showSserversBannerError();
});
}
@@ -248,7 +89,10 @@ function refresh() {
}
$(function () {
- setStoredRows([]);
+ sessionStorage[SSERVERS_VIEW_SESSION_KEY] = JSON.stringify({
+ servers: [],
+ status: null
+ });
sserversTable = $('#sservers').DataTable({
"autoWidth": false,