aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-process
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-03-31 12:20:55 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-04-05 09:58:04 +0200
commit975158a5a726aa67c093f85779ac2c97efd03bb8 (patch)
treef2feb4851f4a0e2a6723e20d182413a01aeffade /server/sonar-process
parent87d559b07cdc6727dafe0c9e1286b30c8e7867ea (diff)
downloadsonarqube-975158a5a726aa67c093f85779ac2c97efd03bb8.tar.gz
sonarqube-975158a5a726aa67c093f85779ac2c97efd03bb8.zip
SONAR-7436 replace JMX/RMI by HTTP
Diffstat (limited to 'server/sonar-process')
-rw-r--r--server/sonar-process/pom.xml18
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java28
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java8
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/Jmx.java (renamed from server/sonar-process/src/main/java/org/sonar/process/jmx/Jmx.java)2
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java4
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java14
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/jmx/CeDatabaseMBean.java43
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/jmx/CeTasksMBean.java55
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java99
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java67
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java65
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java104
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoSection.java (renamed from server/sonar-process/src/main/java/org/sonar/process/jmx/EsSettingsMBean.java)18
-rw-r--r--server/sonar-process/src/main/java/org/sonar/process/systeminfo/package-info.java (renamed from server/sonar-process/src/main/java/org/sonar/process/jmx/package-info.java)2
-rw-r--r--server/sonar-process/src/main/protobuf/process_system_info.proto43
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java4
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/JmxTest.java (renamed from server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTest.java)12
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java91
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java98
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java71
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java58
-rw-r--r--server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java89
22 files changed, 415 insertions, 578 deletions
diff --git a/server/sonar-process/pom.xml b/server/sonar-process/pom.xml
index 3bd9cfc33d7..ee7d279fc2f 100644
--- a/server/sonar-process/pom.xml
+++ b/server/sonar-process/pom.xml
@@ -29,12 +29,23 @@
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
-
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <!-- only if org.sonar.process.systeminfo HTTP server is being used -->
+ <groupId>org.nanohttpd</groupId>
+ <artifactId>nanohttpd</artifactId>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <!-- only if org.sonar.process.systeminfo.protobuf classes are used -->
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <optional>true</optional>
+ </dependency>
<dependency>
<groupId>${project.groupId}</groupId>
@@ -56,6 +67,11 @@
<artifactId>jetty-server</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java b/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
index 9652aca6795..f5e0954f6ff 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/AllProcessesCommands.java
@@ -69,11 +69,11 @@ public class AllProcessesCommands implements AutoCloseable {
private static final int RESTART_BYTE_OFFSET = 2;
private static final int OPERATIONAL_BYTE_OFFSET = 3;
private static final int PING_BYTE_OFFSET = 4;
- private static final int JMX_URL_BYTE_OFFSET = PING_BYTE_OFFSET + 8;
+ private static final int SYSTEM_INFO_URL_BYTE_OFFSET = PING_BYTE_OFFSET + 8;
- private static final int JMX_URL_SIZE_IN_BYTES = 500;
+ private static final int SYSTEM_INFO_URL_SIZE_IN_BYTES = 500;
- private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 1 + 1 + 8 + JMX_URL_SIZE_IN_BYTES;
+ private static final int BYTE_LENGTH_FOR_ONE_PROCESS = 1 + 1 + 1 + 1 + 8 + SYSTEM_INFO_URL_SIZE_IN_BYTES;
// With this shared memory we can handle up to MAX_PROCESSES processes
private static final int MAX_SHARED_MEMORY = BYTE_LENGTH_FOR_ONE_PROCESS * MAX_PROCESSES;
@@ -148,17 +148,17 @@ public class AllProcessesCommands implements AutoCloseable {
return readLong(processNumber, PING_BYTE_OFFSET);
}
- String getJmxUrl(int processNumber) {
- byte[] urlBytes = readBytes(processNumber, JMX_URL_BYTE_OFFSET, JMX_URL_SIZE_IN_BYTES);
+ String getSystemInfoUrl(int processNumber) {
+ byte[] urlBytes = readBytes(processNumber, SYSTEM_INFO_URL_BYTE_OFFSET, SYSTEM_INFO_URL_SIZE_IN_BYTES);
return new String(urlBytes, StandardCharsets.US_ASCII).trim();
}
- void setJmxUrl(int processNumber, String jmxUrl) {
- byte[] urlBytes = rightPad(jmxUrl, JMX_URL_SIZE_IN_BYTES).getBytes(StandardCharsets.US_ASCII);
- if (urlBytes.length > JMX_URL_SIZE_IN_BYTES) {
- throw new IllegalArgumentException(format("JMX URL is too long. Max is %d bytes. Got: %s", JMX_URL_SIZE_IN_BYTES, jmxUrl));
+ void setSystemInfoUrl(int processNumber, String url) {
+ byte[] urlBytes = rightPad(url, SYSTEM_INFO_URL_SIZE_IN_BYTES).getBytes(StandardCharsets.US_ASCII);
+ if (urlBytes.length > SYSTEM_INFO_URL_SIZE_IN_BYTES) {
+ throw new IllegalArgumentException(format("System Info URL is too long. Max is %d bytes. Got: %s", SYSTEM_INFO_URL_SIZE_IN_BYTES, url));
}
- writeBytes(processNumber, JMX_URL_BYTE_OFFSET, urlBytes);
+ writeBytes(processNumber, SYSTEM_INFO_URL_BYTE_OFFSET, urlBytes);
}
/**
@@ -277,13 +277,13 @@ public class AllProcessesCommands implements AutoCloseable {
}
@Override
- public void setJmxUrl(String s) {
- AllProcessesCommands.this.setJmxUrl(processNumber, s);
+ public void setSystemInfoUrl(String s) {
+ AllProcessesCommands.this.setSystemInfoUrl(processNumber, s);
}
@Override
- public String getJmxUrl() {
- return AllProcessesCommands.this.getJmxUrl(processNumber);
+ public String getSystemInfoUrl() {
+ return AllProcessesCommands.this.getSystemInfoUrl(processNumber);
}
@Override
diff --git a/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java b/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java
index d8c9975a4ba..dade6ab6265 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/DefaultProcessCommands.java
@@ -83,13 +83,13 @@ public class DefaultProcessCommands implements ProcessCommands {
}
@Override
- public void setJmxUrl(String s) {
- delegate.setJmxUrl(s);
+ public void setSystemInfoUrl(String s) {
+ delegate.setSystemInfoUrl(s);
}
@Override
- public String getJmxUrl() {
- return delegate.getJmxUrl();
+ public String getSystemInfoUrl() {
+ return delegate.getSystemInfoUrl();
}
@Override
diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/Jmx.java b/server/sonar-process/src/main/java/org/sonar/process/Jmx.java
index 62375a32e83..76a7b03c639 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/Jmx.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/Jmx.java
@@ -17,7 +17,7 @@
* 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;
+package org.sonar.process;
import java.lang.management.ManagementFactory;
import javax.management.InstanceAlreadyExistsException;
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
index 01ece9a7060..9c2f4a35a62 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessCommands.java
@@ -55,9 +55,9 @@ public interface ProcessCommands extends AutoCloseable {
long getLastPing();
- void setJmxUrl(String s);
+ void setSystemInfoUrl(String s);
- String getJmxUrl();
+ String getSystemInfoUrl();
/**
* To be executed by monitor process to ask for child process termination
diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java
index f77cc7c292a..2ca262205ce 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessEntryPoint.java
@@ -22,7 +22,6 @@ package org.sonar.process;
import java.io.File;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import sun.misc.VMSupport;
public class ProcessEntryPoint implements Stoppable {
@@ -107,10 +106,6 @@ public class ProcessEntryPoint implements Stoppable {
Thread.sleep(20L);
}
- String jmxUrl = guessJmxUrl();
- logger.debug("JMX URL is {}", jmxUrl);
- commands.setJmxUrl(jmxUrl);
-
// notify monitor that process is ready
commands.setUp();
@@ -125,15 +120,6 @@ public class ProcessEntryPoint implements Stoppable {
}
}
- private static String guessJmxUrl() {
- // this property is set by the agent management-agent.jar enabled by org.sonar.process.monitor.JavaProcessLauncher.
- String jmxUrl = VMSupport.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress");
- if (jmxUrl == null) {
- throw new IllegalStateException("Fail to load the JMX URL of JVM " + System.getProperty("java.vm.name"));
- }
- return jmxUrl;
- }
-
boolean isStarted() {
return lifecycle.getState() == Lifecycle.State.STARTED;
}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeDatabaseMBean.java b/server/sonar-process/src/main/java/org/sonar/process/jmx/CeDatabaseMBean.java
deleted file mode 100644
index 354ce0db734..00000000000
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeDatabaseMBean.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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;
-
-public interface CeDatabaseMBean {
-
- String OBJECT_NAME = "SonarQube:name=ComputeEngineDatabase";
-
- int getPoolActiveConnections();
-
- int getPoolMaxActiveConnections();
-
- int getPoolIdleConnections();
-
- int getPoolMaxIdleConnections();
-
- int getPoolMinIdleConnections();
-
- int getPoolInitialSize();
-
- long getPoolMaxWaitMillis();
-
- boolean getPoolRemoveAbandoned();
-
- int getPoolRemoveAbandonedTimeoutSeconds();
-}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeTasksMBean.java b/server/sonar-process/src/main/java/org/sonar/process/jmx/CeTasksMBean.java
deleted file mode 100644
index 968dabc52b2..00000000000
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/CeTasksMBean.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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;
-
-public interface CeTasksMBean {
-
- String OBJECT_NAME = "SonarQube:name=ComputeEngineTasks";
-
- /**
- * Count of batch reports waiting for processing since startup, including reports received before instance startup.
- */
- long getPendingCount();
-
- /**
- * Count of batch reports under processing.
- */
- long getInProgressCount();
-
- /**
- * Count of batch reports which processing ended with an error since instance startup.
- */
- long getErrorCount();
-
- /**
- * Count of batch reports which processing ended successfully since instance startup.
- */
- long getSuccessCount();
-
- /**
- * Time spent processing reports since startup, in milliseconds.
- */
- long getProcessingTime();
-
- /**
- * Configured number of Workers.
- */
- int getWorkerCount();
-}
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
deleted file mode 100644
index 4c2eaca5452..00000000000
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnection.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.IOException;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryMXBean;
-import java.lang.management.MemoryUsage;
-import java.lang.management.ThreadMXBean;
-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;
- private final JMXConnector jmxConnector;
-
- JmxConnection(JMXConnector jmxConnector) {
- this.jmxConnector = jmxConnector;
- }
-
- /**
- * Get a MBean from a remote JMX server.
- * @throws IllegalStateException if a valid
- * connection to remote server cannot be created, for instance because the connection to has
- * not yet been established (with {@link JMXConnector#connect()}), or it has been closed/broken.
- */
- public <M> M getMBean(String mBeanName, Class<M> mBeanInterfaceClass) {
- try {
- MBeanServerConnection connection = jmxConnector.getMBeanServerConnection();
- if (mBeanName.startsWith("java.lang")) {
- return ManagementFactory.newPlatformMXBeanProxy(connection, mBeanName, mBeanInterfaceClass);
- }
- return JMX.newMBeanProxy(connection, new ObjectName(mBeanName), mBeanInterfaceClass);
- } catch (Exception e) {
- throw new IllegalStateException(format("Fail to connect to MBean [%s]", mBeanName), e);
- }
- }
-
- public Map<String, Object> getSystemState() {
- Map<String, Object> props = new LinkedHashMap<>();
- MemoryMXBean memory = getMBean(ManagementFactory.MEMORY_MXBEAN_NAME, MemoryMXBean.class);
- MemoryUsage heap = memory.getHeapMemoryUsage();
- props.put("Heap Committed (MB)", toMegaBytes(heap.getCommitted()));
- props.put("Heap Init (MB)", toMegaBytes(heap.getInit()));
- props.put("Heap Max (MB)", toMegaBytes(heap.getMax()));
- props.put("Heap Used (MB)", toMegaBytes(heap.getUsed()));
- MemoryUsage nonHeap = memory.getNonHeapMemoryUsage();
- props.put("Non Heap Committed (MB)", toMegaBytes(nonHeap.getCommitted()));
- props.put("Non Heap Init (MB)", toMegaBytes(nonHeap.getInit()));
- props.put("Non Heap Max (MB)", toMegaBytes(nonHeap.getMax()));
- props.put("Non Heap Used (MB)", toMegaBytes(nonHeap.getUsed()));
- ThreadMXBean thread = getMBean(ManagementFactory.THREAD_MXBEAN_NAME, ThreadMXBean.class);
- props.put("Thread Count", thread.getThreadCount());
- return props;
- }
-
- // visible for testing
- @CheckForNull
- static Long toMegaBytes(long bytes) {
- if (bytes < 0L) {
- return null;
- }
- return bytes / MEGABYTE;
- }
-
- @Override
- public void close() {
- try {
- jmxConnector.close();
- } catch (IOException e) {
- throw new IllegalStateException("Can not close JMX connector", e);
- }
- }
-}
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
deleted file mode 100644
index 29383cc211e..00000000000
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/JmxConnectionFactory.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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 javax.annotation.CheckForNull;
-import javax.annotation.concurrent.Immutable;
-import javax.management.remote.JMXConnector;
-import javax.management.remote.JMXConnectorFactory;
-import javax.management.remote.JMXServiceURL;
-import org.sonar.process.DefaultProcessCommands;
-import org.sonar.process.ProcessEntryPoint;
-import org.sonar.process.ProcessId;
-import org.sonar.process.Props;
-
-/**
- * Connects to JMX of other JVM processes
- */
-@Immutable
-public class JmxConnectionFactory {
- private final File ipcSharedDir;
-
- public JmxConnectionFactory(File ipcSharedDir) {
- this.ipcSharedDir = ipcSharedDir;
- }
-
- public JmxConnectionFactory(Props props) {
- this.ipcSharedDir = props.nonNullValueAsFile(ProcessEntryPoint.PROPERTY_SHARED_PATH);
- }
-
- @CheckForNull
- public JmxConnection create(ProcessId processId) {
- try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(ipcSharedDir, processId.getIpcIndex())) {
- 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/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java
new file mode 100644
index 00000000000..1ca9297ee33
--- /dev/null
+++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/ProcessStateSystemInfo.java
@@ -0,0 +1,65 @@
+/*
+ * 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.systeminfo;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.ThreadMXBean;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+public class ProcessStateSystemInfo implements SystemInfoSection {
+ private static final long MEGABYTE = 1024L * 1024L;
+ private final String name;
+
+ public ProcessStateSystemInfo(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public ProtobufSystemInfo.Section toProtobuf() {
+ return toProtobuf(ManagementFactory.getMemoryMXBean());
+ }
+
+ // Visible for testing
+ ProtobufSystemInfo.Section toProtobuf(MemoryMXBean memoryBean) {
+ ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder();
+ builder.setName(name);
+ MemoryUsage heap = memoryBean.getHeapMemoryUsage();
+ addAttributeInMb(builder, "Heap Committed (MB)", heap.getCommitted());
+ addAttributeInMb(builder, "Heap Init (MB)", heap.getInit());
+ addAttributeInMb(builder, "Heap Max (MB)", heap.getMax());
+ addAttributeInMb(builder, "Heap Used (MB)", heap.getUsed());
+ MemoryUsage nonHeap = memoryBean.getNonHeapMemoryUsage();
+ addAttributeInMb(builder, "Non Heap Committed (MB)", nonHeap.getCommitted());
+ addAttributeInMb(builder, "Non Heap Init (MB)", nonHeap.getInit());
+ addAttributeInMb(builder, "Non Heap Max (MB)", nonHeap.getMax());
+ addAttributeInMb(builder, "Non Heap Used (MB)", nonHeap.getUsed());
+ ThreadMXBean thread = ManagementFactory.getThreadMXBean();
+ builder.addAttributesBuilder().setKey("Thread Count").setLongValue(thread.getThreadCount()).build();
+ return builder.build();
+ }
+
+ private void addAttributeInMb(ProtobufSystemInfo.Section.Builder builder, String key, long valueInBytes) {
+ if (valueInBytes >= 0L) {
+ builder.addAttributesBuilder().setKey(key).setLongValue(valueInBytes / MEGABYTE).build();
+ }
+ }
+}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java
new file mode 100644
index 00000000000..b8c08f3b90c
--- /dev/null
+++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoHttpServer.java
@@ -0,0 +1,104 @@
+/*
+ * 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.systeminfo;
+
+import fi.iki.elonen.NanoHTTPD;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Properties;
+import org.slf4j.LoggerFactory;
+import org.sonar.process.DefaultProcessCommands;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static java.lang.Integer.parseInt;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
+
+/**
+ * This HTTP server exports data required for display of System Info page (and the related web service).
+ * It listens on loopback address only, so it does not need to be secure (no HTTPS, no authentication).
+ */
+public class SystemInfoHttpServer {
+
+ private static final String PROTOBUF_MIME_TYPE = "application/x-protobuf";
+
+ private final Properties processProps;
+ private final List<SystemInfoSection> sectionProviders;
+ private final SystemInfoNanoHttpd nanoHttpd;
+
+ public SystemInfoHttpServer(Properties processProps, List<SystemInfoSection> sectionProviders) throws UnknownHostException {
+ this.processProps = processProps;
+ this.sectionProviders = sectionProviders;
+ InetAddress loopbackAddress = InetAddress.getByName(null);
+ this.nanoHttpd = new SystemInfoNanoHttpd(loopbackAddress.getHostAddress(), 0);
+ }
+
+ // do not rename. This naming convention is required for picocontainer.
+ public void start() {
+ try {
+ nanoHttpd.start();
+ registerHttpUrl();
+ } catch (IOException e) {
+ throw new IllegalStateException("Can not start local HTTP server for System Info monitoring", e);
+ }
+ }
+
+ private void registerHttpUrl() {
+ int processNumber = parseInt(processProps.getProperty(PROPERTY_PROCESS_INDEX));
+ File shareDir = new File(processProps.getProperty(PROPERTY_SHARED_PATH));
+ try (DefaultProcessCommands commands = DefaultProcessCommands.secondary(shareDir, processNumber)) {
+ String url = getUrl();
+ commands.setSystemInfoUrl(url);
+ LoggerFactory.getLogger(getClass()).debug("System Info HTTP server listening at {}", url);
+ }
+ }
+
+ // do not rename. This naming convention is required for picocontainer.
+ public void stop() {
+ nanoHttpd.stop();
+ }
+
+ // visible for testing
+ String getUrl() {
+ return "http://" + nanoHttpd.getHostname() + ":" + nanoHttpd.getListeningPort();
+ }
+
+ private class SystemInfoNanoHttpd extends NanoHTTPD {
+
+ SystemInfoNanoHttpd(String hostname, int port) {
+ super(hostname, port);
+ }
+
+ @Override
+ public Response serve(IHTTPSession session) {
+ ProtobufSystemInfo.SystemInfo.Builder infoBuilder = ProtobufSystemInfo.SystemInfo.newBuilder();
+ for (SystemInfoSection sectionProvider : sectionProviders) {
+ ProtobufSystemInfo.Section section = sectionProvider.toProtobuf();
+ infoBuilder.addSections(section);
+ }
+ byte[] bytes = infoBuilder.build().toByteArray();
+ return newFixedLengthResponse(Response.Status.OK, PROTOBUF_MIME_TYPE, new ByteArrayInputStream(bytes), bytes.length);
+ }
+ }
+}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/EsSettingsMBean.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoSection.java
index 197dc35051c..c990cacb96b 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/EsSettingsMBean.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/SystemInfoSection.java
@@ -17,22 +17,12 @@
* 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;
+package org.sonar.process.systeminfo;
-/**
- * MBean registered in the Elasticsearch process
- */
-public interface EsSettingsMBean {
-
- String OBJECT_NAME = "SonarQube:name=ElasticsearchSettings";
-
- /**
- * @return the enabled HTTP port, -1 if disabled
- */
- int getHttpPort();
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
- String getClusterName();
+public interface SystemInfoSection {
- String getNodeName();
+ ProtobufSystemInfo.Section toProtobuf();
}
diff --git a/server/sonar-process/src/main/java/org/sonar/process/jmx/package-info.java b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/package-info.java
index bb4fb97207f..3ae1af74953 100644
--- a/server/sonar-process/src/main/java/org/sonar/process/jmx/package-info.java
+++ b/server/sonar-process/src/main/java/org/sonar/process/systeminfo/package-info.java
@@ -18,6 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
@ParametersAreNonnullByDefault
-package org.sonar.process.jmx;
+package org.sonar.process.systeminfo;
import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-process/src/main/protobuf/process_system_info.proto b/server/sonar-process/src/main/protobuf/process_system_info.proto
new file mode 100644
index 00000000000..8780b677596
--- /dev/null
+++ b/server/sonar-process/src/main/protobuf/process_system_info.proto
@@ -0,0 +1,43 @@
+// SonarQube, open source software quality management tool.
+// Copyright (C) 2008-2016 SonarSource
+// mailto:contact AT sonarsource DOT com
+//
+// SonarQube 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.
+//
+// SonarQube 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.
+
+syntax = "proto3";
+
+option java_package = "org.sonar.process.systeminfo.protobuf";
+option java_outer_classname = "ProtobufSystemInfo";
+
+option optimize_for = SPEED;
+
+message SystemInfo {
+ repeated Section sections = 1;
+}
+
+message Section {
+ string name = 1;
+ repeated Attribute attributes = 2;
+}
+
+message Attribute {
+ string key = 1;
+ oneof value {
+ bool boolean_value = 2;
+ int64 long_value = 3;
+ double double_value = 4;
+ string string_value = 5;
+ }
+}
diff --git a/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java b/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java
index e834fce905f..1c26836fc1e 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/AllProcessesCommandsTest.java
@@ -105,9 +105,9 @@ public class AllProcessesCommandsTest {
assertThat(readByte(commands, offset + i)).isEqualTo(EMPTY);
}
- commands.setJmxUrl(PROCESS_NUMBER, "jmx:foo");
+ commands.setSystemInfoUrl(PROCESS_NUMBER, "jmx:foo");
assertThat(readByte(commands, offset)).isNotEqualTo(EMPTY);
- assertThat(commands.getJmxUrl(PROCESS_NUMBER)).isEqualTo("jmx:foo");
+ assertThat(commands.getSystemInfoUrl(PROCESS_NUMBER)).isEqualTo("jmx:foo");
}
@Test
diff --git a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTest.java b/server/sonar-process/src/test/java/org/sonar/process/JmxTest.java
index 9b241accac3..7df06238d94 100644
--- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTest.java
+++ b/server/sonar-process/src/test/java/org/sonar/process/JmxTest.java
@@ -17,7 +17,7 @@
* 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;
+package org.sonar.process;
import java.lang.management.ManagementFactory;
import javax.annotation.CheckForNull;
@@ -27,6 +27,8 @@ import javax.management.ObjectName;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.process.jmx.Fake;
+import org.sonar.process.jmx.FakeMBean;
import static org.assertj.core.api.Assertions.assertThat;
@@ -65,6 +67,14 @@ public class JmxTest {
}
@Test
+ public void register_fails_if_name_is_not_valid() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Can not register MBean [/]");
+
+ Jmx.register("/", new Fake());
+ }
+
+ @Test
public void support_implementation_in_different_package_than_interface() throws Exception {
assertThat(lookupMBean()).isNull();
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
deleted file mode 100644
index 4709acb83d3..00000000000
--- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionFactoryTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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
deleted file mode 100644
index efb7f83701f..00000000000
--- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxConnectionTest.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.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();
- assertThat(JmxConnection.toMegaBytes(0L)).isEqualTo(0L);
- assertThat(JmxConnection.toMegaBytes(500L)).isEqualTo(0L);
- 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<String, Object> 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
deleted file mode 100644
index 9ffe8413bef..00000000000
--- a/server/sonar-process/src/test/java/org/sonar/process/jmx/JmxTestServer.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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<String, Object>(), 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-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java
new file mode 100644
index 00000000000..b1088a07584
--- /dev/null
+++ b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/ProcessStateSystemInfoTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.systeminfo;
+
+import java.lang.management.MemoryMXBean;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ProcessStateSystemInfoTest {
+
+ public static final String PROCESS_NAME = "the process name";
+
+ @Test
+ public void toSystemInfoSection() {
+ ProcessStateSystemInfo underTest = new ProcessStateSystemInfo(PROCESS_NAME);
+ ProtobufSystemInfo.Section section = underTest.toProtobuf();
+
+ assertThat(section.getName()).isEqualTo(PROCESS_NAME);
+ assertThat(section.getAttributesCount()).isEqualTo(9);
+ assertThat(section.getAttributes(0).getKey()).isEqualTo("Heap Committed (MB)");
+ assertThat(section.getAttributes(0).getLongValue()).isGreaterThan(1L);
+ assertThat(section.getAttributes(8).getKey()).isEqualTo("Thread Count");
+ assertThat(section.getAttributes(8).getLongValue()).isGreaterThan(1L);
+ }
+
+ @Test
+ public void should_hide_attributes_without_values() {
+ MemoryMXBean memoryBean = mock(MemoryMXBean.class, Mockito.RETURNS_DEEP_STUBS);
+ when(memoryBean.getHeapMemoryUsage().getCommitted()).thenReturn(-1L);
+
+ ProcessStateSystemInfo underTest = new ProcessStateSystemInfo(PROCESS_NAME);
+ ProtobufSystemInfo.Section section = underTest.toProtobuf(memoryBean);
+
+ assertThat(section.getAttributesList()).extracting("key").doesNotContain("Heap Committed (MB)");
+ }
+}
diff --git a/server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java
new file mode 100644
index 00000000000..31f7f48f08f
--- /dev/null
+++ b/server/sonar-process/src/test/java/org/sonar/process/systeminfo/SystemInfoHttpServerTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.systeminfo;
+
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.Response;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.util.Arrays;
+import java.util.Properties;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_PROCESS_INDEX;
+import static org.sonar.process.ProcessEntryPoint.PROPERTY_SHARED_PATH;
+
+public class SystemInfoHttpServerTest {
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ SystemInfoSection stateProvider1 = new ProcessStateSystemInfo("state1");
+ SystemInfoSection stateProvider2 = new ProcessStateSystemInfo("state2");
+ SystemInfoHttpServer underTest;
+
+ @Before
+ public void setUp() throws Exception {
+ Properties properties = new Properties();
+ properties.setProperty(PROPERTY_PROCESS_INDEX, "1");
+ properties.setProperty(PROPERTY_SHARED_PATH, temp.newFolder().getAbsolutePath());
+ underTest = new SystemInfoHttpServer(properties, Arrays.asList(stateProvider1, stateProvider2));
+ }
+
+ @After
+ public void tearDown() {
+ underTest.stop();
+ }
+
+ @Test
+ public void start_starts_http_server_and_publishes_URL_in_IPC() throws Exception {
+ underTest.start();
+ Response response = call(underTest.getUrl());
+ assertThat(response.code()).isEqualTo(200);
+ ProtobufSystemInfo.SystemInfo systemInfo = ProtobufSystemInfo.SystemInfo.parseFrom(response.body().bytes());
+ assertThat(systemInfo.getSectionsCount()).isEqualTo(2);
+ assertThat(systemInfo.getSections(0).getName()).isEqualTo("state1");
+ assertThat(systemInfo.getSections(1).getName()).isEqualTo("state2");
+ }
+
+ @Test
+ public void stop_stops_http_server() throws Exception {
+ underTest.start();
+ underTest.stop();
+ expectedException.expect(ConnectException.class);
+ call(underTest.getUrl());
+ }
+
+ private static Response call(String url) throws IOException {
+ Request request = new Request.Builder().get().url(url).build();
+ return new OkHttpClient().newCall(request).execute();
+ }
+}