adapt cluster stats api to node.client setting removal

The cluster stats api now returns counts for each node role. The `master_data`, `master_only`, `data_only` and `client` fields have been removed from the response in favour of `master`, `data`, `ingest` and `coordinating_only`. The same node can have multiple roles, hence contribute to multiple roles counts. Every node is implicitly a coordinating node, so whenever a node has no explicit roles, it will be counted as coordinating only.
This commit is contained in:
javanna 2016-03-04 14:15:49 +01:00 committed by Luca Cavanna
parent f786e9866c
commit 9c4a5bbe7e
5 changed files with 107 additions and 70 deletions

View File

@ -41,7 +41,9 @@ import org.elasticsearch.plugins.PluginInfo;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map;
import java.util.Set; import java.util.Set;
public class ClusterStatsNodes implements ToXContent, Streamable { public class ClusterStatsNodes implements ToXContent, Streamable {
@ -213,25 +215,29 @@ public class ClusterStatsNodes implements ToXContent, Streamable {
} }
public static class Counts implements Streamable, ToXContent { public static class Counts implements Streamable, ToXContent {
int total; static final String COORDINATING_ONLY = "coordinating_only";
int masterOnly;
int dataOnly; private int total;
int masterData; private Map<String, Integer> roles;
int client;
Counts() {
roles = new HashMap<>();
for (DiscoveryNode.Role role : DiscoveryNode.Role.values()) {
roles.put(role.getRoleName(), 0);
}
roles.put(COORDINATING_ONLY, 0);
}
public void addNodeInfo(NodeInfo nodeInfo) { public void addNodeInfo(NodeInfo nodeInfo) {
total++; total++;
DiscoveryNode node = nodeInfo.getNode(); if (nodeInfo.getNode().getRoles().size() == 0) {
if (node.masterNode()) { Integer count = roles.get(COORDINATING_ONLY);
if (node.dataNode()) { roles.put(COORDINATING_ONLY, ++count);
masterData++;
} else { } else {
masterOnly++; for (DiscoveryNode.Role role : nodeInfo.getNode().getRoles()) {
Integer count = roles.get(role.getRoleName());
roles.put(role.getRoleName(), ++count);
} }
} else if (node.dataNode()) {
dataOnly++;
} else if (node.clientNode()) {
client++;
} }
} }
@ -239,20 +245,8 @@ public class ClusterStatsNodes implements ToXContent, Streamable {
return total; return total;
} }
public int getMasterOnly() { public Map<String, Integer> getRoles() {
return masterOnly; return roles;
}
public int getDataOnly() {
return dataOnly;
}
public int getMasterData() {
return masterData;
}
public int getClient() {
return client;
} }
public static Counts readCounts(StreamInput in) throws IOException { public static Counts readCounts(StreamInput in) throws IOException {
@ -262,38 +256,28 @@ public class ClusterStatsNodes implements ToXContent, Streamable {
} }
@Override @Override
@SuppressWarnings("unchecked")
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
total = in.readVInt(); total = in.readVInt();
masterOnly = in.readVInt(); roles = (Map<String, Integer>)in.readGenericValue();
dataOnly = in.readVInt();
masterData = in.readVInt();
client = in.readVInt();
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(total); out.writeVInt(total);
out.writeVInt(masterOnly); out.writeGenericValue(roles);
out.writeVInt(dataOnly);
out.writeVInt(masterData);
out.writeVInt(client);
} }
static final class Fields { static final class Fields {
static final XContentBuilderString TOTAL = new XContentBuilderString("total"); static final XContentBuilderString TOTAL = new XContentBuilderString("total");
static final XContentBuilderString MASTER_ONLY = new XContentBuilderString("master_only");
static final XContentBuilderString DATA_ONLY = new XContentBuilderString("data_only");
static final XContentBuilderString MASTER_DATA = new XContentBuilderString("master_data");
static final XContentBuilderString CLIENT = new XContentBuilderString("client");
} }
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.field(Fields.TOTAL, total); builder.field(Fields.TOTAL, total);
builder.field(Fields.MASTER_ONLY, masterOnly); for (Map.Entry<String, Integer> entry : roles.entrySet()) {
builder.field(Fields.DATA_ONLY, dataOnly); builder.field(entry.getKey(), entry.getValue());
builder.field(Fields.MASTER_DATA, masterData); }
builder.field(Fields.CLIENT, client);
return builder; return builder;
} }
} }

