From ae3c569beaed7e609b93f595f917e4418963ffe9 Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Thu, 30 Jul 2015 10:30:30 +0200 Subject: [PATCH] Marvel: Add Cluster Stats collector Original commit: elastic/x-pack-elasticsearch@dd96d33a00404bca669d2a2dabf565a71c49cd0a --- .../agent/collector/CollectorModule.java | 2 + .../cluster/ClusterStatsCollector.java | 58 +++++++++++++++++++ .../cluster/ClusterStatsMarvelDoc.java | 41 +++++++++++++ .../marvel/agent/renderer/RendererModule.java | 5 ++ .../cluster/ClusterStatsRenderer.java | 54 +++++++++++++++++ .../main/resources/marvel_index_template.json | 14 +++++ .../samples/marvel_cluster_stats.json | 38 ++++++++++++ 7 files changed, 212 insertions(+) create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java create mode 100644 marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java create mode 100644 marvel/src/test/resources/samples/marvel_cluster_stats.json diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java index 2f092b11203..05f780da2c9 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/CollectorModule.java @@ -7,6 +7,7 @@ package org.elasticsearch.marvel.agent.collector; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.multibindings.Multibinder; +import org.elasticsearch.marvel.agent.collector.cluster.ClusterStatsCollector; import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector; import java.util.HashSet; @@ -19,6 +20,7 @@ public class CollectorModule extends AbstractModule { public CollectorModule() { // Registers default collectors registerCollector(IndexStatsCollector.class); + registerCollector(ClusterStatsCollector.class); } @Override diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java new file mode 100644 index 00000000000..1cf8c60acda --- /dev/null +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsCollector.java @@ -0,0 +1,58 @@ +/* + * 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.stats.ClusterStatsResponse; +import org.elasticsearch.client.Client; +import org.elasticsearch.cluster.ClusterName; +import org.elasticsearch.cluster.ClusterService; +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 java.util.Collection; + +/** + * Collector for cluster stats. + *

+ * This collector runs on the master node only and collects the {@link ClusterStatsMarvelDoc} document + * at a given frequency. + */ +public class ClusterStatsCollector extends AbstractCollector { + + public static final String NAME = "cluster-stats-collector"; + public static final String TYPE = "marvel_cluster_stats"; + + private final ClusterName clusterName; + private final Client client; + + @Inject + public ClusterStatsCollector(Settings settings, ClusterService clusterService, ClusterName clusterName, Client client) { + super(settings, NAME, clusterService); + this.clusterName = clusterName; + this.client = client; + } + + @Override + protected boolean masterOnly() { + return true; + } + + @Override + protected Collection doCollect() throws Exception { + ImmutableList.Builder results = ImmutableList.builder(); + + ClusterStatsResponse clusterStatsResponse = client.admin().cluster().prepareClusterStats().get(); + results.add(buildMarvelDoc(clusterName.value(), TYPE, System.currentTimeMillis(), clusterStatsResponse)); + return results.build(); + } + + protected MarvelDoc buildMarvelDoc(String clusterName, String type, long timestamp, ClusterStatsResponse clusterStatsResponse) { + return ClusterStatsMarvelDoc.createMarvelDoc(clusterName, type, timestamp, clusterStatsResponse); + } +} diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java new file mode 100644 index 00000000000..d068c8b1d49 --- /dev/null +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterStatsMarvelDoc.java @@ -0,0 +1,41 @@ +/* + * 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.stats.ClusterStatsResponse; +import org.elasticsearch.marvel.agent.exporter.MarvelDoc; + +public class ClusterStatsMarvelDoc extends MarvelDoc { + + private final Payload payload; + + public ClusterStatsMarvelDoc(String clusterName, String type, long timestamp, Payload payload) { + super(clusterName, type, timestamp); + this.payload = payload; + } + + @Override + public ClusterStatsMarvelDoc.Payload payload() { + return payload; + } + + public static ClusterStatsMarvelDoc createMarvelDoc(String clusterName, String type, long timestamp, ClusterStatsResponse clusterStats) { + return new ClusterStatsMarvelDoc(clusterName, type, timestamp, new Payload(clusterStats)); + } + + public static class Payload { + + private final ClusterStatsResponse clusterStats; + + Payload(ClusterStatsResponse clusterStats) { + this.clusterStats = clusterStats; + } + + public ClusterStatsResponse getClusterStats() { + return clusterStats; + } + } +} 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 fbc070ee5d1..8505bd05f7e 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 @@ -7,7 +7,9 @@ package org.elasticsearch.marvel.agent.renderer; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.multibindings.MapBinder; +import org.elasticsearch.marvel.agent.collector.cluster.ClusterStatsCollector; import org.elasticsearch.marvel.agent.collector.indices.IndexStatsCollector; +import org.elasticsearch.marvel.agent.renderer.cluster.ClusterStatsRenderer; import org.elasticsearch.marvel.agent.renderer.indices.IndexStatsRenderer; import java.util.HashMap; @@ -29,6 +31,9 @@ public class RendererModule extends AbstractModule { bind(IndexStatsRenderer.class).asEagerSingleton(); mbinder.addBinding(IndexStatsCollector.TYPE).to(IndexStatsRenderer.class); + bind(ClusterStatsRenderer.class).asEagerSingleton(); + mbinder.addBinding(ClusterStatsCollector.TYPE).to(ClusterStatsRenderer.class); + for (Map.Entry> entry : renderers.entrySet()) { bind(entry.getValue()).asEagerSingleton(); mbinder.addBinding(entry.getKey()).to(entry.getValue()); diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java new file mode 100644 index 00000000000..026506312e7 --- /dev/null +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterStatsRenderer.java @@ -0,0 +1,54 @@ +/* + * 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.stats.ClusterStatsResponse; +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.ClusterStatsMarvelDoc; +import org.elasticsearch.marvel.agent.renderer.AbstractRenderer; + +import java.io.IOException; + +public class ClusterStatsRenderer extends AbstractRenderer { + + private static final String[] FILTERS = { + "cluster_stats.nodes.count.total", + "cluster_stats.indices.shards.total", + "cluster_stats.indices.shards.index.replication.min", + "cluster_stats.indices.docs.count", + "cluster_stats.indices.store.size_in_bytes", + "cluster_stats.nodes.fs.total_in_bytes", + "cluster_stats.nodes.fs.free_in_bytes", + "cluster_stats.nodes.fs.available_in_bytes", + "cluster_stats.nodes.jvm.max_uptime_in_millis", + "cluster_stats.nodes.versions", + }; + + public ClusterStatsRenderer() { + super(FILTERS, true); + } + + @Override + protected void doRender(ClusterStatsMarvelDoc marvelDoc, XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.startObject(Fields.CLUSTER_STATS); + + ClusterStatsMarvelDoc.Payload payload = marvelDoc.payload(); + if (payload != null) { + ClusterStatsResponse clusterStats = payload.getClusterStats(); + if (clusterStats != null) { + clusterStats.toXContent(builder, params); + } + } + + builder.endObject(); + } + + static final class Fields { + static final XContentBuilderString CLUSTER_STATS = new XContentBuilderString("cluster_stats"); + } +} diff --git a/marvel/src/main/resources/marvel_index_template.json b/marvel/src/main/resources/marvel_index_template.json index 2e6c160d78a..472f5a13340 100644 --- a/marvel/src/main/resources/marvel_index_template.json +++ b/marvel/src/main/resources/marvel_index_template.json @@ -64,6 +64,20 @@ } } } + }, + "marvel_cluster_stats": { + "properties": { + "cluster_stats": { + "properties": { + "nodes": { + "type": "object" + }, + "indices": { + "type": "object" + } + } + } + } } } } \ No newline at end of file diff --git a/marvel/src/test/resources/samples/marvel_cluster_stats.json b/marvel/src/test/resources/samples/marvel_cluster_stats.json new file mode 100644 index 00000000000..e8241d95bab --- /dev/null +++ b/marvel/src/test/resources/samples/marvel_cluster_stats.json @@ -0,0 +1,38 @@ +{ + "cluster_name": "test", + "timestamp": "2015-07-22T15:54:02.979Z", + "cluster_stats": { + "indices": { + "shards": { + "total": 1, + "index": { + "replication": { + "min": 0.0 + } + } + }, + "docs": { + "count": 12 + }, + "store": { + "size_in_bytes": 57214 + } + }, + "nodes": { + "count": { + "total": 1 + }, + "versions": [ + "2.0.0-beta1-SNAPSHOT" + ], + "jvm": { + "max_uptime_in_millis": 75191 + }, + "fs": { + "total_in_bytes": 486599139328, + "free_in_bytes": 229533143040, + "available_in_bytes": 204791681024 + } + } + } +}