From 134155975af4a75e6128587c2f2ddeecd0c54e27 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Fri, 25 Mar 2016 15:15:49 +0100 Subject: [PATCH] SONAR-7436 System Info must not fail if the monitored process is not up --- .../container/ComputeEngineContainerImpl.java | 4 +- .../process/monitor/JavaProcessLauncher.java | 3 +- server/sonar-process/pom.xml | 3 +- .../org/sonar/process/jmx/JmxConnection.java | 12 ++- .../process/jmx/JmxConnectionFactory.java | 18 +++- .../process/jmx/JmxConnectionFactoryTest.java | 91 +++++++++++++++++++ .../sonar/process/jmx/JmxConnectionTest.java | 62 +++++++++++++ .../org/sonar/process/jmx/JmxTestServer.java | 71 +++++++++++++++ .../monitoring/CeDatabaseMonitor.java | 15 ++- .../platform/monitoring/CeStateMonitor.java | 10 +- .../platform/monitoring/CeTasksMonitor.java | 13 ++- .../platform/monitoring/DatabaseMonitor.java | 7 +- .../server/platform/monitoring/EsMonitor.java | 17 ++-- .../platform/monitoring/EsStateMonitor.java | 10 +- ...java => JmxConnectionFactoryProvider.java} | 2 +- .../platform/monitoring/JvmPropsMonitor.java | 11 +-- .../server/platform/monitoring/Monitor.java | 13 ++- .../platform/monitoring/PluginsMonitor.java | 8 +- .../platform/monitoring/SonarQubeMonitor.java | 8 +- .../platform/monitoring/SystemMonitor.java | 11 ++- .../platformlevel/PlatformLevel4.java | 4 +- .../sonar/server/platform/ws/InfoAction.java | 14 ++- .../monitoring/CeDatabaseMonitorTest.java | 18 +++- .../monitoring/CeStateMonitorTest.java | 14 ++- .../monitoring/CeTasksMonitorTest.java | 16 +++- .../monitoring/DatabaseMonitorTest.java | 6 +- .../platform/monitoring/EsMonitorTest.java | 7 +- .../monitoring/EsStateMonitorTest.java | 14 ++- .../platform/monitoring/FakeMonitor.java | 8 +- .../JmxConnectionFactoryProviderTest.java | 2 +- .../monitoring/JvmPropsMonitorTest.java | 7 +- .../monitoring/PluginsMonitorTest.java | 8 +- .../monitoring/SonarQubeMonitorTest.java | 19 ++-- .../monitoring/SystemMonitorTest.java | 5 +- .../server/platform/ws/InfoActionTest.java | 16 +++- .../sonar-web/src/main/js/apps/system/main.js | 2 +- 36 files changed, 430 insertions(+), 119 deletions(-) create mode 100644 server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java create mode 100644 server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java rename server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/{JmxConnectorProvider.java => JmxConnectionFactoryProvider.java} (96%) diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java index be0bda6e858..cee129ecb32 100644 --- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java +++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java @@ -108,7 +108,7 @@ import org.sonar.server.platform.ServerImpl; import org.sonar.server.platform.ServerLifecycleNotifier; import org.sonar.server.platform.ServerLogging; import org.sonar.server.platform.TempFolderProvider; -import org.sonar.server.platform.monitoring.JmxConnectorProvider; +import org.sonar.server.platform.monitoring.JmxConnectionFactoryProvider; import org.sonar.server.plugins.InstalledPluginReferentialFactory; import org.sonar.server.plugins.ServerExtensionInstaller; import org.sonar.server.properties.ProjectSettingsFactory; @@ -139,7 +139,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer { private static final Object[] LEVEL_1_COMPONENTS = new Object[] { ComputeEngineSettings.class, new SonarQubeVersionProvider(), - new JmxConnectorProvider(), + new JmxConnectionFactoryProvider(), ServerImpl.class, UuidFactoryImpl.INSTANCE, // no EmbeddedDatabaseFactory.class, creating H2 DB if responsibility of WebServer diff --git a/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java b/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java index c586d7c9df0..07556a80e5f 100644 --- a/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java +++ b/server/sonar-process-monitor/src/main/java/org/sonar/process/monitor/JavaProcessLauncher.java @@ -38,7 +38,7 @@ import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_KEY; import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; import static org.sonar.process.ProcessEntryPoint.PROPERTY_TERMINATION_TIMEOUT; -class JavaProcessLauncher implements AutoCloseable { +class JavaProcessLauncher { private final Timeouts timeouts; private final File tempDir; @@ -50,7 +50,6 @@ class JavaProcessLauncher implements AutoCloseable { this.allProcessesCommands = new AllProcessesCommands(tempDir); } - @Override public void close() { allProcessesCommands.close(); } diff --git a/server/sonar-process/pom.xml b/server/sonar-process/pom.xml index df90101c3c0..3bd9cfc33d7 100644 --- a/server/sonar-process/pom.xml +++ b/server/sonar-process/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 org.sonarsource.sonarqube diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java b/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java index 378c135af03..4c2eaca5452 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java +++ b/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java @@ -24,14 +24,16 @@ import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; import java.lang.management.ThreadMXBean; -import java.util.SortedMap; -import java.util.TreeMap; +import java.util.LinkedHashMap; +import java.util.Map; import javax.annotation.CheckForNull; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.management.remote.JMXConnector; +import static java.lang.String.format; + public class JmxConnection implements AutoCloseable { private static final long MEGABYTE = 1024L * 1024L; @@ -55,12 +57,12 @@ public class JmxConnection implements AutoCloseable { } return JMX.newMBeanProxy(connection, new ObjectName(mBeanName), mBeanInterfaceClass); } catch (Exception e) { - throw new IllegalStateException("Fail to connect to MBean " + mBeanName, e); + throw new IllegalStateException(format("Fail to connect to MBean [%s]", mBeanName), e); } } - public SortedMap getSystemState() { - SortedMap props = new TreeMap<>(); + public Map getSystemState() { + Map props = new LinkedHashMap<>(); MemoryMXBean memory = getMBean(ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class); MemoryUsage heap = memory.getHeapMemoryUsage(); props.put("Heap Committed (MB)", toMegaBytes(heap.getCommitted())); diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java b/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java index ca906b9540d..29383cc211e 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java +++ b/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java @@ -20,6 +20,7 @@ package org.sonar.process.jmx; import java.io.File; +import javax.annotation.CheckForNull; import javax.annotation.concurrent.Immutable; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; @@ -44,14 +45,23 @@ public class JmxConnectionFactory { this.ipcSharedDir = props.nonNullValueAsFile(ProcessEntryPoint.PROPERTY_SHARED_PATH); } + @CheckForNull public JmxConnection create(ProcessId processId) { try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(ipcSharedDir, processId.getIpcIndex())) { - String url = commands.getJmxUrl(); - JMXConnector jmxConnector = JMXConnectorFactory.newJMXConnector(new JMXServiceURL(url), null); - jmxConnector.connect(); - return new JmxConnection(jmxConnector); + if (commands.isUp()) { + String url = commands.getJmxUrl(); + JMXConnector jmxConnector = JMXConnectorFactory.newJMXConnector(new JMXServiceURL(url), null); + jmxConnector.connect(); + return new JmxConnection(jmxConnector); + } + return null; } catch (Exception e) { throw new IllegalStateException("Can not connect to process " + processId, e); } } + + // visible for testing + File getIpcSharedDir() { + return ipcSharedDir; + } } diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java new file mode 100644 index 00000000000..4709acb83d3 --- /dev/null +++ b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.process.jmx; + +import java.io.File; +import java.util.Properties; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.process.DefaultProcessCommands; +import org.sonar.process.ProcessId; +import org.sonar.process.Props; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JmxConnectionFactoryTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public JmxTestServer jmxServer = new JmxTestServer(); + + @Test + public void create_returns_null_if_process_is_down() throws Exception { + File ipcSharedDir = temp.newFolder(); + JmxConnectionFactory underTest = new JmxConnectionFactory(ipcSharedDir); + + JmxConnection connection = underTest.create(ProcessId.COMPUTE_ENGINE); + + assertThat(connection).isNull(); + } + + @Test + public void create_connection_if_process_is_up() throws Exception { + File ipcSharedDir = temp.newFolder(); + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(ipcSharedDir, ProcessId.COMPUTE_ENGINE.getIpcIndex())) { + processCommands.setUp(); + processCommands.setJmxUrl(jmxServer.getAddress().toString()); + } + + JmxConnection connection = new JmxConnectionFactory(ipcSharedDir).create(ProcessId.COMPUTE_ENGINE); + assertThat(connection).isNotNull(); + } + + @Test + public void create_throws_ISE_if_fails_to_connect_to_process() throws Exception { + File ipcSharedDir = temp.newFolder(); + try (DefaultProcessCommands processCommands = DefaultProcessCommands.secondary(ipcSharedDir, ProcessId.COMPUTE_ENGINE.getIpcIndex())) { + // process is up but does not have any JMX URL + processCommands.setUp(); + } + + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Can not connect to process " + ProcessId.COMPUTE_ENGINE.toString()); + new JmxConnectionFactory(ipcSharedDir).create(ProcessId.COMPUTE_ENGINE); + } + + @Test + public void load_ipc_shared_dir_from_props() throws Exception { + File ipcSharedDir = temp.newFolder(); + Properties props = new Properties(); + props.setProperty("process.sharedDir", ipcSharedDir.getAbsolutePath()); + + JmxConnectionFactory underTest = new JmxConnectionFactory(new Props(props)); + + assertThat(underTest.getIpcSharedDir().getCanonicalPath()).isEqualTo(ipcSharedDir.getCanonicalPath()); + } + +} diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java index c8aa351524d..efb7f83701f 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java @@ -19,12 +19,46 @@ */ package org.sonar.process.jmx; +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.util.Map; +import javax.management.ObjectName; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static org.assertj.core.api.Assertions.assertThat; public class JmxConnectionTest { + private static final String CUSTOM_OBJECT_NAME = "Test:name=test"; + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Rule + public JmxTestServer jmxServer = new JmxTestServer(); + + JmxConnection underTest; + + @Before + public void setUp() throws Exception { + jmxServer.getMBeanServer().registerMBean(new Fake(), new ObjectName(CUSTOM_OBJECT_NAME)); + JMXConnector jmxConnector = JMXConnectorFactory.newJMXConnector(jmxServer.getAddress(), null); + jmxConnector.connect(); + underTest = new JmxConnection(jmxConnector); + } + + @After + public void tearDown() throws Exception { + underTest.close(); + jmxServer.getMBeanServer().unregisterMBean(new ObjectName(CUSTOM_OBJECT_NAME)); + } + @Test public void toMegaBytes() { assertThat(JmxConnection.toMegaBytes(-1)).isNull(); @@ -33,4 +67,32 @@ public class JmxConnectionTest { assertThat(JmxConnection.toMegaBytes(500_000L)).isEqualTo(0L); assertThat(JmxConnection.toMegaBytes(500_000_000L)).isEqualTo(476L); } + + @Test + public void get_platform_mbean() throws Exception { + RuntimeMXBean runtimeMBean = underTest.getMBean(ManagementFactory.RUNTIME_MXBEAN_NAME, RuntimeMXBean.class); + + assertThat(runtimeMBean).isNotNull(); + } + + @Test + public void get_custom_mbean() throws Exception { + FakeMBean mbean = underTest.getMBean(CUSTOM_OBJECT_NAME, FakeMBean.class); + + assertThat(mbean).isNotNull(); + } + + @Test + public void getMBean_fails_if_does_not_exist() throws Exception { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Fail to connect to MBean [unknown]"); + underTest.getMBean("unknown", FakeMBean.class); + } + + @Test + public void getSystemState() throws Exception { + Map state = underTest.getSystemState(); + assertThat(state).containsKey("Heap Max (MB)"); + assertThat((int) state.get("Thread Count")).isGreaterThan(0); + } } diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java new file mode 100644 index 00000000000..9ffe8413bef --- /dev/null +++ b/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java @@ -0,0 +1,71 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.process.jmx; + +import com.google.common.base.Throwables; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.rmi.registry.LocateRegistry; +import java.util.HashMap; +import javax.management.MBeanServer; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; +import org.junit.rules.ExternalResource; +import org.sonar.process.NetworkUtils; + +public class JmxTestServer extends ExternalResource { + + private final int jmxPort = NetworkUtils.freePort(); + private JMXConnectorServer jmxServer; + + @Override + protected void before() throws Throwable { + LocateRegistry.createRegistry(jmxPort); + JMXServiceURL serviceUrl = new JMXServiceURL("service:jmx:rmi://localhost:" + jmxPort + "/jndi/rmi://localhost:" + jmxPort + "/jmxrmi"); + MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); + jmxServer = JMXConnectorServerFactory.newJMXConnectorServer(serviceUrl, new HashMap(), mbeanServer); + jmxServer.start(); + + } + + @Override + protected void after() { + if (jmxServer != null) { + try { + jmxServer.stop(); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + } + + public int getPort() { + return jmxPort; + } + + public MBeanServer getMBeanServer() { + return jmxServer.getMBeanServer(); + } + + public JMXServiceURL getAddress() { + return jmxServer.getAddress(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java index 1b6b548e379..052d3ff5634 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeDatabaseMonitor.java @@ -19,7 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.util.LinkedHashMap; +import java.util.Map; import org.sonar.process.ProcessId; import org.sonar.process.jmx.CeDatabaseMBean; import org.sonar.process.jmx.JmxConnection; @@ -27,6 +29,8 @@ import org.sonar.process.jmx.JmxConnectionFactory; public class CeDatabaseMonitor implements Monitor { + private static final int NUMBER_OF_ATTRIBUTES = 9; + private final JmxConnectionFactory jmxConnectionFactory; public CeDatabaseMonitor(JmxConnectionFactory jmxConnectionFactory) { @@ -35,13 +39,16 @@ public class CeDatabaseMonitor implements Monitor { @Override public String name() { - return "Compute Engine Database"; + return "Compute Engine Database Connection"; } @Override - public LinkedHashMap attributes() { + public Optional> attributes() { try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)) { - LinkedHashMap result = new LinkedHashMap<>(); + if (connection == null) { + return Optional.absent(); + } + Map result = new LinkedHashMap<>(NUMBER_OF_ATTRIBUTES); CeDatabaseMBean mbean = connection.getMBean(CeDatabaseMBean.OBJECT_NAME, CeDatabaseMBean.class); result.put("Pool Initial Size", mbean.getPoolInitialSize()); result.put("Pool Active Connections", mbean.getPoolActiveConnections()); @@ -52,7 +59,7 @@ public class CeDatabaseMonitor implements Monitor { result.put("Pool Max Wait (ms)", mbean.getPoolMaxWaitMillis()); result.put("Pool Remove Abandoned", mbean.getPoolRemoveAbandoned()); result.put("Pool Remove Abandoned Timeout (sec)", mbean.getPoolRemoveAbandonedTimeoutSeconds()); - return result; + return Optional.of(result); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java index 2c834fe20b7..d920607edb6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeStateMonitor.java @@ -19,7 +19,8 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; +import java.util.Map; import org.sonar.process.ProcessId; import org.sonar.process.jmx.JmxConnection; import org.sonar.process.jmx.JmxConnectionFactory; @@ -38,9 +39,12 @@ public class CeStateMonitor implements Monitor { } @Override - public LinkedHashMap attributes() { + public Optional> attributes() { try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)) { - return new LinkedHashMap<>(connection.getSystemState()); + if (connection == null) { + return Optional.absent(); + } + return Optional.of(connection.getSystemState()); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java index 77c1af84c53..fbdd08ba5dd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/CeTasksMonitor.java @@ -19,7 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.util.LinkedHashMap; +import java.util.Map; import org.sonar.process.ProcessId; import org.sonar.process.jmx.CeTasksMBean; import org.sonar.process.jmx.JmxConnection; @@ -27,6 +29,8 @@ import org.sonar.process.jmx.JmxConnectionFactory; public class CeTasksMonitor implements Monitor { + private static final int NUMBER_OF_ATTRIBUTES = 6; + private final JmxConnectionFactory jmxConnectionFactory; public CeTasksMonitor(JmxConnectionFactory jmxConnectionFactory) { @@ -39,9 +43,12 @@ public class CeTasksMonitor implements Monitor { } @Override - public LinkedHashMap attributes() { + public Optional> attributes() { try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)) { - LinkedHashMap result = new LinkedHashMap<>(); + if (connection == null) { + return Optional.absent(); + } + Map result = new LinkedHashMap<>(NUMBER_OF_ATTRIBUTES); CeTasksMBean ceMBean = connection.getMBean(CeTasksMBean.OBJECT_NAME, CeTasksMBean.class); result.put("Pending", ceMBean.getPendingCount()); result.put("In Progress", ceMBean.getInProgressCount()); @@ -49,7 +56,7 @@ public class CeTasksMonitor implements Monitor { result.put("Processed With Error", ceMBean.getErrorCount()); result.put("Processing Time (ms)", ceMBean.getProcessingTime()); result.put("Worker Count", ceMBean.getWorkerCount()); - return result; + return Optional.of(result); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java index ceb0caf6ff0..f71f841b6e6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java @@ -19,6 +19,7 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.SQLException; @@ -100,11 +101,11 @@ public class DatabaseMonitor extends BaseMonitorMBean implements DatabaseMonitor } @Override - public LinkedHashMap attributes() { - LinkedHashMap attributes = new LinkedHashMap<>(); + public Optional> attributes() { + Map attributes = new LinkedHashMap<>(); completeDbAttributes(attributes); completePoolAttributes(attributes); - return attributes; + return Optional.of(attributes); } private void completePoolAttributes(Map attributes) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java index 0317ba2c1b0..686ae56880a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsMonitor.java @@ -19,6 +19,7 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.util.LinkedHashMap; import java.util.Map; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; @@ -71,20 +72,22 @@ public class EsMonitor extends BaseMonitorMBean implements EsMonitorMBean { } @Override - public LinkedHashMap attributes() { - LinkedHashMap attributes = new LinkedHashMap<>(); + public Optional> attributes() { + Map attributes = new LinkedHashMap<>(); try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.ELASTICSEARCH)) { - EsSettingsMBean mbean = connection.getMBean(EsSettingsMBean.OBJECT_NAME, EsSettingsMBean.class); - attributes.put("Cluster Name", mbean.getClusterName()); - attributes.put("Node Name", mbean.getNodeName()); - attributes.put("HTTP Port", mbean.getHttpPort()); + if (connection != null) { + EsSettingsMBean mbean = connection.getMBean(EsSettingsMBean.OBJECT_NAME, EsSettingsMBean.class); + attributes.put("Cluster Name", mbean.getClusterName()); + attributes.put("Node Name", mbean.getNodeName()); + attributes.put("HTTP Port", mbean.getHttpPort()); + } } attributes.put("State", getStateAsEnum()); attributes.put("Indices", indexAttributes()); attributes.put("Number of Nodes", getNumberOfNodes()); attributes.put("Nodes", nodeAttributes()); - return attributes; + return Optional.of(attributes); } private LinkedHashMap> indexAttributes() { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsStateMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsStateMonitor.java index 0f8d60c4b07..779019be924 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsStateMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsStateMonitor.java @@ -19,7 +19,8 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; +import java.util.Map; import org.sonar.process.ProcessId; import org.sonar.process.jmx.JmxConnection; import org.sonar.process.jmx.JmxConnectionFactory; @@ -38,9 +39,12 @@ public class EsStateMonitor implements Monitor { } @Override - public LinkedHashMap attributes() { + public Optional> attributes() { try (JmxConnection connection = jmxConnectionFactory.create(ProcessId.ELASTICSEARCH)) { - return new LinkedHashMap<>(connection.getSystemState()); + if (connection == null) { + return Optional.absent(); + } + return Optional.of(connection.getSystemState()); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectorProvider.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProvider.java similarity index 96% rename from server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectorProvider.java rename to server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProvider.java index 2bc9d247607..ebc98c1dddf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectorProvider.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProvider.java @@ -27,7 +27,7 @@ import org.sonar.process.jmx.JmxConnectionFactory; import static com.google.common.base.Preconditions.checkArgument; import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH; -public class JmxConnectorProvider extends ProviderAdapter { +public class JmxConnectionFactoryProvider extends ProviderAdapter { private JmxConnectionFactory singleton = null; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java index 3d4b33e292b..26f642b7e6b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropsMonitor.java @@ -19,11 +19,10 @@ */ package org.sonar.server.platform.monitoring; -import com.google.common.collect.Maps; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; import java.util.Map; import java.util.Objects; -import java.util.SortedMap; +import java.util.TreeMap; public class JvmPropsMonitor implements Monitor { @Override @@ -32,11 +31,11 @@ public class JvmPropsMonitor implements Monitor { } @Override - public LinkedHashMap attributes() { - SortedMap sortedProps = Maps.newTreeMap(); + public Optional> attributes() { + Map sortedProps = new TreeMap<>(); for (Map.Entry systemProp : System.getProperties().entrySet()) { sortedProps.put(Objects.toString(systemProp.getKey()), Objects.toString(systemProp.getValue())); } - return new LinkedHashMap<>(sortedProps); + return Optional.of(sortedProps); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java index 4ab48a74d56..c87db9ad8f4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java @@ -19,13 +19,13 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; +import java.util.Map; import org.sonar.api.server.ServerSide; import org.sonar.server.platform.ws.InfoAction; -import java.util.LinkedHashMap; - /** - * Any component that is involved in the informations returned by the web service api/system/info + * Any component that is involved in the information returned by the web service api/system/info */ @ServerSide public interface Monitor { @@ -36,7 +36,10 @@ public interface Monitor { /** * Type of attribute values must be supported by {@link org.sonar.api.utils.text.JsonWriter#valueObject(Object)} - * because of JSON export by {@link InfoAction} + * because of JSON export by {@link InfoAction}. + * + * @return map of attributes, or Optional.absent() if the monitored component is not up. In the latter case + * nothing is returned in the web service api/system/info. */ - LinkedHashMap attributes(); + Optional> attributes(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java index 4bd683e8912..6edb3cef096 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java @@ -19,7 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.util.LinkedHashMap; +import java.util.Map; import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginRepository; import org.sonar.updatecenter.common.Version; @@ -40,8 +42,8 @@ public class PluginsMonitor implements Monitor { } @Override - public LinkedHashMap attributes() { - LinkedHashMap attributes = new LinkedHashMap<>(); + public Optional> attributes() { + Map attributes = new LinkedHashMap<>(); for (PluginInfo plugin : repository.getPluginInfos()) { LinkedHashMap pluginAttributes = new LinkedHashMap<>(); pluginAttributes.put("Name", plugin.getName()); @@ -51,6 +53,6 @@ public class PluginsMonitor implements Monitor { } attributes.put(plugin.getKey(), pluginAttributes); } - return attributes; + return Optional.of(attributes); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java index 51605634647..7d6c3bd00ba 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java @@ -19,8 +19,10 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.io.File; import java.util.LinkedHashMap; +import java.util.Map; import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.platform.Server; @@ -95,8 +97,8 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit } @Override - public LinkedHashMap attributes() { - LinkedHashMap attributes = new LinkedHashMap<>(); + public Optional> attributes() { + Map attributes = new LinkedHashMap<>(); attributes.put("Server ID", getServerId()); attributes.put("Version", getVersion()); attributes.put("External User Authentication", getExternalUserAuthentication()); @@ -109,7 +111,7 @@ public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonit attributes.put("Temp Dir", settings.getString(ProcessProperties.PATH_TEMP)); attributes.put("Logs Dir", settings.getString(ProcessProperties.PATH_LOGS)); attributes.put("Logs Level", getLogLevel()); - return attributes; + return Optional.of(attributes); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java index 30849f76698..d7d279d94c9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java @@ -19,8 +19,7 @@ */ package org.sonar.server.platform.monitoring; -import org.sonar.api.utils.System2; - +import com.google.common.base.Optional; import java.lang.management.ClassLoadingMXBean; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; @@ -28,6 +27,8 @@ import java.lang.management.RuntimeMXBean; import java.lang.management.ThreadMXBean; import java.util.Date; import java.util.LinkedHashMap; +import java.util.Map; +import org.sonar.api.utils.System2; import static org.sonar.api.utils.DateUtils.formatDateTime; @@ -52,8 +53,8 @@ public class SystemMonitor implements Monitor { } @Override - public LinkedHashMap attributes() { - LinkedHashMap attributes = new LinkedHashMap<>(); + public Optional> attributes() { + Map attributes = new LinkedHashMap<>(); attributes.put("System Date", formatDateTime(new Date(system.now()))); attributes.put("Start Time", formatDateTime(new Date(runtimeMXBean().getStartTime()))); attributes.put("JVM Vendor", runtimeMXBean().getVmVendor()); @@ -75,7 +76,7 @@ public class SystemMonitor implements Monitor { attributes.put("Threads", threadMXBean().getThreadCount()); attributes.put("Threads Peak", threadMXBean().getPeakThreadCount()); attributes.put("Daemon Thread", threadMXBean().getDaemonThreadCount()); - return attributes; + return Optional.of(attributes); } private static RuntimeMXBean runtimeMXBean() { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index e8ea9752617..f5d88c657fc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -160,7 +160,7 @@ import org.sonar.server.platform.monitoring.CeTasksMonitor; import org.sonar.server.platform.monitoring.DatabaseMonitor; import org.sonar.server.platform.monitoring.EsMonitor; import org.sonar.server.platform.monitoring.EsStateMonitor; -import org.sonar.server.platform.monitoring.JmxConnectorProvider; +import org.sonar.server.platform.monitoring.JmxConnectionFactoryProvider; import org.sonar.server.platform.monitoring.JvmPropsMonitor; import org.sonar.server.platform.monitoring.PluginsMonitor; import org.sonar.server.platform.monitoring.SonarQubeMonitor; @@ -653,7 +653,7 @@ public class PlatformLevel4 extends PlatformLevel { TypeValidationModule.class, // System - new JmxConnectorProvider(), + new JmxConnectionFactoryProvider(), ServerLogging.class, RestartAction.class, InfoAction.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java index 3a4135818be..3512a9eb632 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/InfoAction.java @@ -19,6 +19,7 @@ */ package org.sonar.server.platform.ws; +import com.google.common.base.Optional; import java.util.Map; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; @@ -63,12 +64,15 @@ public class InfoAction implements SystemWsAction { private void writeJson(JsonWriter json) { json.beginObject(); for (Monitor monitor : monitors) { - json.name(monitor.name()); - json.beginObject(); - for (Map.Entry attribute : monitor.attributes().entrySet()) { - json.name(attribute.getKey()).valueObject(attribute.getValue()); + Optional> attributes = monitor.attributes(); + if (attributes.isPresent()) { + json.name(monitor.name()); + json.beginObject(); + for (Map.Entry attribute : attributes.get().entrySet()) { + json.name(attribute.getKey()).valueObject(attribute.getValue()); + } + json.endObject(); } - json.endObject(); } json.endObject(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java index 4c2ce9ed035..9758471ffcb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeDatabaseMonitorTest.java @@ -19,7 +19,8 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; +import java.util.Map; import org.junit.Test; import org.mockito.Mockito; import org.sonar.process.ProcessId; @@ -41,13 +42,20 @@ public class CeDatabaseMonitorTest { } @Test - public void testAttributes() { + public void attributes() { CeDatabaseMBean mbean = mock(CeDatabaseMBean.class, Mockito.RETURNS_DEFAULTS); when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE).getMBean(CeDatabaseMBean.OBJECT_NAME, CeDatabaseMBean.class)) .thenReturn(mbean); - LinkedHashMap attributes = underTest.attributes(); - assertThat(attributes).containsKeys("Pool Initial Size", "Pool Active Connections"); - assertThat(attributes).hasSize(9); + Optional> attributes = underTest.attributes(); + assertThat(attributes.get()).containsKeys("Pool Initial Size", "Pool Active Connections"); + assertThat(attributes.get()).hasSize(9); + } + + @Test + public void absent_attributes_if_CE_is_down() { + when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)).thenReturn(null); + Optional> attributes = underTest.attributes(); + assertThat(attributes.isPresent()).isFalse(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java index 5db51a693fa..1154bcff55c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeStateMonitorTest.java @@ -19,8 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableSortedMap; -import java.util.LinkedHashMap; +import java.util.Map; import org.assertj.core.data.MapEntry; import org.junit.Test; import org.mockito.Mockito; @@ -45,9 +46,16 @@ public class CeStateMonitorTest { public void testAttributes() { when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE).getSystemState()).thenReturn(ImmutableSortedMap.of( "foo", "foo_val", "bar", "bar_val")); - LinkedHashMap attributes = underTest.attributes(); - assertThat(attributes).containsExactly( + Optional> attributes = underTest.attributes(); + assertThat(attributes.get()).containsExactly( MapEntry.entry("bar", "bar_val"), MapEntry.entry("foo", "foo_val")); } + + @Test + public void absent_attributes_if_CE_is_down() { + when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)).thenReturn(null); + Optional> attributes = underTest.attributes(); + assertThat(attributes.isPresent()).isFalse(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java index cf1902601ae..c9d7626aa5a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/CeTasksMonitorTest.java @@ -19,7 +19,8 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; +import java.util.Map; import org.junit.Test; import org.mockito.Mockito; import org.sonar.process.ProcessId; @@ -46,8 +47,15 @@ public class CeTasksMonitorTest { when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE).getMBean(CeTasksMBean.OBJECT_NAME, CeTasksMBean.class)) .thenReturn(mbean); - LinkedHashMap attributes = underTest.attributes(); - assertThat(attributes).containsKeys("Pending"); - assertThat(attributes).hasSize(6); + Optional> attributes = underTest.attributes(); + assertThat(attributes.get()).containsKeys("Pending"); + assertThat(attributes.get()).hasSize(6); + } + + @Test + public void absent_attributes_if_CE_is_down() { + when(jmxConnectionFactory.create(ProcessId.COMPUTE_ENGINE)).thenReturn(null); + Optional> attributes = underTest.attributes(); + assertThat(attributes.isPresent()).isFalse(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java index 1e7cb5eccc5..5ed384ce7b0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java @@ -19,7 +19,7 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import java.util.Map; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -49,7 +49,7 @@ public class DatabaseMonitorTest { @Test public void db_info() { - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); assertThat(attributes.get("Database")).isEqualTo("H2"); assertThat(attributes.get("Database Version").toString()).startsWith("1."); assertThat(attributes.get("Username")).isEqualTo("SONAR"); @@ -58,7 +58,7 @@ public class DatabaseMonitorTest { @Test public void pool_info() { - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); assertThat((int) attributes.get("Pool Max Connections")).isGreaterThan(0); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java index 0716a6415a8..6379c5d0779 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsMonitorTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; import java.util.Map; import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus; import org.junit.Before; @@ -59,7 +58,7 @@ public class EsMonitorTest { @Test public void cluster_attributes() { - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); assertThat(underTest.getState()).isEqualTo(ClusterHealthStatus.GREEN.name()); assertThat(attributes.get("State")).isEqualTo(ClusterHealthStatus.GREEN); assertThat(attributes.get("Number of Nodes")).isEqualTo(1); @@ -67,7 +66,7 @@ public class EsMonitorTest { @Test public void node_attributes() { - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); Map nodesAttributes = (Map) attributes.get("Nodes"); // one node @@ -79,7 +78,7 @@ public class EsMonitorTest { @Test public void index_attributes() { - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); Map indicesAttributes = (Map) attributes.get("Indices"); // one index "issues" diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java index e06f5c9c111..7618fedfbd8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/EsStateMonitorTest.java @@ -19,8 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import com.google.common.collect.ImmutableSortedMap; -import java.util.LinkedHashMap; +import java.util.Map; import org.assertj.core.data.MapEntry; import org.junit.Test; import org.mockito.Mockito; @@ -44,9 +45,16 @@ public class EsStateMonitorTest { public void testAttributes() { when(jmxConnectionFactory.create(ProcessId.ELASTICSEARCH).getSystemState()).thenReturn(ImmutableSortedMap.of( "foo", "foo_val", "bar", "bar_val")); - LinkedHashMap attributes = underTest.attributes(); - assertThat(attributes).containsExactly( + Optional> attributes = underTest.attributes(); + assertThat(attributes.get()).containsExactly( MapEntry.entry("bar", "bar_val"), MapEntry.entry("foo", "foo_val")); } + + @Test + public void absent_attributes_if_CE_is_down() { + when(jmxConnectionFactory.create(ProcessId.ELASTICSEARCH)).thenReturn(null); + Optional> attributes = underTest.attributes(); + assertThat(attributes.isPresent()).isFalse(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java index 885ab6866a4..879b65f8405 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java @@ -19,7 +19,9 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; +import java.util.Collections; +import java.util.Map; public class FakeMonitor extends BaseMonitorMBean implements FakeMonitorMBean { @@ -34,7 +36,7 @@ public class FakeMonitor extends BaseMonitorMBean implements FakeMonitorMBean { } @Override - public LinkedHashMap attributes() { - return new LinkedHashMap<>(); + public Optional> attributes() { + return Optional.of(Collections.emptyMap()); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java index 5a461bc21c3..03998a76cde 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JmxConnectionFactoryProviderTest.java @@ -34,7 +34,7 @@ public class JmxConnectionFactoryProviderTest { public ExpectedException expectedException = ExpectedException.none(); Settings settings = new Settings(); - JmxConnectorProvider underTest = new JmxConnectorProvider(); + JmxConnectionFactoryProvider underTest = new JmxConnectionFactoryProvider(); @Test public void provide_JmxConnector() { diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java index 48ce163e151..0a534035280 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropsMonitorTest.java @@ -19,7 +19,8 @@ */ package org.sonar.server.platform.monitoring; -import java.util.LinkedHashMap; +import com.google.common.base.Optional; +import java.util.Map; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -35,8 +36,8 @@ public class JvmPropsMonitorTest { @Test public void attributes() { - LinkedHashMap attributes = underTest.attributes(); + Optional> attributes = underTest.attributes(); - assertThat(attributes).containsKeys("java.vm.vendor", "os.name"); + assertThat(attributes.get()).containsKeys("java.vm.vendor", "os.name"); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java index 04501cc361a..c5c4b1a4f51 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java @@ -19,15 +19,13 @@ */ package org.sonar.server.platform.monitoring; +import java.util.Arrays; +import java.util.Map; import org.junit.Test; import org.sonar.core.platform.PluginInfo; import org.sonar.core.platform.PluginRepository; import org.sonar.updatecenter.common.Version; -import java.util.Arrays; -import java.util.LinkedHashMap; -import java.util.Map; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -54,7 +52,7 @@ public class PluginsMonitorTest { new PluginInfo("no-version") .setName("No Version"))); - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); assertThat(attributes).containsKeys("key-1", "key-2"); assertThat((Map) attributes.get("key-1")) diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java index 9c9f91999d9..70155ae82f9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java @@ -19,8 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import com.google.common.base.Optional; import java.io.File; -import java.util.LinkedHashMap; +import java.util.Map; import org.apache.commons.io.FileUtils; import org.junit.Before; import org.junit.Rule; @@ -61,8 +62,8 @@ public class SonarQubeMonitorTest { when(server.getStartedAt()).thenReturn(DateUtils.parseDate("2015-01-01")); SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - LinkedHashMap attributes = monitor.attributes(); - assertThat(attributes).containsKeys("Server ID", "Version"); + Optional> attributes = monitor.attributes(); + assertThat(attributes.get()).containsKeys("Server ID", "Version"); } @Test @@ -73,8 +74,8 @@ public class SonarQubeMonitorTest { when(server.getRootDir()).thenReturn(rootDir); SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - LinkedHashMap attributes = monitor.attributes(); - assertThat(attributes).containsEntry("Official Distribution", Boolean.TRUE); + Optional> attributes = monitor.attributes(); + assertThat(attributes.get()).containsEntry("Official Distribution", Boolean.TRUE); } @Test @@ -84,15 +85,15 @@ public class SonarQubeMonitorTest { when(server.getRootDir()).thenReturn(rootDir); SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - LinkedHashMap attributes = monitor.attributes(); - assertThat(attributes).containsEntry("Official Distribution", Boolean.FALSE); + Optional> attributes = monitor.attributes(); + assertThat(attributes.get()).containsEntry("Official Distribution", Boolean.FALSE); } @Test public void get_log_level() throws Exception { SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server, serverLogging); - LinkedHashMap attributes = monitor.attributes(); - assertThat(attributes).containsEntry("Logs Level", "DEBUG"); + Optional> attributes = monitor.attributes(); + assertThat(attributes.get()).containsEntry("Logs Level", "DEBUG"); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java index 0232572647b..07510691802 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java @@ -19,10 +19,9 @@ */ package org.sonar.server.platform.monitoring; +import java.util.Map; import org.junit.Test; -import java.util.LinkedHashMap; - import static org.assertj.core.api.Assertions.assertThat; public class SystemMonitorTest { @@ -36,7 +35,7 @@ public class SystemMonitorTest { @Test public void system_properties() { - LinkedHashMap attributes = underTest.attributes(); + Map attributes = underTest.attributes().get(); assertThat(attributes).containsKeys("System Date", "Processors"); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java index 539cc6440f9..41a0a6788b9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/InfoActionTest.java @@ -19,7 +19,9 @@ */ package org.sonar.server.platform.ws; +import com.google.common.base.Optional; import java.util.LinkedHashMap; +import java.util.Map; import org.junit.Rule; import org.junit.Test; import org.sonar.api.server.ws.Request; @@ -42,7 +44,8 @@ public class InfoActionTest { Monitor monitor1 = mock(Monitor.class); Monitor monitor2 = mock(Monitor.class); - InfoAction underTest = new InfoAction(userSessionRule, monitor1, monitor2); + Monitor monitor3 = mock(Monitor.class); + InfoAction underTest = new InfoAction(userSessionRule, monitor1, monitor2, monitor3); @Test(expected = ForbiddenException.class) public void should_fail_when_does_not_have_admin_right() { @@ -55,18 +58,21 @@ public class InfoActionTest { public void write_json() { userSessionRule.setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); - LinkedHashMap attributes1 = new LinkedHashMap<>(); + Map attributes1 = new LinkedHashMap<>(); attributes1.put("foo", "bar"); - LinkedHashMap attributes2 = new LinkedHashMap<>(); + Map attributes2 = new LinkedHashMap<>(); attributes2.put("one", 1); attributes2.put("two", 2); when(monitor1.name()).thenReturn("Monitor One"); - when(monitor1.attributes()).thenReturn(attributes1); + when(monitor1.attributes()).thenReturn(Optional.of(attributes1)); when(monitor2.name()).thenReturn("Monitor Two"); - when(monitor2.attributes()).thenReturn(attributes2); + when(monitor2.attributes()).thenReturn(Optional.of(attributes2)); + when(monitor3.name()).thenReturn("Monitor Three"); + when(monitor3.attributes()).thenReturn(Optional.>absent()); WsTester.TestResponse response = new WsTester.TestResponse(); underTest.handle(new SimpleGetRequest(), response); + // response does not contain empty "Monitor Three" assertThat(response.outputAsString()).isEqualTo("{\"Monitor One\":{\"foo\":\"bar\"},\"Monitor Two\":{\"one\":1,\"two\":2}}"); } } diff --git a/server/sonar-web/src/main/js/apps/system/main.js b/server/sonar-web/src/main/js/apps/system/main.js index ea003bb7de6..65cafba2d93 100644 --- a/server/sonar-web/src/main/js/apps/system/main.js +++ b/server/sonar-web/src/main/js/apps/system/main.js @@ -25,7 +25,7 @@ import { translate } from '../../helpers/l10n'; import RestartModal from '../../components/RestartModal'; const SECTIONS_ORDER = ['SonarQube', 'Database', 'Plugins', 'System', 'Elasticsearch State', 'Elasticsearch', - 'Compute Engine Tasks', 'Compute Engine State', 'Compute Engine Database', 'JvmProperties']; + 'Compute Engine Tasks', 'Compute Engine State', 'Compute Engine Database Connection', 'JvmProperties']; export default React.createClass({ componentDidMount() { -- 2.39.5