View File

@ -20,7 +20,6 @@
package org.elasticsearch.rest.action.admin.cluster.stats; package org.elasticsearch.rest.action.admin.cluster.stats;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequest; import org.elasticsearch.action.admin.cluster.stats.ClusterStatsRequest;
import org.elasticsearch.action.admin.cluster.stats.ClusterStatsResponse;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -47,6 +46,6 @@ public class RestClusterStatsAction extends BaseRestHandler {
public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) {
ClusterStatsRequest clusterStatsRequest = new ClusterStatsRequest().nodesIds(request.paramAsStringArray("nodeId", null)); ClusterStatsRequest clusterStatsRequest = new ClusterStatsRequest().nodesIds(request.paramAsStringArray("nodeId", null));
clusterStatsRequest.timeout(request.param("timeout")); clusterStatsRequest.timeout(request.param("timeout"));
client.admin().cluster().clusterStats(clusterStatsRequest, new RestToXContentListener<ClusterStatsResponse>(channel)); client.admin().cluster().clusterStats(clusterStatsRequest, new RestToXContentListener<>(channel));
} }
} }

View File

@ -23,6 +23,7 @@ import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.Requests; import org.elasticsearch.client.Requests;
import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.Priority; import org.elasticsearch.common.Priority;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.EsExecutors; import org.elasticsearch.common.util.concurrent.EsExecutors;
@ -34,6 +35,8 @@ import org.elasticsearch.test.ESIntegTestCase.Scope;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.elasticsearch.common.settings.Settings.settingsBuilder; import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
@ -43,12 +46,9 @@ import static org.hamcrest.Matchers.is;
@ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0) @ClusterScope(scope = Scope.SUITE, numDataNodes = 1, numClientNodes = 0)
public class ClusterStatsIT extends ESIntegTestCase { public class ClusterStatsIT extends ESIntegTestCase {
private void assertCounts(ClusterStatsNodes.Counts counts, int total, int masterOnly, int dataOnly, int masterData, int client) { private void assertCounts(ClusterStatsNodes.Counts counts, int total, Map<String, Integer> roles) {
assertThat(counts.getTotal(), Matchers.equalTo(total)); assertThat(counts.getTotal(), equalTo(total));
assertThat(counts.getMasterOnly(), Matchers.equalTo(masterOnly)); assertThat(counts.getRoles(), equalTo(roles));
assertThat(counts.getDataOnly(), Matchers.equalTo(dataOnly));
assertThat(counts.getMasterData(), Matchers.equalTo(masterData));
assertThat(counts.getClient(), Matchers.equalTo(client));
} }
private void waitForNodes(int numNodes) { private void waitForNodes(int numNodes) {
@ -58,25 +58,53 @@ public class ClusterStatsIT extends ESIntegTestCase {
} }
public void testNodeCounts() { public void testNodeCounts() {
int total = 1;
Map<String, Integer> expectedCounts = new HashMap<>();
expectedCounts.put(DiscoveryNode.Role.DATA.getRoleName(), 1);
expectedCounts.put(DiscoveryNode.Role.MASTER.getRoleName(), 1);
expectedCounts.put(DiscoveryNode.Role.INGEST.getRoleName(), 1);
expectedCounts.put(ClusterStatsNodes.Counts.COORDINATING_ONLY, 0);
int numNodes = randomIntBetween(1, 5);
ClusterStatsResponse response = client().admin().cluster().prepareClusterStats().get(); ClusterStatsResponse response = client().admin().cluster().prepareClusterStats().get();
assertCounts(response.getNodesStats().getCounts(), 1, 0, 0, 1, 0); assertCounts(response.getNodesStats().getCounts(), total, expectedCounts);
internalCluster().startNode(Settings.builder().put(Node.NODE_DATA_SETTING.getKey(), false)); for (int i = 0; i < numNodes; i++) {
waitForNodes(2); boolean isDataNode = randomBoolean();
response = client().admin().cluster().prepareClusterStats().get(); boolean isMasterNode = randomBoolean();
assertCounts(response.getNodesStats().getCounts(), 2, 1, 0, 1, 0); boolean isIngestNode = randomBoolean();
Settings settings = Settings.builder().put(Node.NODE_DATA_SETTING.getKey(), isDataNode)
.put(Node.NODE_MASTER_SETTING.getKey(), isMasterNode).put(Node.NODE_INGEST_SETTING.getKey(), isIngestNode)
.build();
internalCluster().startNode(settings);
total++;
waitForNodes(total);
internalCluster().startNode(Settings.builder().put(Node.NODE_MASTER_SETTING.getKey(), false)); if (isDataNode) {
waitForNodes(3); incrementCountForRole(DiscoveryNode.Role.DATA.getRoleName(), expectedCounts);
response = client().admin().cluster().prepareClusterStats().get(); }
assertCounts(response.getNodesStats().getCounts(), 3, 1, 1, 1, 0); if (isMasterNode) {
incrementCountForRole(DiscoveryNode.Role.MASTER.getRoleName(), expectedCounts);
internalCluster().startNode(Settings.builder().put(Node.NODE_CLIENT_SETTING.getKey(), true)); }
waitForNodes(4); if (isIngestNode) {
response = client().admin().cluster().prepareClusterStats().get(); incrementCountForRole(DiscoveryNode.Role.INGEST.getRoleName(), expectedCounts);
assertCounts(response.getNodesStats().getCounts(), 4, 1, 1, 1, 1); }
if (!isDataNode && !isMasterNode && !isIngestNode) {
incrementCountForRole(ClusterStatsNodes.Counts.COORDINATING_ONLY, expectedCounts);
} }
response = client().admin().cluster().prepareClusterStats().get();
assertCounts(response.getNodesStats().getCounts(), total, expectedCounts);
}
}
private static void incrementCountForRole(String role, Map<String, Integer> counts) {
Integer count = counts.get(role);
if (count == null) {
counts.put(role, 1);
} else {
counts.put(role, ++count);
}
}
private void assertShardStats(ClusterStatsIndices.ShardStats stats, int indices, int total, int primaries, double replicationFactor) { private void assertShardStats(ClusterStatsIndices.ShardStats stats, int indices, int total, int primaries, double replicationFactor) {
assertThat(stats.getIndices(), Matchers.equalTo(indices)); assertThat(stats.getIndices(), Matchers.equalTo(indices));

View File

@ -92,10 +92,10 @@ Will return, for example:
"nodes": { "nodes": {
"count": { "count": {
"total": 2, "total": 2,
"master_only": 0, "master": 2,
"data_only": 0, "data": 2,
"master_data": 2, "ingest": 2,
"client": 0 "coordinating_only": 0
}, },
"versions": [ "versions": [
"{version}" "{version}"

View File

@ -0,0 +1,26 @@
---
"cluster stats test":
- do:
cluster.stats: {}
- is_true: timestamp
- is_true: cluster_name
- match: {status: green}
- gte: { indices.count: 0}
- is_true: indices.docs
- is_true: indices.store
- is_true: indices.fielddata
- is_true: indices.query_cache
- is_true: indices.completion
- is_true: indices.segments
- is_true: indices.percolate
- gte: { nodes.count.total: 1}
- gte: { nodes.count.master: 1}
- gte: { nodes.count.data: 1}
- gte: { nodes.count.ingest: 0}
- gte: { nodes.count.coordinating_only: 0}
- is_true: nodes.os
- is_true: nodes.process
- is_true: nodes.jvm
- is_true: nodes.fs
- is_true: nodes.plugins