summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2015-02-18 17:39:40 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2015-02-22 23:00:00 +0100
commitc4e7fb294ca6b445db2a59336913642dd7273f2b (patch)
tree39de9ec1fecf7fb30e5c9249f13752de29774253 /server
parentd50911dd0c6e8ce6618efc15acfdd52f082c9358 (diff)
downloadsonarqube-c4e7fb294ca6b445db2a59336913642dd7273f2b.tar.gz
sonarqube-c4e7fb294ca6b445db2a59336913642dd7273f2b.zip
Technical monitoring of web server - SONAR-4318 SONAR-5936
Diffstat (limited to 'server')
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java61
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java145
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitorMBean.java72
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitor.java99
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitorMBean.java27
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitor.java109
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitorMBean.java26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitor.java41
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java29
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java61
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java104
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitorMBean.java29
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java171
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java73
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemRestartWsAction.java (renamed from server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartHandler.java)26
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWs.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWsAction.java29
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/NodeHealth.java123
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/BaseMonitorMBeanTest.java61
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java61
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java40
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitorMBean.java24
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitorTest.java37
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java80
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java46
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java43
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java71
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemRestartWsActionTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartHandlerTest.java)44
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java14
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb18
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/controllers/system_controller.rb15
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/models/server.rb39
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/system/index.html.erb58
35 files changed, 1679 insertions, 239 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java b/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java
index 94066a1eaa9..8dcd286c73a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/DatabaseServerCompatibility.java
@@ -36,7 +36,7 @@ public class DatabaseServerCompatibility implements Startable {
public void start() {
DatabaseVersion.Status status = version.getStatus();
if (status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
- throw MessageException.of("Database relates to a more recent version of sonar. Please check your settings.");
+ throw MessageException.of("Database relates to a more recent version of SonarQube. Please check your settings.");
}
if (status == DatabaseVersion.Status.REQUIRES_UPGRADE) {
Loggers.get(DatabaseServerCompatibility.class).warn("Database must be upgraded. Please browse /setup");
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 288a7cbee5b..7965e3f04a9 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -140,10 +140,8 @@ import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.InternalPermissionTemplateService;
import org.sonar.server.permission.PermissionFinder;
import org.sonar.server.permission.ws.PermissionsWs;
-import org.sonar.server.platform.ws.L10nWs;
-import org.sonar.server.platform.ws.RestartHandler;
-import org.sonar.server.platform.ws.ServerWs;
-import org.sonar.server.platform.ws.SystemWs;
+import org.sonar.server.platform.monitoring.*;
+import org.sonar.server.platform.ws.*;
import org.sonar.server.plugins.*;
import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.qualitygate.QgateProjectFinder;
@@ -308,11 +306,7 @@ class ServerComponents {
JRubyI18n.class,
DefaultI18n.class,
RuleI18nManager.class,
- Durations.class,
-
- // ws
- RestartHandler.class,
- SystemWs.class
+ Durations.class
);
}
@@ -638,6 +632,20 @@ class ServerComponents {
// Design
pico.addSingleton(FileDesignWidget.class);
+ // System
+ pico.addSingletons(Arrays.asList(
+ SystemRestartWsAction.class,
+ SystemInfoWsAction.class,
+ SystemWs.class,
+ SystemMonitor.class,
+ SonarQubeMonitor.class,
+ EsClusterMonitor.class,
+ EsNodesMonitor.class,
+ PluginsMonitor.class,
+ JvmPropertiesMonitor.class,
+ DatabaseMonitor.class
+ ));
+
// Compute engine
pico.addSingleton(AnalysisReportQueue.class);
pico.addSingleton(ComputationThreadLauncher.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java
new file mode 100644
index 00000000000..6b982a7ba7d
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/BaseMonitorMBean.java
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import org.picocontainer.Startable;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.OperationsException;
+
+import java.lang.management.ManagementFactory;
+
+public abstract class BaseMonitorMBean implements Monitor, Startable {
+
+ /**
+ * Auto-registers to MBean server
+ */
+ @Override
+ public void start() {
+ try {
+ ManagementFactory.getPlatformMBeanServer().registerMBean(this, objectName());
+ } catch (OperationsException | MBeanRegistrationException e) {
+ throw new IllegalStateException("Fail to register MBean " + name(), e);
+ }
+ }
+
+ @Override
+ public void stop() {
+ try {
+ ManagementFactory.getPlatformMBeanServer().unregisterMBean(objectName());
+ } catch (InstanceNotFoundException ignored) {
+ // ignore, was not correctly started
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to unregister MBean " + name(), e);
+ }
+ }
+
+ ObjectName objectName() throws MalformedObjectNameException {
+ return new ObjectName(String.format("SonarQube:name=%s", name()));
+ }
+}
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
new file mode 100644
index 00000000000..9ce60700212
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitor.java
@@ -0,0 +1,145 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import org.apache.commons.dbcp.BasicDataSource;
+import org.apache.commons.dbutils.DbUtils;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.db.DbClient;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class DatabaseMonitor extends BaseMonitorMBean implements DatabaseMonitorMBean {
+
+ private final DatabaseVersion dbVersion;
+ private final DbClient dbClient;
+
+ public DatabaseMonitor(DatabaseVersion dbVersion, DbClient dbClient) {
+ this.dbVersion = dbVersion;
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ public String name() {
+ return "Database";
+ }
+
+ @Override
+ public String getMigrationStatus() {
+ return dbVersion.getStatus().name();
+ }
+
+ @Override
+ public int getPoolActiveConnections() {
+ return commonsDbcp().getNumActive();
+ }
+
+ @Override
+ public int getPoolMaxActiveConnections() {
+ return commonsDbcp().getMaxActive();
+ }
+
+ @Override
+ public int getPoolIdleConnections() {
+ return commonsDbcp().getNumIdle();
+ }
+
+ @Override
+ public int getPoolMaxIdleConnections() {
+ return commonsDbcp().getMaxIdle();
+ }
+
+ @Override
+ public int getPoolMinIdleConnections() {
+ return commonsDbcp().getMinIdle();
+ }
+
+ @Override
+ public int getPoolInitialSize() {
+ return commonsDbcp().getInitialSize();
+ }
+
+ @Override
+ public long getPoolMaxWaitMillis() {
+ return commonsDbcp().getMaxWait();
+ }
+
+ @Override
+ public boolean getPoolRemoveAbandoned() {
+ return commonsDbcp().getRemoveAbandoned();
+ }
+
+ @Override
+ public int getPoolRemoveAbandonedTimeoutSeconds() {
+ return commonsDbcp().getRemoveAbandonedTimeout();
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ completeDbAttributes(attributes);
+ completePoolAttributes(attributes);
+ return attributes;
+ }
+
+ private void completePoolAttributes(Map<String, Object> attributes) {
+ attributes.put("Pool Active Connections", getPoolActiveConnections());
+ attributes.put("Pool Max Connections", getPoolMaxActiveConnections());
+ attributes.put("Pool Initial Size", getPoolInitialSize());
+ attributes.put("Pool Idle Connections", getPoolIdleConnections());
+ attributes.put("Pool Min Idle Connections", getPoolMinIdleConnections());
+ attributes.put("Pool Max Idle Connections", getPoolMaxIdleConnections());
+ attributes.put("Pool Max Wait (ms)", getPoolMaxWaitMillis());
+ attributes.put("Pool Remove Abandoned", getPoolRemoveAbandoned());
+ attributes.put("Pool Remove Abandoned Timeout (seconds)", getPoolRemoveAbandonedTimeoutSeconds());
+ }
+
+ private BasicDataSource commonsDbcp() {
+ return (BasicDataSource) dbClient.database().getDataSource();
+ }
+
+ private void completeDbAttributes(Map<String, Object> attributes) {
+ DbSession dbSession = dbClient.openSession(false);
+ Connection connection = dbSession.getConnection();
+ try {
+ DatabaseMetaData metadata = connection.getMetaData();
+ attributes.put("Database", metadata.getDatabaseProductName());
+ attributes.put("Database Version", metadata.getDatabaseProductVersion());
+ attributes.put("Username", metadata.getUserName());
+ attributes.put("URL", metadata.getURL());
+ attributes.put("Driver", metadata.getDriverName());
+ attributes.put("Driver Version", metadata.getDriverVersion());
+ attributes.put("Version Status", getMigrationStatus());
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to get DB metadata", e);
+
+ } finally {
+ DbUtils.closeQuietly(connection);
+ MyBatis.closeQuietly(dbSession);
+ }
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitorMBean.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitorMBean.java
new file mode 100644
index 00000000000..e1a177a243a
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/DatabaseMonitorMBean.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+public interface DatabaseMonitorMBean {
+
+ /**
+ * Is database schema up-to-date or should it be upgraded ?
+ */
+ String getMigrationStatus();
+
+ /**
+ *
+ */
+ int getPoolActiveConnections();
+
+ /**
+ * The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit.
+ */
+ int getPoolMaxActiveConnections();
+
+ int getPoolIdleConnections();
+
+ /**
+ * The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit.
+ */
+ int getPoolMaxIdleConnections();
+
+ /**
+ * The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none.
+ */
+ int getPoolMinIdleConnections();
+
+ /**
+ * The initial number of connections that are created when the pool is started.
+ */
+ int getPoolInitialSize();
+
+ /**
+ * The maximum number of milliseconds that the pool will wait
+ * (when there are no available connections) for a connection to be returned before throwing an exception, or -1 to wait indefinitely.
+ */
+ long getPoolMaxWaitMillis();
+
+ /**
+ * Flag to remove abandoned connections if they exceed the {@link #getPoolRemoveAbandonedTimeoutSeconds()}.
+ */
+ boolean getPoolRemoveAbandoned();
+
+ /**
+ * Timeout in seconds before an abandoned connection can be removed.
+ */
+ int getPoolRemoveAbandonedTimeoutSeconds();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitor.java
new file mode 100644
index 00000000000..890a86f9b0c
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitor.java
@@ -0,0 +1,99 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import com.google.common.base.Joiner;
+import org.sonar.server.search.ClusterHealth;
+import org.sonar.server.search.IndexHealth;
+import org.sonar.server.search.SearchHealth;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static org.sonar.api.utils.DateUtils.formatDateTimeNullSafe;
+
+public class EsClusterMonitor extends BaseMonitorMBean
+ implements EsClusterMonitorMBean {
+
+ private final SearchHealth searchHealth;
+
+ public EsClusterMonitor(SearchHealth searchHealth) {
+ this.searchHealth = searchHealth;
+ }
+
+ @Override
+ public String getClusterState() {
+ return clusterHealth().isClusterAvailable() ? "Available" : "Unavailable";
+ }
+
+ @Override
+ public int getNumberOfNodes() {
+ return clusterHealth().getNumberOfNodes();
+ }
+
+ @Override
+ public String getIndexesHealth() {
+ Map<String, String> formattedIndexes = new HashMap<>();
+ for (Map.Entry<String, IndexHealth> healthEntry : searchHealth.getIndexHealth().entrySet()) {
+ formattedIndexes.put(healthEntry.getKey(), formatIndexHealth(healthEntry.getValue()));
+ }
+
+ return Joiner.on(" | ").withKeyValueSeparator(": ").join(formattedIndexes);
+ }
+
+ @Override
+ public String name() {
+ return "ElasticSearchCluster";
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ attributes.put("Cluster State", getClusterState());
+ attributes.put("Number of Nodes", getNumberOfNodes());
+ for (Map.Entry<String, IndexHealth> healthEntry : searchHealth.getIndexHealth().entrySet()) {
+ attributes.put(healthEntry.getKey() + " - Document Count", healthEntry.getValue().getDocumentCount());
+ attributes.put(healthEntry.getKey() + " - Last Sync", formatDateTimeNullSafe(healthEntry.getValue().getLastSynchronization()));
+ attributes.put(healthEntry.getKey() + " - Optimization", formatIndexHealthOptimisation(healthEntry.getValue()));
+ }
+ return attributes;
+ }
+
+ private String formatIndexHealthOptimisation(IndexHealth indexHealth) {
+ return indexHealth.isOptimized() ? "Optimized" : "Unoptimized " +
+ "(Segments: " + indexHealth.getSegmentcount() + ", Pending Deletions: "
+ + indexHealth.getPendingDeletion() + ")";
+ }
+
+ private ClusterHealth clusterHealth() {
+ return searchHealth.getClusterHealth();
+ }
+
+ private String formatIndexHealth(IndexHealth indexHealth) {
+ return new StringBuilder()
+ .append(indexHealth.getDocumentCount())
+ .append("/")
+ .append(formatDateTimeNullSafe(indexHealth.getLastSynchronization()))
+ .append("/")
+ .append(formatIndexHealthOptimisation(indexHealth)).toString();
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitorMBean.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitorMBean.java
new file mode 100644
index 00000000000..a51e29c7668
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsClusterMonitorMBean.java
@@ -0,0 +1,27 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+public interface EsClusterMonitorMBean {
+ String getClusterState();
+ int getNumberOfNodes();
+ String getIndexesHealth();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitor.java
new file mode 100644
index 00000000000..ead31204d55
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitor.java
@@ -0,0 +1,109 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import org.sonar.server.search.NodeHealth;
+import org.sonar.server.search.NodeHealth.Performance;
+import org.sonar.server.search.SearchHealth;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.commons.io.FileUtils.byteCountToDisplaySize;
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+
+public class EsNodesMonitor extends BaseMonitorMBean implements EsNodesMonitorMBean {
+
+ private final SearchHealth searchHealth;
+
+ public EsNodesMonitor(SearchHealth searchHealth) {
+ this.searchHealth = searchHealth;
+ }
+
+ @Override
+ public String getNodes() {
+ List<String> formattedNodes = new ArrayList<>();
+ Table<String, String, String> nodes = nodes();
+
+ for (String nodeName : nodes.rowKeySet()) {
+ StringBuilder formattedNode = new StringBuilder();
+ formattedNode.append(nodeName)
+ .append(" - ")
+ .append(Joiner.on(", ").withKeyValueSeparator(": ").join(nodes.row(nodeName)));
+ formattedNodes.add(formattedNode.toString());
+ }
+
+ return Joiner.on(" | ").join(formattedNodes);
+ }
+
+ @Override
+ public String name() {
+ return "ElasticSearchNodes";
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ Table<String, String, String> nodes = nodes();
+ for (String nodeName : nodes.rowKeySet()) {
+ attributes.put(nodeName, nodes.row(nodeName));
+ }
+ return attributes;
+ }
+
+ private Table<String, String, String> nodes() {
+ Table<String, String, String> nodes = HashBasedTable.create();
+ for (Map.Entry<String, NodeHealth> nodeEntry : searchHealth.getNodesHealth().entrySet()) {
+ String name = nodeEntry.getKey();
+ nodes.put(name, "Name", nodeEntry.getKey());
+ NodeHealth nodeHealth = nodeEntry.getValue();
+ nodes.put(name, "Type", nodeHealth.isMaster() ? "Master" : "Slave");
+ nodes.put(name, "Address", nodeHealth.getAddress());
+ nodes.put(name, "JVM Heap Usage", nodeHealth.getJvmHeapUsedPercent());
+ nodes.put(name, "JVM Threads", String.valueOf(nodeHealth.getJvmThreads()));
+ nodes.put(name, "JVM Started Since", formatDateTime(nodeHealth.getJvmUpSince()));
+ nodes.put(name, "Disk Usage", nodeHealth.getFsUsedPercent());
+ nodes.put(name, "Open Files", String.valueOf(nodeHealth.getOpenFiles()));
+ nodes.put(name, "CPU Load Average", nodeHealth.getProcessCpuPercent());
+ nodes.put(name, "Field Cache Size", byteCountToDisplaySize(nodeHealth.getFieldCacheMemory()));
+ nodes.put(name, "Filter Cache Size", byteCountToDisplaySize(nodeHealth.getFilterCacheMemory()));
+
+ for (Performance performance : nodeHealth.getPerformanceStats()) {
+ String message = "";
+ if (Performance.Status.ERROR.equals(performance.getStatus()) || Performance.Status.WARN.equals(performance.getStatus())) {
+ message = String.format("- %s: %s", performance.getStatus(), performance.getMessage());
+ }
+ if (performance.getName().contains("Eviction")) {
+ nodes.put(name, performance.getName(), String.format("%f %s", performance.getValue(), message));
+ } else {
+ nodes.put(name, performance.getName(), String.format("%.1f ms %s", performance.getValue(), message));
+ }
+ }
+ }
+
+ return nodes;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitorMBean.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitorMBean.java
new file mode 100644
index 00000000000..fc855255497
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/EsNodesMonitorMBean.java
@@ -0,0 +1,26 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+public interface EsNodesMonitorMBean {
+
+ String getNodes();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitor.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitor.java
new file mode 100644
index 00000000000..1d40dbd2d7e
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitor.java
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class JvmPropertiesMonitor implements Monitor {
+ @Override
+ public String name() {
+ return "JvmProperties";
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
+ attributes.put(Objects.toString(entry.getKey()), Objects.toString(entry.getValue()));
+ }
+ return attributes;
+ }
+}
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
new file mode 100644
index 00000000000..661c86dba07
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/Monitor.java
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.sonar.api.ServerComponent;
+
+import java.util.LinkedHashMap;
+
+public interface Monitor extends ServerComponent {
+ LinkedHashMap<String,Object> attributes();
+ String name();
+}
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
new file mode 100644
index 00000000000..ed93664394a
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/PluginsMonitor.java
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+
+public class PluginsMonitor implements Monitor {
+ private final PluginRepository repository;
+
+ public PluginsMonitor(PluginRepository repository) {
+ this.repository = repository;
+ }
+
+ @Override
+ public String name() {
+ return "Plugins";
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ for (PluginMetadata plugin : plugins()) {
+ attributes.put(plugin.getName(), plugin.getVersion());
+ }
+ return attributes;
+ }
+
+ private List<PluginMetadata> plugins() {
+ return Lists.newArrayList(Iterables.filter(repository.getMetadata(), new Predicate<PluginMetadata>() {
+ @Override
+ public boolean apply(PluginMetadata input) {
+ return !input.isCore();
+ }
+ }));
+ }
+}
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
new file mode 100644
index 00000000000..2846f282303
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitor.java
@@ -0,0 +1,104 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.api.security.SecurityRealm;
+import org.sonar.process.ProcessConstants;
+import org.sonar.server.user.SecurityRealmFactory;
+
+import java.util.LinkedHashMap;
+
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+
+public class SonarQubeMonitor extends BaseMonitorMBean implements SonarQubeMonitorMBean {
+
+ private final Settings settings;
+ private final SecurityRealmFactory securityRealmFactory;
+ private final Server server;
+
+ public SonarQubeMonitor(Settings settings, SecurityRealmFactory securityRealmFactory,
+ Server server) {
+ this.settings = settings;
+ this.securityRealmFactory = securityRealmFactory;
+ this.server = server;
+ }
+
+ @Override
+ public String getServerId() {
+ return settings.getString(CoreProperties.PERMANENT_SERVER_ID);
+ }
+
+ @Override
+ public String getVersion() {
+ return server.getVersion();
+ }
+
+ @Override
+ public String getStartedAt() {
+ return formatDateTime(server.getStartedAt());
+ }
+
+ public String getExternalUserAuthentication() {
+ SecurityRealm realm = securityRealmFactory.getRealm();
+ if (realm == null) {
+ return "";
+ }
+ return realm.getName();
+ }
+
+ public boolean getAutomaticUserCreation() {
+ return settings.getBoolean(CoreProperties.CORE_AUTHENTICATOR_CREATE_USERS);
+ }
+
+ public boolean getAllowUsersToSignUp() {
+ return settings.getBoolean(CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY);
+ }
+
+ public boolean getForceAuthentication() {
+ return settings.getBoolean(CoreProperties.CORE_FORCE_AUTHENTICATION_PROPERTY);
+ }
+
+ @Override
+ public String name() {
+ return "SonarQube";
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ attributes.put("Server ID", getServerId());
+ attributes.put("Version", getVersion());
+ attributes.put("Started at", getStartedAt());
+ attributes.put("External User Authentication", getExternalUserAuthentication());
+ attributes.put("Automatic User Creation", getAutomaticUserCreation());
+ attributes.put("Allow Users to Sign Up", getAllowUsersToSignUp());
+ attributes.put("Force authentication", getForceAuthentication());
+ attributes.put("Home Dir", settings.getString(ProcessConstants.PATH_HOME));
+ attributes.put("Data Dir", settings.getString(ProcessConstants.PATH_DATA));
+ attributes.put("Logs Dir", settings.getString(ProcessConstants.PATH_LOGS));
+ attributes.put("Temp Dir", settings.getString(ProcessConstants.PATH_TEMP));
+ return attributes;
+
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitorMBean.java b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitorMBean.java
new file mode 100644
index 00000000000..56b8f4744e7
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SonarQubeMonitorMBean.java
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+public interface SonarQubeMonitorMBean {
+ String getServerId();
+
+ String getVersion();
+
+ String getStartedAt();
+}
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
new file mode 100644
index 00000000000..b4ea751303c
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/monitoring/SystemMonitor.java
@@ -0,0 +1,171 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import org.sonar.api.utils.System2;
+
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
+import java.util.Date;
+import java.util.LinkedHashMap;
+
+import static org.sonar.api.utils.DateUtils.formatDateTime;
+
+public class SystemMonitor implements Monitor {
+ private final System2 system;
+
+ public SystemMonitor() {
+ this(System2.INSTANCE);
+ }
+
+ SystemMonitor(System2 system) {
+ this.system = system;
+ }
+
+ @Override
+ public String name() {
+ return "System";
+ }
+
+ public String getSystemDate() {
+ return formatDateTime(new Date(system.now()));
+ }
+
+ public String getJvmVendor() {
+ return runtimeMXBean().getVmVendor();
+ }
+
+ public String getJvmName() {
+ return runtimeMXBean().getVmName();
+ }
+
+ public String getJvmVersion() {
+ return runtimeMXBean().getVmVersion();
+ }
+
+ public int getProcessors() {
+ return runtime().availableProcessors();
+ }
+
+ public String getSystemClasspath() {
+ return runtimeMXBean().getClassPath();
+ }
+
+ public String getBootClasspath() {
+ return runtimeMXBean().getBootClassPath();
+ }
+
+ public String getLibraryPath() {
+ return runtimeMXBean().getLibraryPath();
+ }
+
+ public String getTotalMemory() {
+ return formatMemory(runtime().totalMemory());
+ }
+
+ public String getFreeMemory() {
+ return formatMemory(runtime().freeMemory());
+ }
+
+ public String getMaxMemory() {
+ return formatMemory(runtime().maxMemory());
+ }
+
+ public String getHeapMemory() {
+ return memoryMXBean().getHeapMemoryUsage().toString();
+ }
+
+ public String getNonHeapMemory() {
+ return memoryMXBean().getNonHeapMemoryUsage().toString();
+ }
+
+ public String getSystemLoadAverage() {
+ return String.format("%.1f%% (last minute)", ManagementFactory.getOperatingSystemMXBean().getSystemLoadAverage() * 100.0);
+ }
+
+ public String getLoadedClasses() {
+ return String.format("currently: %d, total: %d, unloaded: %d",
+ classLoadingMXBean().getLoadedClassCount(),
+ classLoadingMXBean().getTotalLoadedClassCount(),
+ classLoadingMXBean().getUnloadedClassCount());
+ }
+
+ public String getStartTime() {
+ return formatDateTime(new Date(runtimeMXBean().getStartTime()));
+ }
+
+ public String getThreads() {
+ return String.format("total: %d, peak: %d, daemon: %d",
+ threadMXBean().getThreadCount(),
+ threadMXBean().getPeakThreadCount(),
+ threadMXBean().getDaemonThreadCount());
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ LinkedHashMap<String, Object> attributes = new LinkedHashMap<>();
+ attributes.put("System Date", getSystemDate());
+ attributes.put("JVM Vendor", getJvmVendor());
+ attributes.put("JVM Name", getJvmName());
+ attributes.put("JVM Version", getJvmVersion());
+ attributes.put("Processors", getProcessors());
+ attributes.put("System Classpath", getSystemClasspath());
+ attributes.put("BootClassPath", getBootClasspath());
+ attributes.put("Library Path", getLibraryPath());
+ attributes.put("Total Memory", getTotalMemory());
+ attributes.put("Free Memory", getFreeMemory());
+ attributes.put("Max Memory", getMaxMemory());
+ attributes.put("Heap", getHeapMemory());
+ attributes.put("Non Heap", getNonHeapMemory());
+ attributes.put("System Load Average", getSystemLoadAverage());
+ attributes.put("Loaded Classes", getLoadedClasses());
+ attributes.put("Start Time", getStartTime());
+ attributes.put("Threads", getThreads());
+ return attributes;
+ }
+
+ private RuntimeMXBean runtimeMXBean() {
+ return ManagementFactory.getRuntimeMXBean();
+ }
+
+ private Runtime runtime() {
+ return Runtime.getRuntime();
+ }
+
+ private MemoryMXBean memoryMXBean() {
+ return ManagementFactory.getMemoryMXBean();
+ }
+
+ private ClassLoadingMXBean classLoadingMXBean() {
+ return ManagementFactory.getClassLoadingMXBean();
+ }
+
+ private ThreadMXBean threadMXBean() {
+ return ManagementFactory.getThreadMXBean();
+ }
+
+ private String formatMemory(long memoryInBytes) {
+ return String.format("%d MB", memoryInBytes / 1_000_000);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java
new file mode 100644
index 00000000000..05a85daa0f4
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemInfoWsAction.java
@@ -0,0 +1,73 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.platform.monitoring.Monitor;
+import org.sonar.server.user.UserSession;
+
+import java.util.Map;
+
+public class SystemInfoWsAction implements SystemWsAction {
+
+ private final Monitor[] monitors;
+
+ public SystemInfoWsAction(Monitor... monitors) {
+ this.monitors = monitors;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ controller.createAction("info")
+ .setDescription("Detailed information about system configuration")
+ .setSince("5.1")
+ .setHandler(this);
+ }
+
+ @Override
+ public void handle(Request request, Response response) {
+ UserSession.get().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);
+ JsonWriter json = response.newJsonWriter();
+ writeJson(json);
+ json.close();
+ }
+
+ private void writeJson(JsonWriter json) {
+ json.beginObject();
+ for (Monitor monitor : monitors) {
+ json.name(monitor.name());
+ json.beginObject();
+ for (Map.Entry<String, Object> attribute : monitor.attributes().entrySet()) {
+ json.name(attribute.getKey()).valueObject(attribute.getValue());
+ }
+ json.endObject();
+ }
+ json.endObject();
+ }
+
+ Monitor[] getMonitors() {
+ return monitors;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartHandler.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemRestartWsAction.java
index 79c0d51cbad..9227df4f4ac 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartHandler.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemRestartWsAction.java
@@ -22,31 +22,28 @@ package org.sonar.server.platform.ws;
import org.sonar.api.config.Settings;
import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.platform.Platform;
-public class RestartHandler implements RequestHandler {
+public class SystemRestartWsAction implements SystemWsAction {
private final Settings settings;
private final Platform platform;
- private final System2 system;
- public RestartHandler(Settings settings, Platform platform, System2 system) {
+ public SystemRestartWsAction(Settings settings, Platform platform) {
this.settings = settings;
this.platform = platform;
- this.system = system;
}
- void define(WebService.NewController controller) {
+ @Override
+ public void define(WebService.NewController controller) {
controller.createAction("restart")
- .setDescription("Restart server. Available only on development mode (sonar.web.dev=true), except when using Java 6 " +
- "on MS Windows. Ruby on Rails extensions are not reloaded")
+ .setDescription("Restart server. Available only on development mode (sonar.web.dev=true). " +
+ "Ruby on Rails extensions are not reloaded")
.setSince("4.3")
.setPost(true)
.setHandler(this);
@@ -54,7 +51,7 @@ public class RestartHandler implements RequestHandler {
@Override
public void handle(Request request, Response response) {
- if (canRestart()) {
+ if (settings.getBoolean("sonar.web.dev")) {
Logger logger = Loggers.get(getClass());
logger.info("Restart server");
platform.restart();
@@ -65,13 +62,4 @@ public class RestartHandler implements RequestHandler {
throw new ForbiddenException();
}
}
-
- private boolean canRestart() {
- boolean ok = settings.getBoolean("sonar.web.dev");
- if (ok) {
- ok = !system.isOsWindows() || system.isJavaAtLeast17();
- }
- return ok;
- }
-
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWs.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWs.java
index 3ed0f57e605..1f97ad6ad42 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWs.java
@@ -23,19 +23,19 @@ import org.sonar.api.server.ws.WebService;
public class SystemWs implements WebService {
- private final RestartHandler restartHandler;
+ private final SystemWsAction[] actions;
- public SystemWs(RestartHandler restartHandler) {
- this.restartHandler = restartHandler;
+ public SystemWs(SystemWsAction... actions) {
+ this.actions = actions;
}
@Override
public void define(Context context) {
- NewController controller = context.createController("api/system")
- .setDescription("Restart server")
- .setSince("4.3");
+ NewController controller = context.createController("api/system");
- restartHandler.define(controller);
+ for (SystemWsAction action : actions) {
+ action.define(controller);
+ }
controller.done();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWsAction.java
new file mode 100644
index 00000000000..21cacb6a149
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ws/SystemWsAction.java
@@ -0,0 +1,29 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.server.ws.RequestHandler;
+import org.sonar.api.server.ws.WebService;
+
+public interface SystemWsAction extends RequestHandler {
+
+ public void define(WebService.NewController controller);
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/NodeHealth.java b/server/sonar-server/src/main/java/org/sonar/server/search/NodeHealth.java
index e10254c4894..49c8911f4e7 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/NodeHealth.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/NodeHealth.java
@@ -42,6 +42,40 @@ public class NodeHealth {
private long filterCacheMemory;
private List<Performance> performanceStats;
+ NodeHealth(NodeStats nodesStats) {
+ // Master/slave
+ setMaster(nodesStats.getNode().isMasterNode());
+
+ // Host IP and port
+ setAddress(nodesStats.getNode().getAddress().toString());
+
+ // JVM Heap Usage
+ setJvmHeapMax(nodesStats.getJvm().getMem().getHeapMax().bytes());
+ setJvmHeapUsed(nodesStats.getJvm().getMem().getHeapUsed().bytes());
+
+ // Disk Usage
+ setFsTotal(nodesStats.getFs().getTotal().getTotal().bytes());
+ setFsAvailable(nodesStats.getFs().getTotal().getAvailable().bytes());
+
+ // Ping ?
+
+ // Threads
+ setJvmThreads(nodesStats.getJvm().getThreads().count());
+
+ // CPU
+ if (nodesStats.getProcess().getCpu() != null) {
+ setProcessCpuPercent(nodesStats.getProcess().cpu().getPercent());
+ }
+
+ // Open Files
+ setOpenFiles(nodesStats.getProcess().getOpenFileDescriptors());
+
+ // Uptime
+ setJvmUptimeMillis(nodesStats.getJvm().getUptime().getMillis());
+
+ initPerformanceStats(nodesStats);
+ }
+
public boolean isMaster() {
return master;
}
@@ -58,22 +92,22 @@ public class NodeHealth {
this.address = address;
}
- void setJvmHeapMax(long bytes) {
- this.jvmHeapMax = bytes;
- }
-
- void setJvmHeapUsed(long bytes) {
- this.jvmHeapUsed = bytes;
- }
-
public long getJvmHeapMax() {
return jvmHeapMax;
}
+ void setJvmHeapMax(long bytes) {
+ this.jvmHeapMax = bytes;
+ }
+
public long getJvmHeapUsed() {
return jvmHeapUsed;
}
+ void setJvmHeapUsed(long bytes) {
+ this.jvmHeapUsed = bytes;
+ }
+
public String getJvmHeapUsedPercent() {
return formatPercent(getJvmHeapUsed(), getJvmHeapMax());
}
@@ -94,38 +128,38 @@ public class NodeHealth {
return String.format("%.1f%%", 100 * amount * 1.0D / total);
}
+ public long getJvmThreads() {
+ return jvmThreads;
+ }
+
void setJvmThreads(long threads) {
this.jvmThreads = threads;
}
- public long getJvmThreads() {
- return jvmThreads;
+ public String getProcessCpuPercent() {
+ return formatPercent(cpuPercent, 100L);
}
void setProcessCpuPercent(int cpuPercent) {
this.cpuPercent = cpuPercent;
}
- public String getProcessCpuPercent() {
- return formatPercent(cpuPercent, 100L);
+ public long getOpenFiles() {
+ return openFiles;
}
void setOpenFiles(long avgOpenFileDescriptors) {
this.openFiles = avgOpenFileDescriptors;
}
- long getOpenFiles() {
- return openFiles;
+ public long getJvmUptimeMillis() {
+ return jvmUptimeMillis;
}
void setJvmUptimeMillis(long millis) {
this.jvmUptimeMillis = millis;
}
- public long getJvmUptimeMillis() {
- return jvmUptimeMillis;
- }
-
public Date getJvmUpSince() {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(calendar.getTimeInMillis() - getJvmUptimeMillis());
@@ -144,40 +178,6 @@ public class NodeHealth {
return filterCacheMemory;
}
- NodeHealth(NodeStats nodesStats) {
- // Master/slave
- setMaster(nodesStats.getNode().isMasterNode());
-
- // Host IP and port
- setAddress(nodesStats.getNode().getAddress().toString());
-
- // JVM Heap Usage
- setJvmHeapMax(nodesStats.getJvm().getMem().getHeapMax().bytes());
- setJvmHeapUsed(nodesStats.getJvm().getMem().getHeapUsed().bytes());
-
- // Disk Usage
- setFsTotal(nodesStats.getFs().getTotal().getTotal().bytes());
- setFsAvailable(nodesStats.getFs().getTotal().getAvailable().bytes());
-
- // Ping ?
-
- // Threads
- setJvmThreads(nodesStats.getJvm().getThreads().count());
-
- // CPU
- if (nodesStats.getProcess().getCpu() != null) {
- setProcessCpuPercent(nodesStats.getProcess().cpu().getPercent());
- }
-
- // Open Files
- setOpenFiles(nodesStats.getProcess().getOpenFileDescriptors());
-
- // Uptime
- setJvmUptimeMillis(nodesStats.getJvm().getUptime().getMillis());
-
- initPerformanceStats(nodesStats);
- }
-
private void initPerformanceStats(NodeStats nodesStats) {
// Performance Stat
performanceStats = new ArrayList<Performance>();
@@ -190,7 +190,7 @@ public class NodeHealth {
.setWarnThreshold(10)
.setErrorThreshold(50)
.setMessage("Too complex documents or low IO/CPU")
- .setValue(indexCount > 0L ? indexTotalTime / (double)indexCount : 0.0));
+ .setValue(indexCount > 0L ? indexTotalTime / (double) indexCount : 0.0));
// Query stats
long queryCount = nodesStats.getIndices().getSearch().getTotal().getQueryCount();
@@ -200,7 +200,7 @@ public class NodeHealth {
.setWarnThreshold(50)
.setErrorThreshold(500)
.setMessage("Inefficient query and/or filters")
- .setValue(queryCount > 0L ? queryTotalTime / (double)queryCount : 0.0));
+ .setValue(queryCount > 0L ? queryTotalTime / (double) queryCount : 0.0));
// Fetch stats
long fetchCount = nodesStats.getIndices().getSearch().getTotal().getFetchCount();
@@ -210,7 +210,7 @@ public class NodeHealth {
.setWarnThreshold(8)
.setErrorThreshold(15)
.setMessage("Slow IO, fetch-size too large or documents too big")
- .setValue(fetchCount > 0L ? fetchTotalTime / (double)fetchCount : 0.0));
+ .setValue(fetchCount > 0L ? fetchTotalTime / (double) fetchCount : 0.0));
// Get stats
long getCount = nodesStats.getIndices().getGet().getCount();
@@ -220,7 +220,7 @@ public class NodeHealth {
.setWarnThreshold(5)
.setErrorThreshold(10)
.setMessage("Slow IO")
- .setValue(getCount > 0L ? getTotalTime / (double)getCount : 0.0));
+ .setValue(getCount > 0L ? getTotalTime / (double) getCount : 0.0));
// Refresh Stat
long refreshCount = nodesStats.getIndices().getRefresh().getTotal();
@@ -230,7 +230,7 @@ public class NodeHealth {
.setWarnThreshold(10)
.setErrorThreshold(20)
.setMessage("Slow IO")
- .setValue(refreshCount > 0L ? refreshTotalTime / (double)refreshCount : 0.0));
+ .setValue(refreshCount > 0L ? refreshTotalTime / (double) refreshCount : 0.0));
// Field Cache
fieldCacheMemory = nodesStats.getIndices().getFieldData().getMemorySizeInBytes();
@@ -255,16 +255,11 @@ public class NodeHealth {
public static class Performance {
- public static enum Status {
- OK, WARN, ERROR
- }
-
private final String name;
private String message;
private double value;
private double warnThreshold;
private double errorThreshold;
-
public Performance(String name) {
this.name = name;
}
@@ -310,5 +305,9 @@ public class NodeHealth {
this.errorThreshold = errorThreshold;
return this;
}
+
+ public static enum Status {
+ OK, WARN, ERROR
+ }
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/BaseMonitorMBeanTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/BaseMonitorMBeanTest.java
new file mode 100644
index 00000000000..1dbb3dd70cf
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/BaseMonitorMBeanTest.java
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.junit.Test;
+
+import javax.annotation.CheckForNull;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectInstance;
+import java.lang.management.ManagementFactory;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class BaseMonitorMBeanTest {
+
+ FakeMonitor sut = new FakeMonitor();
+
+ @Test
+ public void test_registration() throws Exception {
+ assertThat(getMBean()).isNull();
+
+ sut.start();
+ assertThat(getMBean()).isNotNull();
+
+ sut.stop();
+ assertThat(getMBean()).isNull();
+ }
+
+ @Test
+ public void do_not_fail_when_stopping_unstarted() throws Exception {
+ sut.stop();
+ assertThat(getMBean()).isNull();
+ }
+
+ @CheckForNull
+ private ObjectInstance getMBean() throws Exception {
+ try {
+ return ManagementFactory.getPlatformMBeanServer().getObjectInstance(sut.objectName());
+ } catch (InstanceNotFoundException e) {
+ return null;
+ }
+ }
+
+}
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
new file mode 100644
index 00000000000..75aa97901f7
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/DatabaseMonitorTest.java
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.persistence.DatabaseVersion;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.DbClient;
+
+import java.util.LinkedHashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DatabaseMonitorTest {
+
+ @Rule
+ public DbTester dbTester = new DbTester();
+
+ DatabaseMonitor sut;
+
+ @Before
+ public void setUp() throws Exception {
+ DatabaseVersion dbVersion = new DatabaseVersion(dbTester.myBatis());
+ DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis());
+ sut = new DatabaseMonitor(dbVersion, dbClient);
+ }
+
+ @Test
+ public void db_info() {
+ LinkedHashMap<String, Object> attributes = sut.attributes();
+ assertThat(attributes.get("Database")).isEqualTo("H2");
+ assertThat(attributes.get("Database Version").toString()).startsWith("1.");
+ assertThat(attributes.get("Username")).isEqualTo("SONAR");
+ assertThat(attributes.get("Driver Version").toString()).startsWith("1.");
+ }
+
+ @Test
+ public void pool_info() {
+ LinkedHashMap<String, Object> attributes = sut.attributes();
+ assertThat((int)attributes.get("Pool Max Connections")).isGreaterThan(0);
+ }
+}
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
new file mode 100644
index 00000000000..2bfbf6de823
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitor.java
@@ -0,0 +1,40 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import java.util.LinkedHashMap;
+
+public class FakeMonitor extends BaseMonitorMBean implements FakeMonitorMBean {
+
+ @Override
+ public int getFake() {
+ return 42;
+ }
+
+ @Override
+ public String name() {
+ return "fake";
+ }
+
+ @Override
+ public LinkedHashMap<String, Object> attributes() {
+ return new LinkedHashMap<>();
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitorMBean.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitorMBean.java
new file mode 100644
index 00000000000..91d77b2d33c
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/FakeMonitorMBean.java
@@ -0,0 +1,24 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+public interface FakeMonitorMBean {
+ int getFake();
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitorTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitorTest.java
new file mode 100644
index 00000000000..208516d7276
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/JvmPropertiesMonitorTest.java
@@ -0,0 +1,37 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.junit.Test;
+
+import java.util.LinkedHashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class JvmPropertiesMonitorTest {
+
+ @Test
+ public void attributes() throws Exception {
+ JvmPropertiesMonitor sut = new JvmPropertiesMonitor();
+ LinkedHashMap<String, Object> attributes = sut.attributes();
+
+ assertThat(attributes).containsKey("java.vm.vendor");
+ }
+}
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
new file mode 100644
index 00000000000..4ee0fe3eef2
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/PluginsMonitorTest.java
@@ -0,0 +1,80 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.monitoring;
+
+import org.junit.Test;
+import org.sonar.api.Plugin;
+import org.sonar.api.platform.PluginMetadata;
+import org.sonar.api.platform.PluginRepository;
+import org.sonar.core.plugins.DefaultPluginMetadata;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PluginsMonitorTest {
+
+ PluginsMonitor sut = new PluginsMonitor(new FakePluginRepository());;
+
+ @Test
+ public void name() throws Exception {
+ assertThat(sut.name()).isEqualTo("Plugins");
+ }
+
+ @Test
+ public void plugin_name_and_version() throws Exception {
+ LinkedHashMap<String, Object> attributes = sut.attributes();
+
+ assertThat(attributes)
+ .containsEntry("plugin-1", "1.1")
+ .containsEntry("plugin-2", "2.2");
+ }
+
+ private static class FakePluginRepository implements PluginRepository {
+
+ @Override
+ public Plugin getPlugin(String key) {
+ return null;
+ }
+
+ @Override
+ public Collection<PluginMetadata> getMetadata() {
+ List<PluginMetadata> plugins = new ArrayList<>();
+ plugins.add(DefaultPluginMetadata
+ .create("key-1")
+ .setName("plugin-1")
+ .setVersion("1.1"));
+ plugins.add(DefaultPluginMetadata
+ .create("key-2")
+ .setName("plugin-2")
+ .setVersion("2.2"));
+ return plugins;
+ }
+
+ @Override
+ public PluginMetadata getMetadata(String pluginKey) {
+ return null;
+ }
+ }
+}
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
new file mode 100644
index 00000000000..6972f98e6e7
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SonarQubeMonitorTest.java
@@ -0,0 +1,46 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.server.user.SecurityRealmFactory;
+
+import java.util.LinkedHashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SonarQubeMonitorTest {
+
+ @Test
+ public void getServerId() throws Exception {
+ Settings settings = new Settings();
+ Server server = mock(Server.class);
+ when(server.getStartedAt()).thenReturn(DateUtils.parseDate("2015-01-01"));
+ SonarQubeMonitor monitor = new SonarQubeMonitor(settings, new SecurityRealmFactory(settings), server);
+
+ LinkedHashMap<String, Object> attributes = monitor.attributes();
+ assertThat(attributes).containsKeys("Started at", "Server ID");
+ }
+}
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
new file mode 100644
index 00000000000..ba7064ca217
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/monitoring/SystemMonitorTest.java
@@ -0,0 +1,43 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+package org.sonar.server.platform.monitoring;
+
+import org.junit.Test;
+
+import java.util.LinkedHashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SystemMonitorTest {
+
+ SystemMonitor sut = new SystemMonitor();
+
+ @Test
+ public void name() throws Exception {
+ assertThat(sut.name()).isEqualTo("System");
+ }
+
+ @Test
+ public void system_properties() throws Exception {
+ LinkedHashMap<String, Object> attributes = sut.attributes();
+
+ assertThat(attributes).containsKeys("System Date", "Processors");
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java
new file mode 100644
index 00000000000..f42f3dc09c8
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemInfoWsActionTest.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.platform.ws;
+
+import org.apache.commons.lang.StringUtils;
+import org.assertj.core.api.Condition;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.platform.monitoring.Monitor;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class SystemInfoWsActionTest {
+
+ @ClassRule
+ public static ServerTester serverTester = new ServerTester();
+
+ private SystemInfoWsAction sut;
+
+ @Test
+ public void all_monitors_have_a_name() throws Exception {
+ sut = serverTester.get(SystemInfoWsAction.class);
+
+ assertThat(sut.getMonitors()).areNot(withEmptyName());
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void should_fail_when_does_not_have_admin_right() throws Exception {
+ sut = serverTester.get(SystemInfoWsAction.class);
+ MockUserSession.set()
+ .setLogin("login")
+ .setName("name")
+ .setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
+
+ sut.handle(mock(Request.class), mock(Response.class));
+ }
+
+ private Condition<Monitor> withEmptyName() {
+ return new Condition<Monitor>() {
+ @Override
+ public boolean matches(Monitor m) {
+ return StringUtils.isEmpty(m.name());
+ }
+ };
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartHandlerTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemRestartWsActionTest.java
index 832f80f2585..4329ff9a5d5 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartHandlerTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemRestartWsActionTest.java
@@ -21,63 +21,33 @@ package org.sonar.server.platform.ws;
import org.junit.Test;
import org.sonar.api.config.Settings;
-import org.sonar.api.utils.System2;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.platform.Platform;
import org.sonar.server.ws.WsTester;
import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
-public class RestartHandlerTest {
+public class SystemRestartWsActionTest {
- System2 system = mock(System2.class);
+ Settings settings = new Settings();
+ Platform platform = mock(Platform.class);
+ SystemRestartWsAction sut = new SystemRestartWsAction(settings, platform);
@Test
public void restart_if_dev_mode() throws Exception {
- Platform platform = mock(Platform.class);
- Settings settings = new Settings();
settings.setProperty("sonar.web.dev", true);
- when(system.isOsWindows()).thenReturn(false);
- RestartHandler restartHandler = new RestartHandler(settings, platform, system);
- SystemWs ws = new SystemWs(restartHandler);
+ SystemWs ws = new SystemWs(sut);
WsTester tester = new WsTester(ws);
tester.newPostRequest("api/system", "restart").execute();
-
verify(platform).restart();
}
@Test
public void fail_if_production_mode() throws Exception {
- Platform platform = mock(Platform.class);
- Settings settings = new Settings();
- RestartHandler restartHandler = new RestartHandler(settings, platform, system);
- SystemWs ws = new SystemWs(restartHandler);
-
- WsTester tester = new WsTester(ws);
- try {
- tester.newPostRequest("api/system", "restart").execute();
- fail();
- } catch (ForbiddenException e) {
- verifyZeroInteractions(platform);
- }
- }
-
- @Test
- public void fail_if_windows_java_6() throws Exception {
- Platform platform = mock(Platform.class);
- Settings settings = new Settings();
- settings.setProperty("sonar.web.dev", true);
- when(system.isOsWindows()).thenReturn(true);
- when(system.isJavaAtLeast17()).thenReturn(false);
-
- RestartHandler restartHandler = new RestartHandler(settings, platform, system);
- SystemWs ws = new SystemWs(restartHandler);
+ SystemWs ws = new SystemWs(sut);
WsTester tester = new WsTester(ws);
try {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java
index 132f77d4f35..1c535200e66 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java
@@ -22,7 +22,6 @@ package org.sonar.server.platform.ws;
import org.junit.Test;
import org.sonar.api.config.Settings;
import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.System2;
import org.sonar.server.platform.Platform;
import static org.assertj.core.api.Assertions.assertThat;
@@ -32,18 +31,15 @@ public class SystemWsTest {
@Test
public void define() throws Exception {
- Platform platform = mock(Platform.class);
- Settings settings = new Settings();
- RestartHandler restartHandler = new RestartHandler(settings, platform, mock(System2.class));
- SystemWs ws = new SystemWs(restartHandler);
+ SystemRestartWsAction action1 = new SystemRestartWsAction(mock(Settings.class), mock(Platform.class));
+ SystemInfoWsAction action2 = new SystemInfoWsAction();
+ SystemWs ws = new SystemWs(action1, action2);
WebService.Context context = new WebService.Context();
ws.define(context);
assertThat(context.controllers()).hasSize(1);
- assertThat(context.controller("api/system")).isNotNull();
- assertThat(context.controller("api/system").description()).isNotEmpty();
- assertThat(context.controller("api/system").since()).isEqualTo("4.3");
- assertThat(context.controller("api/system").actions()).isNotEmpty();
+ assertThat(context.controller("api/system").actions()).hasSize(2);
+ assertThat(context.controller("api/system").action("info")).isNotNull();
}
}
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb
index 34de3ab3b16..91ff7fd875e 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/api/server_controller.rb
@@ -45,24 +45,6 @@ class Api::ServerController < Api::ApiController
end
end
- def system
- access_denied unless has_role?(:admin)
- @server=Server.new
- json=[
- {:system_info => server_properties_to_json(@server.system_info)},
- {:system_statistics => server_properties_to_json(@server.system_statistics)},
- {:sonar_info => server_properties_to_json(@server.sonar_info)},
- {:sonar_plugins => server_properties_to_json(@server.sonar_plugins)},
- {:system_properties => server_properties_to_json(@server.system_properties)},
- ]
-
- respond_to do |format|
- format.json{ render :json => jsonp(json) }
- format.xml { render :xml => xml_not_supported }
- format.text { render :text => text_not_supported}
- end
- end
-
def setup
verify_post_request
manager=DatabaseMigrationManager.instance
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/system_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/system_controller.rb
index 1c86a0f75b5..9bb32af6f5a 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/system_controller.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/system_controller.rb
@@ -17,7 +17,6 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
-require 'fastercsv'
class SystemController < ApplicationController
SECTION=Navigation::SECTION_CONFIGURATION
@@ -32,19 +31,7 @@ class SystemController < ApplicationController
respond_to do |format|
format.html
- format.csv {
- send_data(to_csv, :type => 'text/csv; charset=utf-8', :disposition => "attachment; filename=#{filename}.csv")
- }
- end
- end
-
- private
-
- def to_csv
- FasterCSV.generate do |csv|
- @server.info.each do |property|
- csv << property
- end
end
end
+
end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/models/server.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/models/server.rb
index b611f37aed8..2da765f923f 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/models/server.rb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/models/server.rb
@@ -31,20 +31,30 @@ class Server
add_property(system_info, 'JVM Vendor') { java.lang.management.ManagementFactory.getRuntimeMXBean().getVmVendor() }
add_property(system_info, 'JVM Name') { java.lang.management.ManagementFactory.getRuntimeMXBean().getVmName() }
add_property(system_info, 'JVM Version') { java.lang.management.ManagementFactory.getRuntimeMXBean().getVmVersion() }
- add_property(system_info, 'Java Version') { java_property('java.runtime.version') }
- add_property(system_info, 'Java Home') { java_property('java.home') }
- add_property(system_info, 'JIT Compiler') { java_property('java.compiler') }
- add_property(system_info, 'Application Server Container') { $servlet_context.getServerInfo() }
- add_property(system_info, 'User Name') { java_property('user.name') }
- add_property(system_info, 'User TimeZone') { java_property('user.timezone') }
- add_property(system_info, 'OS') { "#{java_property('os.name')} / #{java_property('os.arch')} / #{java_property('os.version')}" }
+ #add_property(system_info, 'Java Version') { java_property('java.runtime.version') }
+ #add_property(system_info, 'Java Home') { java_property('java.home') }
+ #add_property(system_info, 'JIT Compiler') { java_property('java.compiler') }
+ #add_property(system_info, 'Application Server Container') { $servlet_context.getServerInfo() }
+ #add_property(system_info, 'User Name') { java_property('user.name') }
+ #add_property(system_info, 'User TimeZone') { java_property('user.timezone') }
+ #add_property(system_info, 'OS') { "#{java_property('os.name')} / #{java_property('os.arch')} / #{java_property('os.version')}" }
add_property(system_info, 'Processors') { java.lang.Runtime.getRuntime().availableProcessors() }
add_property(system_info, 'System Classpath') { java.lang.management.ManagementFactory.getRuntimeMXBean().getClassPath() }
add_property(system_info, 'Boot Classpath') { java.lang.management.ManagementFactory.getRuntimeMXBean().getBootClassPath() }
add_property(system_info, 'Library Path') { java.lang.management.ManagementFactory.getRuntimeMXBean().getLibraryPath() }
+ add_property(system_statistics, 'Total Memory') { "#{java.lang.Runtime.getRuntime().totalMemory() / 1000000} MB" }
+ add_property(system_statistics, 'Free Memory') { "#{java.lang.Runtime.getRuntime().freeMemory() / 1000000} MB" }
+ add_property(system_statistics, 'Max Memory') { "#{java.lang.Runtime.getRuntime().maxMemory() / 1000000} MB" }
+ add_property(system_statistics, 'Heap') { "#{java.lang.management.ManagementFactory.getMemoryMXBean().getHeapMemoryUsage()}" }
+ add_property(system_statistics, 'Non Heap') { "#{java.lang.management.ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage()}" }
+ add_property(system_statistics, 'System Load Average (last minute)') { system_load_average() }
+ add_property(system_statistics, 'Loaded Classes (currently/total/unloaded)') { "#{java.lang.management.ManagementFactory.getClassLoadingMXBean().getLoadedClassCount()} / #{java.lang.management.ManagementFactory.getClassLoadingMXBean().getTotalLoadedClassCount()} / #{java.lang.management.ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount()}" }
+ add_property(system_statistics, 'Start Time') { "#{format_date(java.util.Date.new(java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()))}" }
+ add_property(system_statistics, 'Threads (total/peak/daemon)') { "#{java.lang.management.ManagementFactory.getThreadMXBean().getThreadCount()} / #{java.lang.management.ManagementFactory.getThreadMXBean().getPeakThreadCount()} / #{java.lang.management.ManagementFactory.getThreadMXBean().getDaemonThreadCount() }" }
system_info
end
+ #TODO to remove
def system_statistics
system_statistics=[]
add_property(system_statistics, 'Total Memory') { "#{java.lang.Runtime.getRuntime().totalMemory() / 1000000} MB" }
@@ -64,13 +74,13 @@ class Server
add_property(sonar_info, 'Server ID') { sonar_property(ServerIdConfigurationController::PROPERTY_SERVER_ID) }
add_property(sonar_info, 'Version') { org.sonar.server.platform.Platform.getServer().getVersion() }
add_property(sonar_info, 'Started at') { org.sonar.server.platform.Platform.getServer().getStartedAt() }
- add_property(sonar_info, 'Database') { "#{jdbc_metadata.getDatabaseProductName()} #{jdbc_metadata.getDatabaseProductVersion()}" }
- add_property(sonar_info, 'Database URL') { sonar_property('sonar.jdbc.url') }
- add_property(sonar_info, 'Database Login') { sonar_property('sonar.jdbc.username') }
- add_property(sonar_info, 'Database Driver') { "#{jdbc_metadata.getDriverName()} #{jdbc_metadata.getDriverVersion()}" }
- add_property(sonar_info, 'Database Active Connections') { "#{Java::OrgSonarServerUi::JRubyFacade.getInstance().getDatabase().getDataSource().getNumActive()}" }
- add_property(sonar_info, 'Database Max. Active Connections') { sonar_property('sonar.jdbc.maxActive') }
- add_property(sonar_info, 'Database Max. Pool Wait') { sonar_property('sonar.jdbc.maxWait') }
+ #add_property(sonar_info, 'Database') { "#{jdbc_metadata.getDatabaseProductName()} #{jdbc_metadata.getDatabaseProductVersion()}" }
+ #add_property(sonar_info, 'Database URL') { sonar_property('sonar.jdbc.url') }
+ #add_property(sonar_info, 'Database Login') { sonar_property('sonar.jdbc.username') }
+ #add_property(sonar_info, 'Database Driver') { "#{jdbc_metadata.getDriverName()} #{jdbc_metadata.getDriverVersion()}" }
+ #add_property(sonar_info, 'Database Active Connections') { "#{Java::OrgSonarServerUi::JRubyFacade.getInstance().getDatabase().getDataSource().getNumActive()}" }
+ #add_property(sonar_info, 'Database Max. Active Connections') { sonar_property('sonar.jdbc.maxActive') }
+ #add_property(sonar_info, 'Database Max. Pool Wait') { sonar_property('sonar.jdbc.maxWait') }
add_property(sonar_info, 'External User Authentication') { realm_name }
add_property(sonar_info, 'Automatic User Creation') { sonar_property(org.sonar.api.CoreProperties.CORE_AUTHENTICATOR_CREATE_USERS) }
add_property(sonar_info, 'Allow Users to Sign Up') { sonar_property(org.sonar.api.CoreProperties.CORE_ALLOW_USERS_TO_SIGNUP_PROPERTY) }
@@ -124,6 +134,7 @@ class Server
nodes_info
end
+ #TODO should be removed
def sonar_plugins
sonar_plugins=[]
Java::OrgSonarServerUi::JRubyFacade.getInstance().getPluginsMetadata().to_a.select { |plugin| !plugin.isCore() }.sort.each do |plugin|
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/system/index.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/system/index.html.erb
index 56b92a5fc50..f237a396468 100644
--- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/system/index.html.erb
+++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/system/index.html.erb
@@ -2,8 +2,8 @@
<header class="page-header">
<h1 class="page-title"><%= message('system_info.page') -%></h1>
<div class="page-actions">
- <div class="csv">
- <a href="<%= ApplicationController.root_context -%>/system/index?format=csv" id="download-link">Download</a>
+ <div>
+ <a href="<%= ApplicationController.root_context -%>/api/system/info" id="download-link">Download</a>
</div>
</div>
<p class="page-description"><%= message('system_info.page.description') -%></p>
@@ -19,35 +19,11 @@
<% @server.sonar_info.each do |data| %>
<%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'sonar'} %>
<% end %>
- <tbody>
+ </tbody>
</table>
<br/>
- <table class="data width100" id="plugins">
- <thead>
- <tr>
- <th colspan="2"><h2>SonarQube Plugins</h2></th>
- </tr>
- </thead>
- <tbody>
- <%
- user_plugins=@server.sonar_plugins
- if user_plugins.empty?
- %>
- <tr>
- <td colspan="2" class="even">None</td>
- </tr>
- <% else %>
- <% user_plugins.each do |data| %>
- <%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'plugins'} %>
- <% end %>
- <% end %>
- <tbody>
- </table>
-
- <br/>
-
<table class="data width100" id="system_info">
<thead>
<tr>
@@ -58,7 +34,7 @@
<% @server.system_info.each do |data| %>
<%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'system'} %>
<% end %>
- <tbody>
+ </tbody>
</table>
<br/>
@@ -66,14 +42,14 @@
<table class="data width100" id="cluster_info">
<thead>
<tr>
- <th colspan="2"><h2>Search Info - Cluster</h2></th>
+ <th colspan="2"><h2>ElasticSearch - Cluster</h2></th>
</tr>
</thead>
<tbody>
<% @server.cluster_info.each do |data| %>
<%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'cluster'} %>
<% end %>
- <tbody>
+ </tbody>
</table>
<br/>
@@ -82,35 +58,19 @@
<table class="data width100" id="cluster_info<%= node_info[0][1] -%>">
<thead>
<tr>
- <th colspan="2"><h2>Search Info - <%= node_info[0][1] -%></h2></th>
+ <th colspan="2"><h2>ElasticSearch - <%= node_info[0][1] -%></h2></th>
</tr>
</thead>
<tbody>
<% node_info.drop(1).each do |data| %>
<%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'node'} %>
<% end %>
- <tbody>
+ </tbody>
</table>
<br/>
<% end -%>
- <table class="data width100" id="memory">
- <thead>
- <tr>
- <th colspan="2"><h2>Java VM Statistics</h2></th>
- </tr>
- </thead>
- <tbody>
- <% @server.system_statistics.each do |data| %>
- <%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'memory'} %>
- <% end %>
- <tbody>
- </table>
-
- <br/>
-
-
<table class="data width100" id="system_properties">
<thead>
<tr>
@@ -121,6 +81,6 @@
<% @server.system_properties.each do |data| %>
<%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'system_properties'} %>
<% end %>
- <tbody>
+ </tbody>
</table>
</div>