aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/ClusterHealth.java42
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/NodeHealth.java44
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/SearchClient.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/SearchHealth.java19
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/search/SearchHealthMediumTest.java8
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/models/server.rb30
-rw-r--r--server/sonar-web/src/main/webapp/WEB-INF/app/views/system/index.html.erb25
7 files changed, 151 insertions, 48 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/ClusterHealth.java b/server/sonar-server/src/main/java/org/sonar/server/search/ClusterHealth.java
new file mode 100644
index 00000000000..45b260ad192
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/ClusterHealth.java
@@ -0,0 +1,42 @@
+/*
+ * 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.search;
+
+public class ClusterHealth {
+
+ private boolean clusterAvailable;
+ private int numberOfNodes;
+
+ void setClusterAvailable(boolean clusterAvailable) {
+ this.clusterAvailable = clusterAvailable;
+ }
+
+ public boolean isClusterAvailable() {
+ return clusterAvailable;
+ }
+
+ void setNumberOfNodes(int total) {
+ this.numberOfNodes = total;
+ }
+
+ public int getNumberOfNodes() {
+ return numberOfNodes;
+ }
+}
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 3f77c3cbb1d..1d59e9b65a7 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
@@ -19,12 +19,14 @@
*/
package org.sonar.server.search;
+import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
+
import java.util.Calendar;
import java.util.Date;
public class NodeHealth {
- private boolean clusterAvailable;
+ private boolean master;
private long jvmHeapMax;
private long jvmHeapUsed;
private long fsAvailable;
@@ -34,12 +36,12 @@ public class NodeHealth {
private long openFiles;
private long jvmUptimeMillis;
- void setClusterAvailable(boolean clusterAvailable) {
- this.clusterAvailable = clusterAvailable;
+ public boolean isMaster() {
+ return master;
}
- public boolean isClusterAvailable() {
- return clusterAvailable;
+ void setMaster(boolean master) {
+ this.master = master;
}
void setJvmHeapMax(long bytes) {
@@ -115,4 +117,36 @@ public class NodeHealth {
calendar.setTimeInMillis(calendar.getTimeInMillis() - getJvmUptimeMillis());
return calendar.getTime();
}
+
+ NodeHealth(NodeStats nodesStats) {
+ // Master/slave
+ setMaster(nodesStats.getNode().isMasterNode());
+
+ // JVM Heap Usage
+ setJvmHeapMax(nodesStats.getJvm().getMem().getHeapMax().bytes());
+ setJvmHeapUsed(nodesStats.getJvm().getMem().getHeapUsed().bytes());
+
+ // OS Memory Usage ?
+ // nodesStats.getOs().getMem().freePercent();
+
+ // 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());
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/SearchClient.java b/server/sonar-server/src/main/java/org/sonar/server/search/SearchClient.java
index 0c919160eda..eef7012c67f 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/SearchClient.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/SearchClient.java
@@ -75,38 +75,15 @@ public class SearchClient extends TransportClient {
this.profiling = new Profiling(settings);
}
- public NodeHealth getNodeHealth() {
- NodeHealth health = new NodeHealth();
+ public ClusterHealth getClusterHealth() {
+ ClusterHealth health = new ClusterHealth();
ClusterStatsResponse clusterStatsResponse = this.admin().cluster().prepareClusterStats().get();
// Cluster health
health.setClusterAvailable(clusterStatsResponse.getStatus() != ClusterHealthStatus.RED);
- ClusterStatsNodes nodesStats = clusterStatsResponse.getNodesStats();
-
- // JVM Heap Usage
- health.setJvmHeapMax(nodesStats.getJvm().getHeapMax().bytes());
- health.setJvmHeapUsed(nodesStats.getJvm().getHeapUsed().bytes());
-
- // OS Memory Usage ?
-
- // Disk Usage
- health.setFsTotal(nodesStats.getFs().getTotal().bytes());
- health.setFsAvailable(nodesStats.getFs().getAvailable().bytes());
-
- // Ping ?
-
- // Threads
- health.setJvmThreads(nodesStats.getJvm().getThreads());
-
- // CPU
- health.setProcessCpuPercent(nodesStats.getProcess().getCpuPercent());
-
- // Open Files
- health.setOpenFiles(nodesStats.getProcess().getAvgOpenFileDescriptors());
-
- // Uptime
- health.setJvmUptimeMillis(nodesStats.getJvm().getMaxUpTime().getMillis());
+ // Number of nodes
+ health.setNumberOfNodes(clusterStatsResponse.getNodesStats().getCounts().getTotal());
return health;
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/SearchHealth.java b/server/sonar-server/src/main/java/org/sonar/server/search/SearchHealth.java
index e4d077a121c..cfc274c1780 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/SearchHealth.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/SearchHealth.java
@@ -21,10 +21,15 @@ package org.sonar.server.search;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.Maps;
+import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
+import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsRequestBuilder;
+import org.elasticsearch.action.admin.cluster.node.stats.NodesStatsResponse;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequestBuilder;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import java.util.Map;
+import java.util.Map.Entry;
public class SearchHealth {
@@ -36,8 +41,8 @@ public class SearchHealth {
this.indexClient = indexClient;
}
- public NodeHealth getNodeHealth() {
- return searchClient.getNodeHealth();
+ public ClusterHealth getClusterHealth() {
+ return searchClient.getClusterHealth();
}
public Map<String, IndexHealth> getIndexHealth() {
@@ -60,4 +65,14 @@ public class SearchHealth {
return builder.build();
}
+ public Map<String, NodeHealth > getNodesHealth() {
+ NodesStatsRequestBuilder nodesStatsRequest = searchClient.admin().cluster().prepareNodesStats().all();
+ NodesStatsResponse nodesStats = searchClient.execute(nodesStatsRequest);
+
+ Map<String, NodeHealth> health = Maps.newHashMap();
+ for (Entry<String, NodeStats> nodeEntry: nodesStats.getNodesMap().entrySet()) {
+ health.put(nodeEntry.getKey(), new NodeHealth(nodeEntry.getValue()));
+ }
+ return ImmutableMap.copyOf(health);
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/SearchHealthMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/SearchHealthMediumTest.java
index ec865abb3dc..4236b4fc851 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/search/SearchHealthMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/search/SearchHealthMediumTest.java
@@ -38,8 +38,12 @@ public class SearchHealthMediumTest {
SearchHealth health = tester.get(SearchHealth.class);
Date now = new Date();
- NodeHealth nodeHealth = health.getNodeHealth();
- assertThat(nodeHealth.isClusterAvailable()).isTrue();
+ ClusterHealth clusterHealth = health.getClusterHealth();
+ assertThat(clusterHealth.isClusterAvailable()).isTrue();
+ assertThat(clusterHealth.getNumberOfNodes()).isEqualTo(1);
+
+ NodeHealth nodeHealth = health.getNodesHealth().values().iterator().next();
+ assertThat(nodeHealth.isMaster()).isTrue();
assertThat(nodeHealth.getJvmHeapUsedPercent()).contains("%");
assertThat(nodeHealth.getFsUsedPercent()).contains("%");
assertThat(nodeHealth.getJvmThreads()).isGreaterThanOrEqualTo(0L);
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 e33a68466ea..d1116ecf15c 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
@@ -76,17 +76,12 @@ class Server
sonar_info
end
- def search_info
+ def cluster_info
search_info=[]
search_health = Java::OrgSonarServerPlatform::Platform.component(Java::OrgSonarServerSearch::SearchHealth.java_class)
- node_health = search_health.getNodeHealth()
+ node_health = search_health.getClusterHealth()
add_property(search_info, 'Cluster State') { node_health.isClusterAvailable() ? 'Available' : 'Unavailable' }
- add_property(search_info, 'JVM Heap Usage') { node_health.getJvmHeapUsedPercent() }
- add_property(search_info, 'JVM Threads') { node_health.getJvmThreads() }
- add_property(search_info, 'JVM Uptime') { Internal.i18n.ageFromNow(node_health.getJvmUpSince()) }
- add_property(search_info, 'Disk Usage') { node_health.getFsUsedPercent() }
- add_property(search_info, 'Open Files') { node_health.getOpenFiles() }
- add_property(search_info, 'CPU Load Average') { node_health.getProcessCpuPercent() }
+ add_property(search_info, 'Number of Nodes') { node_health.getNumberOfNodes() }
search_health.getIndexHealth().each do |name, index_health|
add_property(search_info, "#{name} - Document Count") { index_health.getDocumentCount() }
@@ -97,6 +92,25 @@ class Server
search_info
end
+ def nodes_info
+ nodes_info=[]
+ search_health = Java::OrgSonarServerPlatform::Platform.component(Java::OrgSonarServerSearch::SearchHealth.java_class)
+ search_health.getNodesHealth().each do |name, node_health|
+ node_info=[]
+ add_property(node_info, 'Node Name') { name }
+ add_property(node_info, 'Node Type') { node_health.isMaster() ? 'Master' : 'Slave' }
+ add_property(node_info, 'JVM Heap Usage') { node_health.getJvmHeapUsedPercent() }
+ add_property(node_info, 'JVM Threads') { node_health.getJvmThreads() }
+ add_property(node_info, 'JVM Uptime') { Internal.i18n.ageFromNow(node_health.getJvmUpSince()) }
+ add_property(node_info, 'Disk Usage') { node_health.getFsUsedPercent() }
+ add_property(node_info, 'Open Files') { node_health.getOpenFiles() }
+ add_property(node_info, 'CPU Load Average') { node_health.getProcessCpuPercent() }
+ nodes_info.push(node_info)
+ end
+
+ nodes_info
+ end
+
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 5449aed0585..2916e4bcc7d 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
@@ -60,21 +60,38 @@
<br/>
-<table class="data width100" id="search_info">
+<table class="data width100" id="cluster_info">
<thead>
<tr>
- <th colspan="2"><h2>Search Info</h2></th>
+ <th colspan="2"><h2>Search Info - Cluster</h2></th>
</tr>
</thead>
<tbody>
- <% @server.search_info.each do |data| %>
- <%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'search' } %>
+ <% @server.cluster_info.each do |data| %>
+ <%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'cluster' } %>
<% end %>
<tbody>
</table>
<br/>
+<% @server.nodes_info.each do |node_info| -%>
+<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>
+ </tr>
+</thead>
+<tbody>
+ <% node_info.drop(1).each do |data| %>
+ <%= render :partial => 'row', :locals => {:title => data[0], :value => data[1], :name => 'node' } %>
+ <% end %>
+<tbody>
+</table>
+
+<br/>
+<% end -%>
+
<table class="data width100" id="memory">
<thead>
<tr>