summaryrefslogtreecommitdiffstats
path: root/service-monitor
diff options
context:
space:
mode:
authorHåkon Hallingstad <hakon@oath.com>2018-12-08 02:05:15 +0100
committerHåkon Hallingstad <hakon@oath.com>2018-12-08 02:05:15 +0100
commit4023a30a3dfd3fe231693cd1a300af9725bd008e (patch)
tree51c687a9404e17e3b99f2fd902b7d3b7fb32c79b /service-monitor
parent8009fe519c103479a3cf02ab6cb7dc7b460c4d80 (diff)
Monitor health of host infra applications
Diffstat (limited to 'service-monitor')
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModelManager.java31
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitorFactory.java12
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/health/HealthMonitorManager.java22
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/model/ServiceId.java6
-rw-r--r--service-monitor/src/main/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImpl.java10
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/health/HealthMonitorManagerTest.java73
-rw-r--r--service-monitor/src/test/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImplTest.java7
7 files changed, 135 insertions, 26 deletions
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModelManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModelManager.java
index cc8dc7f8df7..e0e2b64bdae 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModelManager.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/duper/DuperModelManager.java
@@ -32,13 +32,14 @@ public class DuperModelManager implements DuperModelInfraApi {
private static Logger logger = Logger.getLogger(DuperModelManager.class.getName());
// Infrastructure applications
+ private final ConfigServerHostApplication configServerHostApplication = new ConfigServerHostApplication();
+ private final ProxyHostApplication proxyHostApplication = new ProxyHostApplication();
+ private final ControllerApplication controllerApplication = new ControllerApplication();
+ private final ControllerHostApplication controllerHostApplication = new ControllerHostApplication();
+ // this must be static to be referenced in this(). Remove static once legacy config server from config is gone.
private static final ConfigServerApplication configServerApplication = new ConfigServerApplication();
- private static final ConfigServerHostApplication configServerHostApplication = new ConfigServerHostApplication();
- private static final ProxyHostApplication proxyHostApplication = new ProxyHostApplication();
- private static final ControllerApplication controllerApplication = new ControllerApplication();
- private static final ControllerHostApplication controllerHostApplication = new ControllerHostApplication();
- private static final Map<ApplicationId, InfraApplication> supportedInfraApplications = Stream.of(
+ private final Map<ApplicationId, InfraApplication> supportedInfraApplications = Stream.of(
configServerApplication,
configServerHostApplication,
proxyHostApplication,
@@ -55,16 +56,6 @@ public class DuperModelManager implements DuperModelInfraApi {
// The set of active infrastructure ApplicationInfo. Not all are necessarily in the DuperModel for historical reasons.
private final Set<ApplicationId> activeInfraInfos = new HashSet<>(2 * supportedInfraApplications.size());
- /**
- * Returns true if application is considered an infrastructure application by the DuperModel.
- *
- * <p>Note: The tenant host "application" is NOT considered an infrastructure application: It is just a
- * cluster in the {@link ZoneApplication zone application}.
- */
- public static boolean isInfrastructureApplication(ApplicationId applicationId) {
- return supportedInfraApplications.containsKey(applicationId);
- }
-
@Inject
public DuperModelManager(ConfigserverConfig configServerConfig, FlagSource flagSource, SuperModelProvider superModelProvider) {
this(
@@ -148,6 +139,16 @@ public class DuperModelManager implements DuperModelInfraApi {
return new ArrayList<>(supportedInfraApplications.values());
}
+ /**
+ * Returns true if application is considered an infrastructure application by the DuperModel.
+ *
+ * <p>Note: The tenant host "application" is NOT considered an infrastructure application: It is just a
+ * cluster in the {@link ZoneApplication zone application}.
+ */
+ public boolean isSupportedInfraApplication(ApplicationId applicationId) {
+ return supportedInfraApplications.containsKey(applicationId);
+ }
+
@Override
public boolean infraApplicationIsActive(ApplicationId applicationId) {
synchronized (monitor) {
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitorFactory.java b/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitorFactory.java
new file mode 100644
index 00000000000..43be236268c
--- /dev/null
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/health/ApplicationHealthMonitorFactory.java
@@ -0,0 +1,12 @@
+// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.service.health;
+
+import com.yahoo.config.model.api.ApplicationInfo;
+
+/**
+ * @author hakonhall
+ */
+@FunctionalInterface
+interface ApplicationHealthMonitorFactory {
+ ApplicationHealthMonitor create(ApplicationInfo applicationInfo);
+}
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/health/HealthMonitorManager.java b/service-monitor/src/main/java/com/yahoo/vespa/service/health/HealthMonitorManager.java
index 91f9f313fe4..e9a5ec314f6 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/health/HealthMonitorManager.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/health/HealthMonitorManager.java
@@ -8,6 +8,8 @@ import com.yahoo.vespa.applicationmodel.ClusterId;
import com.yahoo.vespa.applicationmodel.ConfigId;
import com.yahoo.vespa.applicationmodel.ServiceStatus;
import com.yahoo.vespa.applicationmodel.ServiceType;
+import com.yahoo.vespa.flags.FeatureFlag;
+import com.yahoo.vespa.flags.FileFlagSource;
import com.yahoo.vespa.service.duper.DuperModelManager;
import com.yahoo.vespa.service.duper.ZoneApplication;
import com.yahoo.vespa.service.manager.MonitorManager;
@@ -22,16 +24,28 @@ import java.util.concurrent.ConcurrentHashMap;
public class HealthMonitorManager implements MonitorManager {
private final ConcurrentHashMap<ApplicationId, ApplicationHealthMonitor> healthMonitors = new ConcurrentHashMap<>();
private final DuperModelManager duperModel;
+ private final ApplicationHealthMonitorFactory applicationHealthMonitorFactory;
+ private final FeatureFlag monitorInfra;
@Inject
- public HealthMonitorManager(DuperModelManager duperModel) {
+ public HealthMonitorManager(DuperModelManager duperModel, FileFlagSource flagSource) {
+ this(duperModel,
+ new FeatureFlag("healthmonitor-monitorinfra", true, flagSource),
+ ApplicationHealthMonitor::startMonitoring);
+ }
+
+ HealthMonitorManager(DuperModelManager duperModel,
+ FeatureFlag monitorInfra,
+ ApplicationHealthMonitorFactory applicationHealthMonitorFactory) {
this.duperModel = duperModel;
+ this.applicationHealthMonitorFactory = applicationHealthMonitorFactory;
+ this.monitorInfra = monitorInfra;
}
@Override
public void applicationActivated(ApplicationInfo application) {
if (wouldMonitor(application.getApplicationId())) {
- ApplicationHealthMonitor monitor = ApplicationHealthMonitor.startMonitoring(application);
+ ApplicationHealthMonitor monitor = applicationHealthMonitorFactory.create(application);
healthMonitors.put(application.getApplicationId(), monitor);
}
}
@@ -65,6 +79,10 @@ public class HealthMonitorManager implements MonitorManager {
@Override
public boolean wouldMonitor(ApplicationId id) {
+ if (duperModel.isSupportedInfraApplication(id) && monitorInfra.value()) {
+ return true;
+ }
+
if (id.equals(duperModel.getConfigServerApplication().getApplicationId())) {
return true;
}
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/model/ServiceId.java b/service-monitor/src/main/java/com/yahoo/vespa/service/model/ServiceId.java
index b695b0b19f8..c0bcff7284c 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/model/ServiceId.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/model/ServiceId.java
@@ -22,9 +22,9 @@ public class ServiceId {
private final ConfigId configId;
public ServiceId(ApplicationId applicationId,
- ClusterId clusterId,
- ServiceType serviceType,
- ConfigId configId) {
+ ClusterId clusterId,
+ ServiceType serviceType,
+ ConfigId configId) {
this.applicationId = applicationId;
this.clusterId = clusterId;
this.serviceType = serviceType;
diff --git a/service-monitor/src/main/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImpl.java b/service-monitor/src/main/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImpl.java
index 39da5040ca0..13f24bc3694 100644
--- a/service-monitor/src/main/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImpl.java
+++ b/service-monitor/src/main/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImpl.java
@@ -28,14 +28,16 @@ public class SlobrokMonitorManagerImpl implements SlobrokApi, MonitorManager {
private final Object monitor = new Object();
private final HashMap<ApplicationId, SlobrokMonitor> slobrokMonitors = new HashMap<>();
+ private final DuperModelManager duperModel;
@Inject
- public SlobrokMonitorManagerImpl() {
- this(SlobrokMonitor::new);
+ public SlobrokMonitorManagerImpl(DuperModelManager duperModel) {
+ this(SlobrokMonitor::new, duperModel);
}
- SlobrokMonitorManagerImpl(Supplier<SlobrokMonitor> slobrokMonitorFactory) {
+ SlobrokMonitorManagerImpl(Supplier<SlobrokMonitor> slobrokMonitorFactory, DuperModelManager duperModel) {
this.slobrokMonitorFactory = slobrokMonitorFactory;
+ this.duperModel = duperModel;
}
@Override
@@ -108,7 +110,7 @@ public class SlobrokMonitorManagerImpl implements SlobrokApi, MonitorManager {
@Override
public boolean wouldMonitor(ApplicationId applicationId) {
- if (DuperModelManager.isInfrastructureApplication(applicationId)) {
+ if (duperModel.isSupportedInfraApplication(applicationId)) {
return false;
}
diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/health/HealthMonitorManagerTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/health/HealthMonitorManagerTest.java
index 5195bf218b6..f420f5c1284 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/health/HealthMonitorManagerTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/health/HealthMonitorManagerTest.java
@@ -2,33 +2,51 @@
package com.yahoo.vespa.service.health;
import com.yahoo.config.model.api.ApplicationInfo;
+import com.yahoo.config.provision.HostName;
import com.yahoo.vespa.applicationmodel.ClusterId;
import com.yahoo.vespa.applicationmodel.ConfigId;
import com.yahoo.vespa.applicationmodel.ServiceStatus;
import com.yahoo.vespa.applicationmodel.ServiceType;
+import com.yahoo.vespa.flags.FeatureFlag;
import com.yahoo.vespa.service.duper.ConfigServerApplication;
+import com.yahoo.vespa.service.duper.ControllerHostApplication;
import com.yahoo.vespa.service.duper.DuperModelManager;
+import com.yahoo.vespa.service.duper.InfraApplication;
+import com.yahoo.vespa.service.duper.ProxyHostApplication;
import com.yahoo.vespa.service.duper.ZoneApplication;
import com.yahoo.vespa.service.monitor.ConfigserverUtil;
import org.junit.Before;
import org.junit.Test;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class HealthMonitorManagerTest {
private final ConfigServerApplication configServerApplication = new ConfigServerApplication();
private final DuperModelManager duperModel = mock(DuperModelManager.class);
- private final HealthMonitorManager manager = new HealthMonitorManager(duperModel);
+ private final FeatureFlag monitorInfra = mock(FeatureFlag.class);
+ private final ApplicationHealthMonitor monitor = mock(ApplicationHealthMonitor.class);
+ private final ApplicationHealthMonitorFactory monitorFactory = mock(ApplicationHealthMonitorFactory.class);
+ private final HealthMonitorManager manager = new HealthMonitorManager(duperModel, monitorInfra, monitorFactory);
@Before
public void setUp() {
when(duperModel.getConfigServerApplication()).thenReturn(configServerApplication);
+ when(monitorFactory.create(any())).thenReturn(monitor);
}
@Test
public void addRemove() {
+ when(monitorInfra.value()).thenReturn(false);
ApplicationInfo applicationInfo = ConfigserverUtil.makeExampleConfigServer();
manager.applicationActivated(applicationInfo);
manager.applicationRemoved(applicationInfo.getApplicationId());
@@ -36,6 +54,7 @@ public class HealthMonitorManagerTest {
@Test
public void withHostAdmin() {
+ when(monitorInfra.value()).thenReturn(false);
ServiceStatus status = manager.getStatus(
ZoneApplication.ZONE_APPLICATION_ID,
ClusterId.NODE_ADMIN,
@@ -43,4 +62,56 @@ public class HealthMonitorManagerTest {
new ConfigId("config-id-1"));
assertEquals(ServiceStatus.UP, status);
}
+
+ @Test
+ public void infrastructureApplication() {
+ when(monitorInfra.value()).thenReturn(false);
+
+ ProxyHostApplication proxyHostApplication = new ProxyHostApplication();
+ when(duperModel.isSupportedInfraApplication(proxyHostApplication.getApplicationId())).thenReturn(true);
+ List<HostName> hostnames = Stream.of("proxyhost1", "proxyhost2").map(HostName::from).collect(Collectors.toList());
+ ApplicationInfo proxyHostApplicationInfo = proxyHostApplication.makeApplicationInfo(hostnames);
+
+ manager.applicationActivated(proxyHostApplicationInfo);
+ verify(monitorFactory, never()).create(proxyHostApplicationInfo);
+
+ assertStatus(ServiceStatus.NOT_CHECKED, 0, proxyHostApplication, "proxyhost1");
+ }
+
+ @Test
+ public void infrastructureApplicationWithMonitoring() {
+ when(monitorInfra.value()).thenReturn(true);
+
+ ProxyHostApplication proxyHostApplication = new ProxyHostApplication();
+ when(duperModel.isSupportedInfraApplication(proxyHostApplication.getApplicationId())).thenReturn(true);
+ List<HostName> hostnames = Stream.of("proxyhost1", "proxyhost2").map(HostName::from).collect(Collectors.toList());
+ ApplicationInfo proxyHostApplicationInfo = proxyHostApplication.makeApplicationInfo(hostnames);
+
+ manager.applicationActivated(proxyHostApplicationInfo);
+ verify(monitorFactory, times(1)).create(proxyHostApplicationInfo);
+
+ when(monitor.getStatus(any(), any(), any(), any())).thenReturn(ServiceStatus.UP);
+ assertStatus(ServiceStatus.UP, 1, proxyHostApplication, "proxyhost1");
+
+ ControllerHostApplication controllerHostApplication = new ControllerHostApplication();
+ when(duperModel.isSupportedInfraApplication(controllerHostApplication.getApplicationId())).thenReturn(true);
+ assertStatus(ServiceStatus.NOT_CHECKED, 0, controllerHostApplication, "controllerhost1");
+ }
+
+ private void assertStatus(ServiceStatus expected, int verifyTimes, InfraApplication infraApplication, String hostname) {
+ ServiceStatus actual = manager.getStatus(
+ infraApplication.getApplicationId(),
+ infraApplication.getClusterId(),
+ infraApplication.getServiceType(),
+ infraApplication.configIdFor(HostName.from(hostname)));
+
+ assertEquals(expected, actual);
+
+ verify(monitor, times(verifyTimes)).getStatus(
+ infraApplication.getApplicationId(),
+ infraApplication.getClusterId(),
+ infraApplication.getServiceType(),
+ infraApplication.configIdFor(HostName.from(hostname)));
+
+ }
} \ No newline at end of file
diff --git a/service-monitor/src/test/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImplTest.java b/service-monitor/src/test/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImplTest.java
index c3ee1d078bf..bc6bff6fba8 100644
--- a/service-monitor/src/test/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImplTest.java
+++ b/service-monitor/src/test/java/com/yahoo/vespa/service/slobrok/SlobrokMonitorManagerImplTest.java
@@ -7,6 +7,8 @@ import com.yahoo.vespa.applicationmodel.ClusterId;
import com.yahoo.vespa.applicationmodel.ConfigId;
import com.yahoo.vespa.applicationmodel.ServiceStatus;
import com.yahoo.vespa.applicationmodel.ServiceType;
+import com.yahoo.vespa.service.duper.ConfigServerApplication;
+import com.yahoo.vespa.service.duper.DuperModelManager;
import org.junit.Before;
import org.junit.Test;
@@ -25,8 +27,10 @@ public class SlobrokMonitorManagerImplTest {
@SuppressWarnings("unchecked")
private final Supplier<SlobrokMonitor> slobrokMonitorFactory = mock(Supplier.class);
+ private final ConfigServerApplication configServerApplication = new ConfigServerApplication();
+ private final DuperModelManager duperModelManager = mock(DuperModelManager.class);
private final SlobrokMonitorManagerImpl slobrokMonitorManager =
- new SlobrokMonitorManagerImpl(slobrokMonitorFactory);
+ new SlobrokMonitorManagerImpl(slobrokMonitorFactory, duperModelManager);
private final SlobrokMonitor slobrokMonitor = mock(SlobrokMonitor.class);
private final ApplicationId applicationId = ApplicationId.from("tenant", "app", "instance");
private final ApplicationInfo application = mock(ApplicationInfo.class);
@@ -34,6 +38,7 @@ public class SlobrokMonitorManagerImplTest {
@Before
public void setup() {
+ when(duperModelManager.getConfigServerApplication()).thenReturn(configServerApplication);
when(slobrokMonitorFactory.get()).thenReturn(slobrokMonitor);
when(application.getApplicationId()).thenReturn(applicationId);
}