Marvel: Add Cluster State collector
closes elastic/elasticsearch-marvelelastic/elasticsearch#445 Original commit: elastic/x-pack-elasticsearch@28c8b0f5af
This commit is contained in:
parent
52be1aa943
commit
5b519935be
|
@ -7,11 +7,13 @@ package org.elasticsearch.marvel.agent.collector;
|
||||||
|
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchTimeoutException;
|
import org.elasticsearch.ElasticsearchTimeoutException;
|
||||||
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.settings.MarvelSettingsService;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@ -20,12 +22,17 @@ public abstract class AbstractCollector<T> extends AbstractLifecycleComponent<T>
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
protected final ClusterService clusterService;
|
protected final ClusterService clusterService;
|
||||||
|
protected final ClusterName clusterName;
|
||||||
|
protected final MarvelSettingsService marvelSettings;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AbstractCollector(Settings settings, String name, ClusterService clusterService) {
|
public AbstractCollector(Settings settings, String name, ClusterService clusterService,
|
||||||
|
ClusterName clusterName, MarvelSettingsService marvelSettings) {
|
||||||
super(settings);
|
super(settings);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.clusterService = clusterService;
|
this.clusterService = clusterService;
|
||||||
|
this.clusterName = clusterName;
|
||||||
|
this.marvelSettings = marvelSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.marvel.agent.collector;
|
||||||
|
|
||||||
import org.elasticsearch.common.inject.AbstractModule;
|
import org.elasticsearch.common.inject.AbstractModule;
|
||||||
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
import org.elasticsearch.common.inject.multibindings.Multibinder;
|
||||||
|
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStateCollector;
|
||||||
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStatsCollector;
|
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStatsCollector;
|
||||||
import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector;
|
import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector;
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ public class CollectorModule extends AbstractModule {
|
||||||
// Registers default collectors
|
// Registers default collectors
|
||||||
registerCollector(IndexStatsCollector.class);
|
registerCollector(IndexStatsCollector.class);
|
||||||
registerCollector(ClusterStatsCollector.class);
|
registerCollector(ClusterStatsCollector.class);
|
||||||
|
registerCollector(ClusterStateCollector.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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 com.google.common.collect.ImmutableList;
|
||||||
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
|
||||||
|
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
|
||||||
|
import org.elasticsearch.client.Client;
|
||||||
|
import org.elasticsearch.cluster.ClusterName;
|
||||||
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.marvel.agent.collector.AbstractCollector;
|
||||||
|
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.settings.MarvelSettingsService;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collector for cluster state.
|
||||||
|
* <p/>
|
||||||
|
* This collector runs on the master node only and collects the {@link ClusterStateMarvelDoc} document
|
||||||
|
* at a given frequency.
|
||||||
|
*/
|
||||||
|
public class ClusterStateCollector extends AbstractCollector<ClusterStateCollector> {
|
||||||
|
|
||||||
|
public static final String NAME = "cluster-state-collector";
|
||||||
|
public static final String TYPE = "marvel_cluster_state";
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ClusterStateCollector(Settings settings, ClusterService clusterService,
|
||||||
|
ClusterName clusterName, MarvelSettingsService marvelSettings, Client client) {
|
||||||
|
super(settings, NAME, clusterService, clusterName, marvelSettings);
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean masterOnly() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<MarvelDoc> doCollect() throws Exception {
|
||||||
|
ImmutableList.Builder<MarvelDoc> results = ImmutableList.builder();
|
||||||
|
|
||||||
|
ClusterState clusterState = clusterService.state();
|
||||||
|
ClusterHealthResponse clusterHealth = client.admin().cluster().prepareHealth().get(marvelSettings.clusterStateTimeout());
|
||||||
|
|
||||||
|
results.add(buildMarvelDoc(clusterName.value(), TYPE, System.currentTimeMillis(), clusterState, clusterHealth.getStatus()));
|
||||||
|
return results.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MarvelDoc buildMarvelDoc(String clusterName, String type, long timestamp, ClusterState clusterState, ClusterHealthStatus status) {
|
||||||
|
return ClusterStateMarvelDoc.createMarvelDoc(clusterName, type, timestamp, clusterState, status);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.cluster.health.ClusterHealthStatus;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
|
|
||||||
|
public class ClusterStateMarvelDoc extends MarvelDoc<ClusterStateMarvelDoc.Payload> {
|
||||||
|
|
||||||
|
private final Payload payload;
|
||||||
|
|
||||||
|
public ClusterStateMarvelDoc(String clusterName, String type, long timestamp, Payload payload) {
|
||||||
|
super(clusterName, type, timestamp);
|
||||||
|
this.payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClusterStateMarvelDoc.Payload payload() {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClusterStateMarvelDoc createMarvelDoc(String clusterName, String type, long timestamp, ClusterState clusterState, ClusterHealthStatus status) {
|
||||||
|
return new ClusterStateMarvelDoc(clusterName, type, timestamp, new Payload(clusterState, status));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Payload {
|
||||||
|
|
||||||
|
private final ClusterState clusterState;
|
||||||
|
private final ClusterHealthStatus status;
|
||||||
|
|
||||||
|
Payload(ClusterState clusterState, ClusterHealthStatus status) {
|
||||||
|
this.clusterState = clusterState;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClusterState getClusterState() {
|
||||||
|
return clusterState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClusterHealthStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,12 +14,13 @@ import org.elasticsearch.common.inject.Inject;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.marvel.agent.collector.AbstractCollector;
|
import org.elasticsearch.marvel.agent.collector.AbstractCollector;
|
||||||
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.settings.MarvelSettingsService;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collector for cluster stats.
|
* Collector for cluster stats.
|
||||||
* <p>
|
* <p/>
|
||||||
* This collector runs on the master node only and collects the {@link ClusterStatsMarvelDoc} document
|
* This collector runs on the master node only and collects the {@link ClusterStatsMarvelDoc} document
|
||||||
* at a given frequency.
|
* at a given frequency.
|
||||||
*/
|
*/
|
||||||
|
@ -28,13 +29,12 @@ public class ClusterStatsCollector extends AbstractCollector<ClusterStatsCollect
|
||||||
public static final String NAME = "cluster-stats-collector";
|
public static final String NAME = "cluster-stats-collector";
|
||||||
public static final String TYPE = "marvel_cluster_stats";
|
public static final String TYPE = "marvel_cluster_stats";
|
||||||
|
|
||||||
private final ClusterName clusterName;
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ClusterStatsCollector(Settings settings, ClusterService clusterService, ClusterName clusterName, Client client) {
|
public ClusterStatsCollector(Settings settings, ClusterService clusterService,
|
||||||
super(settings, NAME, clusterService);
|
ClusterName clusterName, MarvelSettingsService marvelSettings, Client client) {
|
||||||
this.clusterName = clusterName;
|
super(settings, NAME, clusterService, clusterName, marvelSettings);
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,16 +30,13 @@ public class IndexStatsCollector extends AbstractCollector<IndexStatsCollector>
|
||||||
public static final String NAME = "index-stats-collector";
|
public static final String NAME = "index-stats-collector";
|
||||||
public static final String TYPE = "marvel_index_stats";
|
public static final String TYPE = "marvel_index_stats";
|
||||||
|
|
||||||
private final ClusterName clusterName;
|
|
||||||
private final Client client;
|
private final Client client;
|
||||||
private final MarvelSettingsService marvelSettings;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public IndexStatsCollector(Settings settings, ClusterService clusterService, ClusterName clusterName, Client client, MarvelSettingsService marvelSettings) {
|
public IndexStatsCollector(Settings settings, ClusterService clusterService,
|
||||||
super(settings, NAME, clusterService);
|
ClusterName clusterName, MarvelSettingsService marvelSettings, Client client) {
|
||||||
|
super(settings, NAME, clusterService, clusterName, marvelSettings);
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.clusterName = clusterName;
|
|
||||||
this.marvelSettings = marvelSettings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,8 +7,10 @@ package org.elasticsearch.marvel.agent.renderer;
|
||||||
|
|
||||||
import org.elasticsearch.common.inject.AbstractModule;
|
import org.elasticsearch.common.inject.AbstractModule;
|
||||||
import org.elasticsearch.common.inject.multibindings.MapBinder;
|
import org.elasticsearch.common.inject.multibindings.MapBinder;
|
||||||
|
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStateCollector;
|
||||||
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStatsCollector;
|
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStatsCollector;
|
||||||
import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector;
|
import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector;
|
||||||
|
import org.elasticsearch.marvel.agent.renderer.cluster.ClusterStateRenderer;
|
||||||
import org.elasticsearch.marvel.agent.renderer.cluster.ClusterStatsRenderer;
|
import org.elasticsearch.marvel.agent.renderer.cluster.ClusterStatsRenderer;
|
||||||
import org.elasticsearch.marvel.agent.renderer.indices.IndexStatsRenderer;
|
import org.elasticsearch.marvel.agent.renderer.indices.IndexStatsRenderer;
|
||||||
|
|
||||||
|
@ -34,6 +36,9 @@ public class RendererModule extends AbstractModule {
|
||||||
bind(ClusterStatsRenderer.class).asEagerSingleton();
|
bind(ClusterStatsRenderer.class).asEagerSingleton();
|
||||||
mbinder.addBinding(ClusterStatsCollector.TYPE).to(ClusterStatsRenderer.class);
|
mbinder.addBinding(ClusterStatsCollector.TYPE).to(ClusterStatsRenderer.class);
|
||||||
|
|
||||||
|
bind(ClusterStateRenderer.class).asEagerSingleton();
|
||||||
|
mbinder.addBinding(ClusterStateCollector.TYPE).to(ClusterStateRenderer.class);
|
||||||
|
|
||||||
for (Map.Entry<String, Class<? extends Renderer>> entry : renderers.entrySet()) {
|
for (Map.Entry<String, Class<? extends Renderer>> entry : renderers.entrySet()) {
|
||||||
bind(entry.getValue()).asEagerSingleton();
|
bind(entry.getValue()).asEagerSingleton();
|
||||||
mbinder.addBinding(entry.getKey()).to(entry.getValue());
|
mbinder.addBinding(entry.getKey()).to(entry.getValue());
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* 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.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.routing.RoutingTable;
|
||||||
|
import org.elasticsearch.cluster.routing.ShardRouting;
|
||||||
|
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.ClusterStateMarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.renderer.AbstractRenderer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class ClusterStateRenderer extends AbstractRenderer<ClusterStateMarvelDoc> {
|
||||||
|
|
||||||
|
private static final String[] FILTERS = {
|
||||||
|
"cluster_state.version",
|
||||||
|
"cluster_state.master_node",
|
||||||
|
"cluster_state.status",
|
||||||
|
"cluster_state.nodes",
|
||||||
|
"cluster_state.shards",
|
||||||
|
};
|
||||||
|
|
||||||
|
public ClusterStateRenderer() {
|
||||||
|
super(FILTERS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRender(ClusterStateMarvelDoc marvelDoc, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||||
|
builder.startObject(Fields.CLUSTER_STATE);
|
||||||
|
|
||||||
|
ClusterStateMarvelDoc.Payload payload = marvelDoc.payload();
|
||||||
|
if (payload != null) {
|
||||||
|
ClusterState clusterState = payload.getClusterState();
|
||||||
|
if (clusterState != null) {
|
||||||
|
builder.field(Fields.STATUS, payload.getStatus().name().toLowerCase(Locale.ROOT));
|
||||||
|
|
||||||
|
clusterState.toXContent(builder, params);
|
||||||
|
|
||||||
|
RoutingTable routingTable = clusterState.routingTable();
|
||||||
|
if (routingTable != null) {
|
||||||
|
List<ShardRouting> shards = routingTable.allShards();
|
||||||
|
if (shards != null) {
|
||||||
|
|
||||||
|
builder.startArray(Fields.SHARDS);
|
||||||
|
for (ShardRouting shard : shards) {
|
||||||
|
shard.toXContent(builder, params);
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class Fields {
|
||||||
|
static final XContentBuilderString CLUSTER_STATE = new XContentBuilderString("cluster_state");
|
||||||
|
static final XContentBuilderString STATUS = new XContentBuilderString("status");
|
||||||
|
static final XContentBuilderString SHARDS = new XContentBuilderString("shards");
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,9 +30,9 @@ public class IndexStatsRenderer extends AbstractRenderer<IndexStatsMarvelDoc> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doRender(IndexStatsMarvelDoc marvelDoc, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
protected void doRender(IndexStatsMarvelDoc marvelDoc, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||||
IndexStatsMarvelDoc.Payload payload = marvelDoc.payload();
|
|
||||||
|
|
||||||
builder.startObject(Fields.INDEX_STATS);
|
builder.startObject(Fields.INDEX_STATS);
|
||||||
|
|
||||||
|
IndexStatsMarvelDoc.Payload payload = marvelDoc.payload();
|
||||||
if (payload != null) {
|
if (payload != null) {
|
||||||
IndexStats indexStats = payload.getIndexStats();
|
IndexStats indexStats = payload.getIndexStats();
|
||||||
if (indexStats != null) {
|
if (indexStats != null) {
|
||||||
|
|
|
@ -27,11 +27,13 @@ public class MarvelSettingsService extends AbstractComponent implements NodeSett
|
||||||
private final List<MarvelSetting> settings;
|
private final List<MarvelSetting> settings;
|
||||||
|
|
||||||
final TimeValueSetting indexStatsTimeout = MarvelSetting.timeSetting(PREFIX + "index.stats.timeout", TimeValue.timeValueMinutes(10),
|
final TimeValueSetting indexStatsTimeout = MarvelSetting.timeSetting(PREFIX + "index.stats.timeout", TimeValue.timeValueMinutes(10),
|
||||||
"Timeout value when collecting Index Stats (default to 10m)");
|
"Timeout value when collecting indices statistics (default to 10m)");
|
||||||
|
|
||||||
final StringArraySetting indices = MarvelSetting.arraySetting(PREFIX + "indices", Strings.EMPTY_ARRAY,
|
final StringArraySetting indices = MarvelSetting.arraySetting(PREFIX + "indices", Strings.EMPTY_ARRAY,
|
||||||
"List of indices names whose stats will be exported (default to all indices)");
|
"List of indices names whose stats will be exported (default to all indices)");
|
||||||
|
|
||||||
|
final TimeValueSetting clusterStateTimeout = MarvelSetting.timeSetting(PREFIX + "cluster.state.timeout", TimeValue.timeValueMinutes(10),
|
||||||
|
"Timeout value when collecting the cluster state (default to 10m)");
|
||||||
|
|
||||||
MarvelSettingsService(Settings clusterSettings) {
|
MarvelSettingsService(Settings clusterSettings) {
|
||||||
super(clusterSettings);
|
super(clusterSettings);
|
||||||
|
@ -40,6 +42,7 @@ public class MarvelSettingsService extends AbstractComponent implements NodeSett
|
||||||
ImmutableList.Builder<MarvelSetting> builder = ImmutableList.builder();
|
ImmutableList.Builder<MarvelSetting> builder = ImmutableList.builder();
|
||||||
builder.add(indexStatsTimeout);
|
builder.add(indexStatsTimeout);
|
||||||
builder.add(indices);
|
builder.add(indices);
|
||||||
|
builder.add(clusterStateTimeout);
|
||||||
this.settings = builder.build();
|
this.settings = builder.build();
|
||||||
|
|
||||||
logger.trace("initializing marvel settings:");
|
logger.trace("initializing marvel settings:");
|
||||||
|
@ -85,4 +88,8 @@ public class MarvelSettingsService extends AbstractComponent implements NodeSett
|
||||||
public String[] indices() {
|
public String[] indices() {
|
||||||
return indices.getValue();
|
return indices.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TimeValue clusterStateTimeout() {
|
||||||
|
return clusterStateTimeout.getValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,31 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"marvel_cluster_state": {
|
||||||
|
"properties": {
|
||||||
|
"cluster_state": {
|
||||||
|
"properties": {
|
||||||
|
"version": {
|
||||||
|
"type": "long"
|
||||||
|
},
|
||||||
|
"master_node": {
|
||||||
|
"type": "string",
|
||||||
|
"index": "not_analyzed"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"type": "string",
|
||||||
|
"index": "not_analyzed"
|
||||||
|
},
|
||||||
|
"nodes": {
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"shards": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* 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.ClusterName;
|
||||||
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.settings.MarvelSettingsService;
|
||||||
|
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
public class ClusterStateCollectorTests extends ElasticsearchSingleNodeTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClusterStateCollectorNoIndices() throws Exception {
|
||||||
|
Collection<MarvelDoc> 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.clusterName(), equalTo(client().admin().cluster().prepareHealth().get().getClusterName()));
|
||||||
|
assertThat(clusterStateMarvelDoc.timestamp(), greaterThan(0L));
|
||||||
|
assertThat(clusterStateMarvelDoc.type(), equalTo(ClusterStateCollector.TYPE));
|
||||||
|
|
||||||
|
ClusterStateMarvelDoc.Payload payload = clusterStateMarvelDoc.payload();
|
||||||
|
assertNotNull(payload);
|
||||||
|
assertNotNull(payload.getClusterState());
|
||||||
|
|
||||||
|
ClusterState clusterState = payload.getClusterState();
|
||||||
|
assertThat(clusterState.getRoutingTable().allShards(), hasSize(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClusterStateCollectorOneIndex() throws Exception {
|
||||||
|
int nbShards = randomIntBetween(1, 5);
|
||||||
|
createIndex("test", Settings.settingsBuilder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, nbShards).build());
|
||||||
|
|
||||||
|
int nbDocs = randomIntBetween(1, 20);
|
||||||
|
for (int i = 0; i < nbDocs; i++) {
|
||||||
|
client().prepareIndex("test", "test").setSource("num", i).get();
|
||||||
|
}
|
||||||
|
client().admin().indices().prepareRefresh().get();
|
||||||
|
assertHitCount(client().prepareCount().get(), nbDocs);
|
||||||
|
|
||||||
|
Collection<MarvelDoc> 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.clusterName(), equalTo(client().admin().cluster().prepareHealth().get().getClusterName()));
|
||||||
|
assertThat(clusterStateMarvelDoc.timestamp(), greaterThan(0L));
|
||||||
|
assertThat(clusterStateMarvelDoc.type(), equalTo(ClusterStateCollector.TYPE));
|
||||||
|
|
||||||
|
ClusterStateMarvelDoc.Payload payload = clusterStateMarvelDoc.payload();
|
||||||
|
assertNotNull(payload);
|
||||||
|
assertNotNull(payload.getClusterState());
|
||||||
|
|
||||||
|
ClusterState clusterState = payload.getClusterState();
|
||||||
|
assertThat(clusterState.getRoutingTable().allShards("test"), hasSize(nbShards));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClusterStateCollectorMultipleIndices() throws Exception {
|
||||||
|
int nbIndices = randomIntBetween(1, 5);
|
||||||
|
int[] docsPerIndex = new int[nbIndices];
|
||||||
|
int[] shardsPerIndex = new int[nbIndices];
|
||||||
|
|
||||||
|
for (int i = 0; i < nbIndices; i++) {
|
||||||
|
shardsPerIndex[i] = randomIntBetween(1, 5);
|
||||||
|
createIndex("test-" + i, Settings.settingsBuilder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, shardsPerIndex[i]).build());
|
||||||
|
|
||||||
|
docsPerIndex[i] = randomIntBetween(1, 20);
|
||||||
|
for (int j = 0; j < docsPerIndex[i]; j++) {
|
||||||
|
client().prepareIndex("test-" + i, "test").setSource("num", i).get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
client().admin().indices().prepareRefresh().get();
|
||||||
|
for (int i = 0; i < nbIndices; i++) {
|
||||||
|
assertHitCount(client().prepareCount("test-" + i).get(), docsPerIndex[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<MarvelDoc> results = newClusterStateCollector().doCollect();
|
||||||
|
MarvelDoc marvelDoc = results.iterator().next();
|
||||||
|
assertNotNull(marvelDoc);
|
||||||
|
assertThat(marvelDoc, instanceOf(ClusterStateMarvelDoc.class));
|
||||||
|
|
||||||
|
ClusterStateMarvelDoc clusterStateMarvelDoc = (ClusterStateMarvelDoc) marvelDoc;
|
||||||
|
assertThat(clusterStateMarvelDoc.clusterName(), equalTo(client().admin().cluster().prepareHealth().get().getClusterName()));
|
||||||
|
assertThat(clusterStateMarvelDoc.timestamp(), greaterThan(0L));
|
||||||
|
assertThat(clusterStateMarvelDoc.type(), equalTo(ClusterStateCollector.TYPE));
|
||||||
|
|
||||||
|
ClusterStateMarvelDoc.Payload payload = clusterStateMarvelDoc.payload();
|
||||||
|
assertNotNull(payload);
|
||||||
|
assertNotNull(payload.getClusterState());
|
||||||
|
|
||||||
|
ClusterState clusterState = payload.getClusterState();
|
||||||
|
for (int i = 0; i < nbIndices; i++) {
|
||||||
|
assertThat(clusterState.getRoutingTable().allShards("test-" + i), hasSize(shardsPerIndex[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClusterStateCollector newClusterStateCollector() {
|
||||||
|
return new ClusterStateCollector(getInstanceFromNode(Settings.class),
|
||||||
|
getInstanceFromNode(ClusterService.class),
|
||||||
|
getInstanceFromNode(ClusterName.class),
|
||||||
|
getInstanceFromNode(MarvelSettingsService.class),
|
||||||
|
client());
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import org.elasticsearch.cluster.ClusterName;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
import org.elasticsearch.marvel.agent.exporter.MarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.settings.MarvelSettingsService;
|
||||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -39,7 +40,10 @@ public class ClusterStatsCollectorTests extends ElasticsearchIntegrationTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClusterStatsCollector newClusterStatsCollector() {
|
private ClusterStatsCollector newClusterStatsCollector() {
|
||||||
return new ClusterStatsCollector(internalCluster().getInstance(Settings.class), internalCluster().getInstance(ClusterService.class),
|
return new ClusterStatsCollector(internalCluster().getInstance(Settings.class),
|
||||||
internalCluster().getInstance(ClusterName.class), client());
|
internalCluster().getInstance(ClusterService.class),
|
||||||
|
internalCluster().getInstance(ClusterName.class),
|
||||||
|
internalCluster().getInstance(MarvelSettingsService.class),
|
||||||
|
client());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,8 @@ public class IndexStatsCollectorTests extends ElasticsearchSingleNodeTest {
|
||||||
return new IndexStatsCollector(getInstanceFromNode(Settings.class),
|
return new IndexStatsCollector(getInstanceFromNode(Settings.class),
|
||||||
getInstanceFromNode(ClusterService.class),
|
getInstanceFromNode(ClusterService.class),
|
||||||
getInstanceFromNode(ClusterName.class),
|
getInstanceFromNode(ClusterName.class),
|
||||||
client(),
|
getInstanceFromNode(MarvelSettingsService.class),
|
||||||
getInstanceFromNode(MarvelSettingsService.class));
|
client());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForNoBlocksOnNode() throws InterruptedException {
|
public void waitForNoBlocksOnNode() throws InterruptedException {
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.cluster.health.ClusterHealthResponse;
|
||||||
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.io.Streams;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.marvel.agent.collector.cluster.ClusterStateMarvelDoc;
|
||||||
|
import org.elasticsearch.marvel.agent.renderer.Renderer;
|
||||||
|
import org.elasticsearch.marvel.agent.renderer.RendererTestUtils;
|
||||||
|
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ClusterStateRendererTests extends ElasticsearchSingleNodeTest {
|
||||||
|
|
||||||
|
private static final String SAMPLE_FILE = "/samples/marvel_cluster_state.json";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testClusterStateRenderer() throws Exception {
|
||||||
|
createIndex("my-index", Settings.settingsBuilder()
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 3)
|
||||||
|
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
logger.debug("--> retrieving cluster state");
|
||||||
|
ClusterState clusterState = getInstanceFromNode(ClusterService.class).state();
|
||||||
|
|
||||||
|
logger.debug("--> retrieving cluster health");
|
||||||
|
ClusterHealthResponse clusterHealth = client().admin().cluster().prepareHealth().get();
|
||||||
|
|
||||||
|
logger.debug("--> creating the cluster state marvel document");
|
||||||
|
ClusterStateMarvelDoc marvelDoc = ClusterStateMarvelDoc.createMarvelDoc("test", "marvel_cluster_state", 1437580442979L,
|
||||||
|
clusterState, clusterHealth.getStatus());
|
||||||
|
|
||||||
|
logger.debug("--> rendering the document");
|
||||||
|
Renderer renderer = new ClusterStateRenderer();
|
||||||
|
String result = RendererTestUtils.renderAsJSON(marvelDoc, renderer);
|
||||||
|
|
||||||
|
logger.debug("--> loading sample document from file {}", SAMPLE_FILE);
|
||||||
|
String expected = Streams.copyToStringFromClasspath(SAMPLE_FILE);
|
||||||
|
|
||||||
|
String nodeId = clusterState.getNodes().getLocalNodeId();
|
||||||
|
logger.debug("--> replace the local node id in sample document with {}", nodeId);
|
||||||
|
expected = Strings.replace(expected, "__node_id__", nodeId);
|
||||||
|
|
||||||
|
logger.debug("--> comparing both documents, they must have the same structure");
|
||||||
|
RendererTestUtils.assertJSONStructure(result, expected);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"cluster_name": "test",
|
||||||
|
"timestamp": "2015-07-22T15:54:02.979Z",
|
||||||
|
"cluster_state": {
|
||||||
|
"status": "yellow",
|
||||||
|
"version": 14,
|
||||||
|
"master_node": "__node_id__",
|
||||||
|
"nodes": {
|
||||||
|
"__node_id__": {
|
||||||
|
"name": "Box",
|
||||||
|
"transport_address": "inet[/127.0.0.1:9300]",
|
||||||
|
"attributes": {
|
||||||
|
"local": "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"shards": [
|
||||||
|
{
|
||||||
|
"state": "STARTED",
|
||||||
|
"primary": true,
|
||||||
|
"node": "__node_id__",
|
||||||
|
"relocating_node": null,
|
||||||
|
"shard": 0,
|
||||||
|
"index": "my-index",
|
||||||
|
"version": 2,
|
||||||
|
"allocation_id": {
|
||||||
|
"id": "p6c9fBsNSc6SBTq0E0jLZw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "STARTED",
|
||||||
|
"primary": true,
|
||||||
|
"node": "__node_id__",
|
||||||
|
"relocating_node": null,
|
||||||
|
"shard": 1,
|
||||||
|
"index": "my-index",
|
||||||
|
"version": 2,
|
||||||
|
"allocation_id": {
|
||||||
|
"id": "KBOkx9UmRNmlZ6LGsnqxJw"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"state": "STARTED",
|
||||||
|
"primary": true,
|
||||||
|
"node": "__node_id__",
|
||||||
|
"relocating_node": null,
|
||||||
|
"shard": 2,
|
||||||
|
"index": "my-index",
|
||||||
|
"version": 2,
|
||||||
|
"allocation_id": {
|
||||||
|
"id": "aHXocqcnRme-y6OJIZX-CQ"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue