From a47adfb270d2d336d21fb9a9c341c18f036b9ce1 Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Tue, 10 Nov 2015 15:24:58 +0100 Subject: [PATCH] Marvel: Index Nodes in Time Based Index and Data Index Closes elastic/elasticsearch#946 Original commit: elastic/x-pack-elasticsearch@0f5721ffbf689f3127a1f7b4661006a7a53b73c3 --- .../cluster/ClusterStateCollector.java | 30 ++++- .../cluster/ClusterStateNodeMarvelDoc.java | 29 +++++ .../cluster/DiscoveryNodeMarvelDoc.java | 24 ++++ .../collector/node/NodeStatsCollector.java | 3 +- .../marvel/agent/renderer/RendererModule.java | 6 +- .../cluster/ClusterStateNodeRenderer.java | 35 ++++++ .../cluster/ClusterStateRenderer.java | 1 - .../cluster/DiscoveryNodeRenderer.java | 54 +++++++++ .../main/resources/marvel_index_template.json | 22 +++- .../cluster/ClusterStateCollectorTests.java | 114 ++++++++++++------ .../renderer/cluster/ClusterStateTests.java | 79 ++++++++++++ .../test/resources/samples/cluster_state.json | 11 +- 12 files changed, 349 insertions(+), 59 deletions(-) create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/DiscoveryNodeRenderer.java diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java index abe7c7330dd..faaf64ff332 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollector.java @@ -9,6 +9,8 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.marvel.agent.collector.AbstractCollector; @@ -25,18 +27,20 @@ import java.util.List; /** * Collector for cluster state. *

