summaryrefslogtreecommitdiffstats
path: root/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java
diff options
context:
space:
mode:
Diffstat (limited to 'service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java')
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java40
1 files changed, 29 insertions, 11 deletions
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java b/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java
index e728d1ea914..873baeae710 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitor.java
@@ -8,13 +8,14 @@ import com.yahoo.vespa.applicationmodel.ConfigId;
import com.yahoo.vespa.applicationmodel.ServiceStatus;
import com.yahoo.vespa.applicationmodel.ServiceStatusInfo;
import com.yahoo.vespa.applicationmodel.ServiceType;
-import com.yahoo.vespa.service.model.ServiceId;
+import com.yahoo.vespa.service.monitor.ServiceId;
import com.yahoo.vespa.service.monitor.ServiceStatusProvider;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Responsible for monitoring a whole application using /state/v1/health.
@@ -24,6 +25,10 @@ import java.util.Set;
class ApplicationHealthMonitor implements ServiceStatusProvider, AutoCloseable {
private final ApplicationId applicationId;
private final StateV1HealthModel healthModel;
+
+ // Guards against concurrent access to monitors field w/objects in 1. monitor() (called from e.g. DuperModel),
+ // 2. getStatus() called from caching layer and Orchestrator above, and 3. REST calls to getAllServiceStatuses().
+ private final Object guard = new Object();
private final Map<ServiceId, HealthMonitor> monitors = new HashMap<>();
ApplicationHealthMonitor(ApplicationId applicationId, StateV1HealthModel healthModel) {
@@ -38,13 +43,15 @@ class ApplicationHealthMonitor implements ServiceStatusProvider, AutoCloseable {
Map<ServiceId, HealthEndpoint> endpoints = healthModel.extractHealthEndpoints(applicationInfo);
- // Remove obsolete monitors
- Set<ServiceId> removed = new HashSet<>(monitors.keySet());
- removed.removeAll(endpoints.keySet());
- removed.stream().map(monitors::remove).forEach(HealthMonitor::close);
+ synchronized (guard) {
+ // Remove obsolete monitors
+ Set<ServiceId> removed = new HashSet<>(monitors.keySet());
+ removed.removeAll(endpoints.keySet());
+ removed.stream().map(monitors::remove).forEach(HealthMonitor::close);
- // Add new monitors.
- endpoints.forEach((serviceId, endpoint) -> monitors.computeIfAbsent(serviceId, ignoredId -> endpoint.startMonitoring()));
+ // Add new monitors.
+ endpoints.forEach((serviceId, endpoint) -> monitors.computeIfAbsent(serviceId, ignoredId -> endpoint.startMonitoring()));
+ }
}
@Override
@@ -53,12 +60,23 @@ class ApplicationHealthMonitor implements ServiceStatusProvider, AutoCloseable {
ServiceType serviceType,
ConfigId configId) {
ServiceId serviceId = new ServiceId(applicationId, clusterId, serviceType, configId);
- HealthMonitor monitor = monitors.get(serviceId);
- if (monitor == null) {
- return new ServiceStatusInfo(ServiceStatus.NOT_CHECKED);
+
+ synchronized (guard) {
+ HealthMonitor monitor = monitors.get(serviceId);
+ if (monitor == null) {
+ return new ServiceStatusInfo(ServiceStatus.NOT_CHECKED);
+ }
+
+ return monitor.getStatus();
}
+ }
- return monitor.getStatus();
+ public Map<ServiceId, ServiceStatusInfo> getAllServiceStatuses() {
+ synchronized (guard) {
+ return monitors.entrySet().stream().collect(Collectors.toMap(
+ entry -> entry.getKey(),
+ entry -> entry.getValue().getStatus()));
+ }
}
@Override