Skip to content

Commit

Permalink
Added cluster health status to the Cluster Stats API
Browse files Browse the repository at this point in the history
Relates to elastic#4460
  • Loading branch information
bleskes committed Dec 18, 2013
1 parent ceed5d6 commit 36d1d22
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/reference/cluster/stats.asciidoc
Expand Up @@ -18,6 +18,7 @@ Will return, for example:
--------------------------------------------------
{
"cluster_name": "elasticsearch",
"status": "green",
"indices": {
"count": 3,
"shards": {
Expand Down
Expand Up @@ -19,11 +19,13 @@

package org.elasticsearch.action.admin.cluster.stats;

import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
import org.elasticsearch.action.admin.indices.stats.ShardStats;
import org.elasticsearch.action.support.nodes.NodeOperationResponse;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;

Expand All @@ -34,15 +36,17 @@ public class ClusterStatsNodeResponse extends NodeOperationResponse {
private NodeInfo nodeInfo;
private NodeStats nodeStats;
private ShardStats[] shardsStats;
private ClusterHealthStatus clusterStatus;

ClusterStatsNodeResponse() {
}

public ClusterStatsNodeResponse(DiscoveryNode node, NodeInfo nodeInfo, NodeStats nodeStats, ShardStats[] shardsStats) {
public ClusterStatsNodeResponse(DiscoveryNode node, @Nullable ClusterHealthStatus clusterStatus, NodeInfo nodeInfo, NodeStats nodeStats, ShardStats[] shardsStats) {
super(node);
this.nodeInfo = nodeInfo;
this.nodeStats = nodeStats;
this.shardsStats = shardsStats;
this.clusterStatus = clusterStatus;
}

public NodeInfo nodeInfo() {
Expand All @@ -53,6 +57,14 @@ public NodeStats nodeStats() {
return this.nodeStats;
}

/**
* Cluster Health Status, only populated on master nodes.
*/
@Nullable
public ClusterHealthStatus clusterStatus() {
return clusterStatus;
}

public ShardStats[] shardsStats() {
return this.shardsStats;
}
Expand All @@ -66,6 +78,10 @@ public static ClusterStatsNodeResponse readNodeResponse(StreamInput in) throws I
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
clusterStatus = null;
if (in.readBoolean()) {
clusterStatus = ClusterHealthStatus.fromValue(in.readByte());
}
this.nodeInfo = NodeInfo.readNodeInfo(in);
this.nodeStats = NodeStats.readNodeStats(in);
int size = in.readVInt();
Expand All @@ -78,6 +94,12 @@ public void readFrom(StreamInput in) throws IOException {
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
if (clusterStatus == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeByte(clusterStatus.value());
}
nodeInfo.writeTo(out);
nodeStats.writeTo(out);
out.writeVInt(shardsStats.length);
Expand Down
Expand Up @@ -19,6 +19,7 @@

package org.elasticsearch.action.admin.cluster.stats;

import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.support.nodes.NodesOperationResponse;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.common.io.stream.StreamInput;
Expand All @@ -30,6 +31,7 @@

import java.io.IOException;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;

/**
Expand All @@ -40,6 +42,7 @@ public class ClusterStatsResponse extends NodesOperationResponse<ClusterStatsNod
ClusterStatsNodes nodesStats;
ClusterStatsIndices indicesStats;
String clusterUUID;
ClusterHealthStatus status;
long timestamp;


Expand All @@ -52,12 +55,23 @@ public ClusterStatsResponse(long timestamp, ClusterName clusterName, String clus
this.clusterUUID = clusterUUID;
nodesStats = new ClusterStatsNodes(nodes);
indicesStats = new ClusterStatsIndices(nodes);
for (ClusterStatsNodeResponse response : nodes) {
// only the master node populates the status
if (response.clusterStatus() != null) {
status = response.clusterStatus();
break;
}
}
}

public long getTimestamp() {
return this.timestamp;
}

public ClusterHealthStatus getStatus() {
return this.status;
}

public ClusterStatsNodes getNodesStats() {
return nodesStats;
}
Expand Down Expand Up @@ -90,6 +104,11 @@ public Iterator<ClusterStatsNodeResponse> iterator() {
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
timestamp = in.readVLong();
status = null;
if (in.readBoolean()) {
// it may be that the master switched on us while doing the operation. In this case the status may be null.
status = ClusterHealthStatus.fromValue(in.readByte());
}
clusterUUID = in.readString();
nodesStats = ClusterStatsNodes.readNodeStats(in);
indicesStats = ClusterStatsIndices.readIndicesStats(in);
Expand All @@ -99,6 +118,12 @@ public void readFrom(StreamInput in) throws IOException {
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeVLong(timestamp);
if (status == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
out.writeByte(status.value());
}
out.writeString(clusterUUID);
nodesStats.writeTo(out);
indicesStats.writeTo(out);
Expand All @@ -109,6 +134,7 @@ static final class Fields {
static final XContentBuilderString INDICES = new XContentBuilderString("indices");
static final XContentBuilderString UUID = new XContentBuilderString("uuid");
static final XContentBuilderString CLUSTER_NAME = new XContentBuilderString("cluster_name");
static final XContentBuilderString STATUS = new XContentBuilderString("status");
}

@Override
Expand All @@ -118,7 +144,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
if (params.paramAsBoolean("output_uuid", false)) {
builder.field(Fields.UUID, clusterUUID);
}

if (status != null) {
builder.field(Fields.STATUS, status.name().toLowerCase(Locale.ROOT));
}
builder.startObject(Fields.INDICES);
indicesStats.toXContent(builder, params);
builder.endObject();
Expand Down
Expand Up @@ -20,6 +20,8 @@
package org.elasticsearch.action.admin.cluster.stats;

import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.admin.cluster.health.ClusterIndexHealth;
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
import org.elasticsearch.action.admin.cluster.node.stats.NodeStats;
import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
Expand All @@ -28,6 +30,8 @@
import org.elasticsearch.action.support.nodes.TransportNodesOperationAction;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.routing.IndexRoutingTable;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
Expand Down Expand Up @@ -129,7 +133,31 @@ protected ClusterStatsNodeResponse nodeOperation(ClusterStatsNodeRequest nodeReq

}

return new ClusterStatsNodeResponse(nodeInfo.getNode(), nodeInfo, nodeStats, shardsStats.toArray(new ShardStats[shardsStats.size()]));
ClusterHealthStatus clusterStatus = null;
if (clusterService.state().nodes().localNodeMaster()) {
// populate cluster status
clusterStatus = ClusterHealthStatus.GREEN;
for (IndexRoutingTable indexRoutingTable : clusterService.state().routingTable()) {
IndexMetaData indexMetaData = clusterService.state().metaData().index(indexRoutingTable.index());
if (indexRoutingTable == null) {
continue;
}

ClusterIndexHealth indexHealth = new ClusterIndexHealth(indexMetaData, indexRoutingTable);
switch (indexHealth.getStatus()) {
case RED:
clusterStatus = ClusterHealthStatus.RED;
break;
case YELLOW:
if (clusterStatus != ClusterHealthStatus.RED) {
clusterStatus = ClusterHealthStatus.YELLOW;
}
break;
}
}
}

return new ClusterStatsNodeResponse(nodeInfo.getNode(), clusterStatus, nodeInfo, nodeStats, shardsStats.toArray(new ShardStats[shardsStats.size()]));

}

Expand Down
Expand Up @@ -20,6 +20,7 @@


import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.monitor.sigar.SigarService;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
Expand Down Expand Up @@ -68,9 +69,15 @@ private void assertShardStats(ClusterStatsIndices.ShardStats stats, int indices,
@Test
public void testIndicesShardStats() {
cluster().startNode();

ClusterStatsResponse response = client().admin().cluster().prepareClusterStats().get();
assertThat(response.getStatus(), Matchers.equalTo(ClusterHealthStatus.GREEN));


prepareCreate("test1").setSettings("number_of_shards", 2, "number_of_replicas", 1).get();
ensureYellow();
ClusterStatsResponse response = client().admin().cluster().prepareClusterStats().get();
response = client().admin().cluster().prepareClusterStats().get();
assertThat(response.getStatus(), Matchers.equalTo(ClusterHealthStatus.YELLOW));
assertThat(response.indicesStats.getDocs().getCount(), Matchers.equalTo(0l));
assertThat(response.indicesStats.getIndexCount(), Matchers.equalTo(1));
assertShardStats(response.getIndicesStats().getShards(), 1, 2, 2, 0.0);
Expand All @@ -81,12 +88,14 @@ public void testIndicesShardStats() {
index("test1", "type", "1", "f", "f");
refresh(); // make the doc visible
response = client().admin().cluster().prepareClusterStats().get();
assertThat(response.getStatus(), Matchers.equalTo(ClusterHealthStatus.GREEN));
assertThat(response.indicesStats.getDocs().getCount(), Matchers.equalTo(1l));
assertShardStats(response.getIndicesStats().getShards(), 1, 4, 2, 1.0);

prepareCreate("test2").setSettings("number_of_shards", 3, "number_of_replicas", 0).get();
ensureGreen();
response = client().admin().cluster().prepareClusterStats().get();
assertThat(response.getStatus(), Matchers.equalTo(ClusterHealthStatus.GREEN));
assertThat(response.indicesStats.getIndexCount(), Matchers.equalTo(2));
assertShardStats(response.getIndicesStats().getShards(), 2, 7, 5, 2.0 / 5);

Expand Down

0 comments on commit 36d1d22

Please sign in to comment.