- * This collector runs on the master node only and collects the {@link ClusterStateMarvelDoc} document + * This collector runs on the master node only and collects {@link ClusterStateMarvelDoc} document * at a given frequency. */ public class ClusterStateCollector extends AbstractCollector { public static final String NAME = "cluster-state-collector"; public static final String TYPE = "cluster_state"; + public static final String NODES_TYPE = "nodes"; + public static final String NODE_TYPE = "node"; private final Client client; @Inject - public ClusterStateCollector(Settings settings, ClusterService clusterService, MarvelSettings marvelSettings, MarvelLicensee marvelLicensee, + public ClusterStateCollector(Settings settings, ClusterService clusterService, MarvelSettings marvelSettings, MarvelLicensee marvelLicensee, SecuredClient client) { super(settings, NAME, clusterService, marvelSettings, marvelLicensee); this.client = client; @@ -49,12 +53,28 @@ public class ClusterStateCollector extends AbstractCollector doCollect() throws Exception { - List results = new ArrayList<>(1); + List results = new ArrayList<>(3); ClusterState clusterState = clusterService.state(); - ClusterHealthResponse clusterHealth = client.admin().cluster().prepareHealth().get(marvelSettings.clusterStateTimeout()); + String clusterUUID = clusterState.metaData().clusterUUID(); + String stateUUID = clusterState.stateUUID(); + long timestamp = System.currentTimeMillis(); + + // Adds a cluster_state document with associated status + ClusterHealthResponse clusterHealth = client.admin().cluster().prepareHealth().get(marvelSettings.clusterStateTimeout()); + results.add(new ClusterStateMarvelDoc(clusterUUID, TYPE, timestamp, clusterState, clusterHealth.getStatus())); + + DiscoveryNodes nodes = clusterState.nodes(); + if (nodes != null) { + for (DiscoveryNode node : nodes) { + // Adds a document for every node in the marvel timestamped index (type "nodes") + results.add(new ClusterStateNodeMarvelDoc(clusterUUID, NODES_TYPE, timestamp, stateUUID, node.getId())); + + // Adds a document for every node in the marvel data index (type "node") + results.add(new DiscoveryNodeMarvelDoc(MarvelSettings.MARVEL_DATA_INDEX_NAME, NODE_TYPE, node.getId(), clusterUUID, timestamp, node)); + } + } - results.add(new ClusterStateMarvelDoc(clusterUUID(), TYPE, System.currentTimeMillis(), clusterState, clusterHealth.getStatus())); return Collections.unmodifiableCollection(results); } } diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java new file mode 100644 index 00000000000..3ec6ba6710d --- /dev/null +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateNodeMarvelDoc.java @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.marvel.agent.collector.cluster; + +import org.elasticsearch.marvel.agent.exporter.MarvelDoc; + +public class ClusterStateNodeMarvelDoc extends MarvelDoc { + + private final String stateUUID; + private final String nodeId; + + public ClusterStateNodeMarvelDoc(String clusterUUID, String type, long timestamp, String stateUUID, String nodeId) { + super(clusterUUID, type, timestamp); + this.stateUUID = stateUUID; + this.nodeId = nodeId; + } + + public String getStateUUID() { + return stateUUID; + } + + public String getNodeId() { + return nodeId; + } +} + diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java new file mode 100644 index 00000000000..8af34289165 --- /dev/null +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/DiscoveryNodeMarvelDoc.java @@ -0,0 +1,24 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.marvel.agent.collector.cluster; + +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.marvel.agent.exporter.MarvelDoc; + +public class DiscoveryNodeMarvelDoc extends MarvelDoc { + + private final DiscoveryNode node; + + public DiscoveryNodeMarvelDoc(String index, String type, String id, String clusterUUID, long timestamp, DiscoveryNode node) { + super(index, type, id, clusterUUID, timestamp); + this.node = node; + } + + public DiscoveryNode getNode() { + return node; + } +} + diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java index 43fe39cb3ac..8e884b38f6d 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/node/NodeStatsCollector.java @@ -9,6 +9,7 @@ package org.elasticsearch.marvel.agent.collector.node; import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; import org.elasticsearch.bootstrap.BootstrapInfo; import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDecider; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; @@ -61,7 +62,7 @@ public class NodeStatsCollector extends AbstractCollector { // for nodes that can hold data. Client nodes can collect nodes stats because // elasticsearch correctly handles the nodes stats for client nodes. return super.shouldCollect() - && (clusterService.localNode().isDataNode() == false || nodeEnvironment.hasNodeFile()); + && (DiscoveryNode.nodeRequiresLocalStorage(settings) == false || nodeEnvironment.hasNodeFile()); } @Override diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java index 62c0631bb2e..931ae428612 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/RendererModule.java @@ -15,9 +15,7 @@ import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector; import org.elasticsearch.marvel.agent.collector.indices.IndicesStatsCollector; import org.elasticsearch.marvel.agent.collector.node.NodeStatsCollector; import org.elasticsearch.marvel.agent.collector.shards.ShardsCollector; -import org.elasticsearch.marvel.agent.renderer.cluster.ClusterInfoRenderer; -import org.elasticsearch.marvel.agent.renderer.cluster.ClusterStateRenderer; -import org.elasticsearch.marvel.agent.renderer.cluster.ClusterStatsRenderer; +import org.elasticsearch.marvel.agent.renderer.cluster.*; import org.elasticsearch.marvel.agent.renderer.indices.IndexRecoveryRenderer; import org.elasticsearch.marvel.agent.renderer.indices.IndexStatsRenderer; import org.elasticsearch.marvel.agent.renderer.indices.IndicesStatsRenderer; @@ -54,6 +52,8 @@ public class RendererModule extends AbstractModule { bind(ClusterStateRenderer.class).asEagerSingleton(); mbinder.addBinding(ClusterStateCollector.TYPE).to(ClusterStateRenderer.class); + mbinder.addBinding(ClusterStateCollector.NODES_TYPE).to(ClusterStateNodeRenderer.class); + mbinder.addBinding(ClusterStateCollector.NODE_TYPE).to(DiscoveryNodeRenderer.class); bind(ShardsRenderer.class).asEagerSingleton(); mbinder.addBinding(ShardsCollector.TYPE).to(ShardsRenderer.class); diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java new file mode 100644 index 00000000000..b2afa2464d8 --- /dev/null +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateNodeRenderer.java @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.marvel.agent.renderer.cluster; + +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentBuilderString; +import org.elasticsearch.marvel.agent.collector.cluster.ClusterStateNodeMarvelDoc; +import org.elasticsearch.marvel.agent.renderer.AbstractRenderer; + +import java.io.IOException; + +public class ClusterStateNodeRenderer extends AbstractRenderer { + + public ClusterStateNodeRenderer() { + super(null, false); + } + + @Override + protected void doRender(ClusterStateNodeMarvelDoc marvelDoc, XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.field(Fields.STATE_UUID, marvelDoc.getStateUUID()); + builder.startObject(Fields.NODE); + builder.field(Fields.ID, marvelDoc.getNodeId()); + builder.endObject(); + } + + static final class Fields { + static final XContentBuilderString STATE_UUID = new XContentBuilderString("state_uuid"); + static final XContentBuilderString NODE = new XContentBuilderString("node"); + static final XContentBuilderString ID = new XContentBuilderString("id"); + } +} diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java index 78f473edbcc..abf759d88b1 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateRenderer.java @@ -22,7 +22,6 @@ public class ClusterStateRenderer extends AbstractRenderer { + + public DiscoveryNodeRenderer() { + super(null, false); + } + + @Override + protected void doRender(DiscoveryNodeMarvelDoc marvelDoc, XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.startObject(Fields.NODE); + + DiscoveryNode node = marvelDoc.getNode(); + if (node != null) { + builder.field(Fields.NAME, node.getName()); + builder.field(Fields.TRANSPORT_ADDRESS, node.getAddress().toString()); + + builder.startObject(Fields.ATTRIBUTES); + for (ObjectObjectCursor attr : node.getAttributes()) { + builder.field(attr.key, attr.value); + } + builder.endObject(); + builder.field(Fields.ID, node.getId()); + } + + builder.endObject(); + } + + static final class Fields { + static final XContentBuilderString NODE = new XContentBuilderString("node"); + static final XContentBuilderString NAME = new XContentBuilderString("name"); + static final XContentBuilderString TRANSPORT_ADDRESS = new XContentBuilderString("transport_address"); + static final XContentBuilderString ATTRIBUTES = new XContentBuilderString("attributes"); + static final XContentBuilderString ID = new XContentBuilderString("id"); + } +} + + + diff --git a/marvel/src/main/resources/marvel_index_template.json b/marvel/src/main/resources/marvel_index_template.json index d367802d90b..30fb5121bae 100644 --- a/marvel/src/main/resources/marvel_index_template.json +++ b/marvel/src/main/resources/marvel_index_template.json @@ -186,9 +186,6 @@ "type": "string", "index": "not_analyzed" }, - "nodes": { - "enabled": false - }, "shards": { "type": "object" } @@ -199,6 +196,25 @@ "cluster_info": { "enabled": false }, + "node": { + "enabled": false + }, + "nodes": { + "properties": { + "state_uuid": { + "type": "string", + "index": "not_analyzed" + }, + "node": { + "properties": { + "id": { + "type": "string", + "index": "not_analyzed" + } + } + } + } + }, "node_stats": { "properties": { "node_stats": { diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java b/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java index 57078392eeb..2bf231c7750 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java +++ b/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStateCollectorTests.java @@ -14,32 +14,18 @@ import org.elasticsearch.marvel.agent.exporter.MarvelDoc; import org.elasticsearch.marvel.agent.settings.MarvelSettings; import org.elasticsearch.marvel.license.MarvelLicensee; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.*; public class ClusterStateCollectorTests extends AbstractCollectorTestCase { + public void testClusterStateCollectorNoIndices() throws Exception { - Collection results = newClusterStateCollector().doCollect(); - assertThat(results, hasSize(1)); - - MarvelDoc marvelDoc = results.iterator().next(); - assertNotNull(marvelDoc); - assertThat(marvelDoc, instanceOf(ClusterStateMarvelDoc.class)); - - ClusterStateMarvelDoc clusterStateMarvelDoc = (ClusterStateMarvelDoc) marvelDoc; - assertThat(clusterStateMarvelDoc.clusterUUID(), equalTo(client().admin().cluster().prepareState().setMetaData(true).get().getState().metaData().clusterUUID())); - assertThat(clusterStateMarvelDoc.timestamp(), greaterThan(0L)); - assertThat(clusterStateMarvelDoc.type(), equalTo(ClusterStateCollector.TYPE)); - assertNotNull(clusterStateMarvelDoc.getClusterState()); - - ClusterState clusterState = clusterStateMarvelDoc.getClusterState(); - assertThat(clusterState.getRoutingTable().allShards(), hasSize(0)); + assertMarvelDocs(newClusterStateCollector().doCollect(), 0); } public void testClusterStateCollectorOneIndex() throws Exception { @@ -56,33 +42,20 @@ public class ClusterStateCollectorTests extends AbstractCollectorTestCase { securedFlush(); securedRefresh(); + assertHitCount(client().prepareSearch().setSize(0).get(), nbDocs); - - Collection results = newClusterStateCollector().doCollect(); - assertThat(results, hasSize(1)); - - MarvelDoc marvelDoc = results.iterator().next(); - assertNotNull(marvelDoc); - assertThat(marvelDoc, instanceOf(ClusterStateMarvelDoc.class)); - - ClusterStateMarvelDoc clusterStateMarvelDoc = (ClusterStateMarvelDoc) marvelDoc; - assertThat(clusterStateMarvelDoc.clusterUUID(), equalTo(client().admin().cluster().prepareState().setMetaData(true).get().getState().metaData().clusterUUID())); - assertThat(clusterStateMarvelDoc.timestamp(), greaterThan(0L)); - assertThat(clusterStateMarvelDoc.type(), equalTo(ClusterStateCollector.TYPE)); - - assertNotNull(clusterStateMarvelDoc.getClusterState()); - - ClusterState clusterState = clusterStateMarvelDoc.getClusterState(); - assertThat(clusterState.getRoutingTable().allShards("test"), hasSize(nbShards)); + assertMarvelDocs(newClusterStateCollector().doCollect(), nbShards); } public void testClusterStateCollectorMultipleIndices() throws Exception { int nbIndices = randomIntBetween(1, 5); int[] docsPerIndex = new int[nbIndices]; int[] shardsPerIndex = new int[nbIndices]; + int nbShards = 0; for (int i = 0; i < nbIndices; i++) { shardsPerIndex[i] = randomIntBetween(1, 5); + nbShards += shardsPerIndex[i]; assertAcked(prepareCreate("test-" + i).setSettings(Settings.settingsBuilder() .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, shardsPerIndex[i]) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0) @@ -96,11 +69,14 @@ public class ClusterStateCollectorTests extends AbstractCollectorTestCase { securedFlush(); securedRefresh(); + for (int i = 0; i < nbIndices; i++) { assertHitCount(client().prepareSearch("test-" + i).setSize(0).get(), docsPerIndex[i]); } Collection results = newClusterStateCollector().doCollect(); + assertMarvelDocs(results, nbShards); + MarvelDoc marvelDoc = results.iterator().next(); assertNotNull(marvelDoc); assertThat(marvelDoc, instanceOf(ClusterStateMarvelDoc.class)); @@ -168,4 +144,70 @@ public class ClusterStateCollectorTests extends AbstractCollectorTestCase { internalCluster().getInstance(MarvelLicensee.class, nodeId), securedClient(nodeId)); } + + private void assertMarvelDocs(Collection results, final int nbShards) { + assertThat("expecting 1 document for the cluster state and 2 documents per node", results, hasSize(1 + internalCluster().size() * 2)); + + final ClusterState clusterState = securedClient().admin().cluster().prepareState().get().getState(); + final String clusterUUID = clusterState.getMetaData().clusterUUID(); + final String stateUUID = clusterState.stateUUID(); + + List clusterStateNodes = new ArrayList<>(); + List discoveryNodes = new ArrayList<>(); + + for (MarvelDoc marvelDoc : results) { + assertThat(marvelDoc.clusterUUID(), equalTo(clusterUUID)); + assertThat(marvelDoc.timestamp(), greaterThan(0L)); + assertThat(marvelDoc, anyOf(instanceOf(ClusterStateMarvelDoc.class), instanceOf(ClusterStateNodeMarvelDoc.class), instanceOf(DiscoveryNodeMarvelDoc.class))); + + switch (marvelDoc.type()) { + case ClusterStateCollector.TYPE: + ClusterStateMarvelDoc clusterStateMarvelDoc = (ClusterStateMarvelDoc) marvelDoc; + assertThat(clusterStateMarvelDoc.getClusterState().getRoutingTable().allShards(), hasSize(nbShards)); + break; + + case ClusterStateCollector.NODES_TYPE: + ClusterStateNodeMarvelDoc clusterStateNodeMarvelDoc = (ClusterStateNodeMarvelDoc) marvelDoc; + assertThat(clusterStateNodeMarvelDoc.getStateUUID(), equalTo(stateUUID)); + assertThat(clusterStateNodeMarvelDoc.getNodeId(), not(isEmptyOrNullString())); + clusterStateNodes.add(clusterStateNodeMarvelDoc); + break; + + case ClusterStateCollector.NODE_TYPE: + DiscoveryNodeMarvelDoc discoveryNodeMarvelDoc = (DiscoveryNodeMarvelDoc) marvelDoc; + assertThat(discoveryNodeMarvelDoc.index(), equalTo(MarvelSettings.MARVEL_DATA_INDEX_NAME)); + assertThat(discoveryNodeMarvelDoc.id(), not(isEmptyOrNullString())); + assertNotNull(discoveryNodeMarvelDoc.getNode()); + discoveryNodes.add(discoveryNodeMarvelDoc); + break; + default: + fail("unknown marvel document type " + marvelDoc.type()); + } + } + + assertThat(clusterStateNodes, hasSize(internalCluster().size())); + assertThat(discoveryNodes, hasSize(internalCluster().size())); + + for (final String nodeName : internalCluster().getNodeNames()) { + final String nodeId = internalCluster().clusterService(nodeName).localNode().getId(); + + boolean found = false; + for (ClusterStateNodeMarvelDoc doc : clusterStateNodes) { + if (nodeId.equals(doc.getNodeId())) { + found = true; + break; + } + } + assertTrue("Could not find node id [" + nodeName + "]", found); + + found = false; + for (DiscoveryNodeMarvelDoc doc : discoveryNodes) { + if (nodeName.equals(doc.getNode().getName())) { + found = true; + break; + } + } + assertTrue("Could not find node name [" + nodeName + "]", found); + } + } } diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java b/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java index ef2d1fe00d2..2405147adac 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java +++ b/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStateTests.java @@ -10,6 +10,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.marvel.agent.collector.cluster.ClusterStateCollector; +import org.elasticsearch.marvel.agent.renderer.AbstractRenderer; import org.elasticsearch.marvel.agent.settings.MarvelSettings; import org.elasticsearch.marvel.test.MarvelIntegTestCase; import org.elasticsearch.search.SearchHit; @@ -23,6 +24,8 @@ import java.util.concurrent.TimeUnit; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.core.Is.is; @ClusterScope(scope = Scope.TEST) public class ClusterStateTests extends MarvelIntegTestCase { @@ -89,4 +92,80 @@ public class ClusterStateTests extends MarvelIntegTestCase { .setTypes(ClusterStateCollector.TYPE) .setQuery(QueryBuilders.matchQuery("cluster_state.nodes." + nodes.masterNodeId() + ".name", nodes.masterNode().name())).get(), 0L); } + + public void testClusterStateNodes() throws Exception { + final long nbNodes = internalCluster().size(); + + logger.debug("--> waiting for documents to be collected"); + awaitMarvelDocsCount(greaterThanOrEqualTo(nbNodes), ClusterStateCollector.NODES_TYPE); + + logger.debug("--> searching for marvel documents of type [{}]", ClusterStateCollector.NODES_TYPE); + SearchResponse response = client().prepareSearch().setTypes(ClusterStateCollector.NODES_TYPE).get(); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(nbNodes)); + + logger.debug("--> checking that every document contains the expected fields"); + String[] filters = { + AbstractRenderer.Fields.CLUSTER_UUID.underscore().toString(), + AbstractRenderer.Fields.TIMESTAMP.underscore().toString(), + ClusterStateNodeRenderer.Fields.STATE_UUID.underscore().toString(), + ClusterStateNodeRenderer.Fields.NODE.underscore().toString(), + ClusterStateNodeRenderer.Fields.NODE.underscore().toString() + "." + ClusterStateNodeRenderer.Fields.ID.underscore().toString(), + }; + + for (SearchHit searchHit : response.getHits().getHits()) { + Map fields = searchHit.sourceAsMap(); + + for (String filter : filters) { + assertContains(filter, fields); + } + } + + logger.debug("--> cluster state nodes successfully collected"); + } + + public void testClusterStateNode() throws Exception { + final long nbNodes = internalCluster().size(); + + logger.debug("--> waiting for documents to be collected"); + awaitMarvelDocsCount(greaterThanOrEqualTo(nbNodes), ClusterStateCollector.NODE_TYPE); + + logger.debug("--> searching for marvel documents of type [{}]", ClusterStateCollector.NODE_TYPE); + SearchResponse response = client().prepareSearch().setTypes(ClusterStateCollector.NODE_TYPE).get(); + assertThat(response.getHits().getTotalHits(), greaterThanOrEqualTo(nbNodes)); + + logger.debug("--> checking that every document contains the expected fields"); + String[] filters = { + AbstractRenderer.Fields.CLUSTER_UUID.underscore().toString(), + AbstractRenderer.Fields.TIMESTAMP.underscore().toString(), + DiscoveryNodeRenderer.Fields.NODE.underscore().toString(), + DiscoveryNodeRenderer.Fields.NODE.underscore().toString() + "." + DiscoveryNodeRenderer.Fields.ID.underscore().toString(), + DiscoveryNodeRenderer.Fields.NODE.underscore().toString() + "." + DiscoveryNodeRenderer.Fields.NAME.underscore().toString(), + DiscoveryNodeRenderer.Fields.NODE.underscore().toString() + "." + DiscoveryNodeRenderer.Fields.ATTRIBUTES.underscore().toString(), + DiscoveryNodeRenderer.Fields.NODE.underscore().toString() + "." + DiscoveryNodeRenderer.Fields.TRANSPORT_ADDRESS.underscore().toString(), + }; + + for (SearchHit searchHit : response.getHits().getHits()) { + Map fields = searchHit.sourceAsMap(); + + for (String filter : filters) { + assertContains(filter, fields); + } + } + + for (final String nodeName : internalCluster().getNodeNames()) { + final String nodeId = internalCluster().clusterService(nodeName).localNode().getId(); + + logger.debug("--> getting marvel document for node id [{}]", nodeId); + assertThat(client().prepareGet(MarvelSettings.MARVEL_DATA_INDEX_NAME, ClusterStateCollector.NODE_TYPE, nodeId).get().isExists(), is(true)); + + // checks that document is not indexed + assertHitCount(client().prepareSearch().setSize(0) + .setTypes(ClusterStateCollector.NODE_TYPE) + .setQuery(QueryBuilders.boolQuery() + .should(QueryBuilders.matchQuery("node.id", nodeId)) + .should(QueryBuilders.matchQuery("node.name", nodeName))).get(), 0); + } + + logger.debug("--> cluster state node successfully collected"); + } } diff --git a/marvel/src/test/resources/samples/cluster_state.json b/marvel/src/test/resources/samples/cluster_state.json index 7066face4ab..24ec82416a9 100644 --- a/marvel/src/test/resources/samples/cluster_state.json +++ b/marvel/src/test/resources/samples/cluster_state.json @@ -5,15 +5,6 @@ "status": "yellow", "version": 14, "state_uuid": "lj0hNoO9QaeNa1eR2ukktQ", - "master_node": "__node_id__", - "nodes": { - "__node_id__": { - "name": "Box", - "transport_address": "inet[/127.0.0.1:9300]", - "attributes": { - "local": "true" - } - } - } + "master_node": "__node_id__" } } \ No newline at end of file