Browse Source

Simplify indices stats API

Note: This breaks backward compatibility

* Removed clear/all parameters, now all stats are returned by default
* Made the metrics part of the URL
* Removed a lot of handlers
* Added shards/indices/cluster level paremeter to change response serialization
* Returning translog statistics in IndicesStats
* Added TranslogStats class
* Added IndexShard.translogStats() method to get the stats from concrete implementation
* Updated documentation

Closes #4054
Alexander Reelsen 12 years ago
parent
commit
33878be1e8

+ 6 - 28
docs/reference/indices/stats.asciidoc

@@ -20,8 +20,8 @@ Specific index stats can be retrieved using:
 curl localhost:9200/index1,index2/_stats
 --------------------------------------------------
 
-By default, `docs`, `store`, and `indexing`, `get`, and `search` stats
-are returned, other stats can be enabled as well:
+By default, all stats are returned, returning only specific stats can be
+specified as well in the URI. Those stats can be any of:
 
 [horizontal]
 `docs`:: 		The number of docs / deleted docs (docs not yet merged out).
@@ -45,7 +45,6 @@ are returned, other stats can be enabled as well:
 `flush`:: 		Flush statistics.
 `completion`:: 		Completion suggest statistics.
 `refresh`:: 	Refresh statistics.
-`clear`:: 		Clears all the flags (first).
 
 Some statistics allow per field granularity which accepts a list comma-separated list of included fields. By default all fields are included:
 
@@ -58,14 +57,12 @@ Here are some samples:
 
 [source,js]
 --------------------------------------------------
-# Get back stats for merge and refresh on top of the defaults
-curl 'localhost:9200/_stats?merge=true&refresh=true'
-# Get back stats just for flush
-curl 'localhost:9200/_stats?clear=true&flush=true'
+# Get back stats for merge and refresh only for all indices
+curl 'localhost:9200/_stats/merge,refresh'
 # Get back stats for type1 and type2 documents for the my_index index
-curl 'localhost:9200/my_index/_stats?clear=true&indexing=true&types=type1,type2
+curl 'localhost:9200/my_index/_stats/indexing?types=type1,type2
 # Get back just search stats for group1 and group2
-curl 'localhost:9200/_stats?clear=true&search=true&groups=group1,group2
+curl 'localhost:9200/_stats/search?groups=group1,group2
 --------------------------------------------------
 
 The stats returned are aggregated on the index level, with
@@ -77,22 +74,3 @@ they are created on other nodes. On the other hand, even though a shard
 "left" a node, that node will still retain the stats that shard
 contributed to.
 
-[float]
-=== Specific stats endpoints
-
-Instead of using flags to indicate which stats to return, specific REST
-endpoints can be used, for example:
-
-[source,js]
---------------------------------------------------
-# Merge stats across all indices
-curl localhost:9200/_stats/merge
-# Merge stats for the my_index index
-curl localhost:9200/my_index/_stats/merge
-# Indexing stats for my_index
-curl localhost:9200/my_index/_stats/indexing
-# Indexing stats for my_index for my_type1 and my_type2
-curl localhost:9200/my_index/_stats/indexing/my_type1,my_type2
-# Search stats for group1 and group2
-curl 'localhost:9200/_stats/search/group1,group2
---------------------------------------------------

+ 30 - 0
src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java

@@ -40,6 +40,7 @@ import org.elasticsearch.index.search.stats.SearchStats;
 import org.elasticsearch.index.shard.DocsStats;
 import org.elasticsearch.index.shard.service.IndexShard;
 import org.elasticsearch.index.store.StoreStats;
+import org.elasticsearch.index.translog.TranslogStats;
 import org.elasticsearch.index.warmer.WarmerStats;
 import org.elasticsearch.search.suggest.completion.CompletionStats;
 
@@ -103,6 +104,9 @@ public class CommonStats implements Streamable, ToXContent {
                 case Percolate:
                     percolate = new PercolateStats();
                     break;
+                case Translog:
+                    translog = new TranslogStats();
+                    break;
                 default:
                     throw new IllegalStateException("Unknown Flag: " + flag);
             }
@@ -160,6 +164,9 @@ public class CommonStats implements Streamable, ToXContent {
                 case Percolate:
                     percolate = indexShard.shardPercolateService().stats();
                     break;
+                case Translog:
+                    translog = indexShard.translogStats();
+                    break;
                 default:
                     throw new IllegalStateException("Unknown Flag: " + flag);
             }
@@ -211,6 +218,9 @@ public class CommonStats implements Streamable, ToXContent {
     @Nullable
     public SegmentsStats segments;
 
+    @Nullable
+    public TranslogStats translog;
+
     public void add(CommonStats stats) {
         if (docs == null) {
             if (stats.getDocs() != null) {
@@ -334,6 +344,14 @@ public class CommonStats implements Streamable, ToXContent {
         } else {
             segments.add(stats.getSegments());
         }
+        if (translog == null) {
+            if (stats.getTranslog() != null) {
+                translog = new TranslogStats();
+                translog.add(stats.getTranslog());
+            }
+        } else {
+            translog.add(stats.getTranslog());
+        }
     }
 
     @Nullable
@@ -411,6 +429,9 @@ public class CommonStats implements Streamable, ToXContent {
         return segments;
     }
 
+    @Nullable
+    public TranslogStats getTranslog() { return translog; }
+
     public static CommonStats readCommonStats(StreamInput in) throws IOException {
         CommonStats stats = new CommonStats();
         stats.readFrom(in);
@@ -468,6 +489,9 @@ public class CommonStats implements Streamable, ToXContent {
                 segments = SegmentsStats.readSegmentsStats(in);
             }
         }
+        if (in.getVersion().after(Version.V_1_0_0_Beta2)) {
+            translog = in.readOptionalStreamable(new TranslogStats());
+        }
     }
 
     @Override
@@ -566,6 +590,9 @@ public class CommonStats implements Streamable, ToXContent {
                 segments.writeTo(out);
             }
         }
+        if (out.getVersion().after(Version.V_1_0_0_Beta2)) {
+            out.writeOptionalStreamable(translog);
+        }
     }
 
     // note, requires a wrapping object
@@ -616,6 +643,9 @@ public class CommonStats implements Streamable, ToXContent {
         if (segments != null) {
             segments.toXContent(builder, params);
         }
+        if (translog != null) {
+            translog.toXContent(builder, params);
+        }
         return builder;
     }
 }

+ 3 - 2
src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStatsFlags.java

@@ -34,7 +34,7 @@ public class CommonStatsFlags implements Streamable, Cloneable {
     public final static CommonStatsFlags ALL = new CommonStatsFlags().all();
     public final static CommonStatsFlags NONE = new CommonStatsFlags().clear();
 
-    private EnumSet<Flag> flags = EnumSet.of(Flag.Docs, Flag.Store, Flag.Indexing, Flag.Get, Flag.Search, Flag.Percolate);
+    private EnumSet<Flag> flags = EnumSet.allOf(Flag.class);
     private String[] types = null;
     private String[] groups = null;
     private String[] fieldDataFields = null;
@@ -227,7 +227,8 @@ public class CommonStatsFlags implements Streamable, Cloneable {
         Warmer("warmer"),
         Percolate("percolate"),
         Completion("completion"),
-        Segments("segments");
+        Segments("segments"),
+        Translog("translog");
 
         private final String restName;
 

+ 10 - 2
src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsRequest.java

@@ -29,8 +29,7 @@ import java.io.IOException;
 /**
  * A request to get indices level stats. Allow to enable different stats to be returned.
  * <p/>
- * <p>By default, the {@link #docs(boolean)}, {@link #store(boolean)}, {@link #indexing(boolean)}
- * are enabled. Other stats can be enabled as well.
+ * <p>By default, all statistics are enabled.
  * <p/>
  * <p>All the stats to be returned can be cleared using {@link #clear()}, at which point, specific
  * stats can be enabled.
@@ -239,6 +238,15 @@ public class IndicesStatsRequest extends BroadcastOperationRequest<IndicesStatsR
         return flags.completionDataFields();
     }
 
+    public IndicesStatsRequest translog(boolean translog) {
+        flags.set(Flag.Translog, translog);
+        return this;
+    }
+
+    public boolean translog() {
+        return flags.isSet(Flag.Translog);
+    }
+
     @Override
     public void writeTo(StreamOutput out) throws IOException {
         super.writeTo(out);

+ 5 - 0
src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsRequestBuilder.java

@@ -154,6 +154,11 @@ public class IndicesStatsRequestBuilder extends BroadcastOperationRequestBuilder
         return this;
     }
 
+    public IndicesStatsRequestBuilder setTranslog(boolean translog) {
+        request.translog(translog);
+        return this;
+    }
+
     @Override
     protected void doExecute(ActionListener<IndicesStatsResponse> listener) {
         ((IndicesAdminClient) client).stats(request, listener);

+ 27 - 20
src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsResponse.java

@@ -156,6 +156,12 @@ public class IndicesStatsResponse extends BroadcastOperationResponse implements
 
     @Override
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        String level = params.param("level", "indices");
+        boolean isLevelValid = "indices".equalsIgnoreCase(level) || "shards".equalsIgnoreCase(level) || "cluster".equalsIgnoreCase(level);
+        if (!isLevelValid) {
+            return builder;
+        }
+
         builder.startObject("_all");
 
         builder.startObject("primaries");
@@ -168,35 +174,36 @@ public class IndicesStatsResponse extends BroadcastOperationResponse implements
 
         builder.endObject();
 
-        builder.startObject(Fields.INDICES);
-        for (IndexStats indexStats : getIndices().values()) {
-            builder.startObject(indexStats.getIndex(), XContentBuilder.FieldCaseConversion.NONE);
+        if ("indices".equalsIgnoreCase(level) || "shards".equalsIgnoreCase(level)) {
+            builder.startObject(Fields.INDICES);
+            for (IndexStats indexStats : getIndices().values()) {
+                builder.startObject(indexStats.getIndex(), XContentBuilder.FieldCaseConversion.NONE);
 
-            builder.startObject("primaries");
-            indexStats.getPrimaries().toXContent(builder, params);
-            builder.endObject();
+                builder.startObject("primaries");
+                indexStats.getPrimaries().toXContent(builder, params);
+                builder.endObject();
 
-            builder.startObject("total");
-            indexStats.getTotal().toXContent(builder, params);
-            builder.endObject();
+                builder.startObject("total");
+                indexStats.getTotal().toXContent(builder, params);
+                builder.endObject();
 
-            if ("shards".equalsIgnoreCase(params.param("level", null))) {
-                builder.startObject(Fields.SHARDS);
-                for (IndexShardStats indexShardStats : indexStats) {
-                    builder.startArray(Integer.toString(indexShardStats.getShardId().id()));
-                    for (ShardStats shardStats : indexShardStats) {
-                        builder.startObject();
-                        shardStats.toXContent(builder, params);
-                        builder.endObject();
+                if ("shards".equalsIgnoreCase(level)) {
+                    builder.startObject(Fields.SHARDS);
+                    for (IndexShardStats indexShardStats : indexStats) {
+                        builder.startArray(Integer.toString(indexShardStats.getShardId().id()));
+                        for (ShardStats shardStats : indexShardStats) {
+                            builder.startObject();
+                            shardStats.toXContent(builder, params);
+                            builder.endObject();
+                        }
+                        builder.endArray();
                     }
-                    builder.endArray();
+                    builder.endObject();
                 }
                 builder.endObject();
             }
-
             builder.endObject();
         }
-        builder.endObject();
 
         return builder;
     }

+ 3 - 0
src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java

@@ -190,6 +190,9 @@ public class TransportIndicesStatsAction extends TransportBroadcastOperationActi
             flags.set(CommonStatsFlags.Flag.Completion);
             flags.completionDataFields(request.request.completionFields());
         }
+        if (request.request.translog()) {
+            flags.set(CommonStatsFlags.Flag.Translog);
+        }
 
         return new ShardStats(indexShard, flags);
     }

+ 3 - 0
src/main/java/org/elasticsearch/index/shard/service/IndexShard.java

@@ -20,6 +20,7 @@
 package org.elasticsearch.index.shard.service;
 
 import org.elasticsearch.ElasticSearchException;
+import org.elasticsearch.index.translog.TranslogStats;
 import org.elasticsearch.cluster.routing.ShardRouting;
 import org.elasticsearch.common.Nullable;
 import org.elasticsearch.common.bytes.BytesReference;
@@ -108,6 +109,8 @@ public interface IndexShard extends IndexShardComponent {
 
     CompletionStats completionStats(String... fields);
 
+    TranslogStats translogStats();
+
     PercolatorQueriesRegistry percolateRegistry();
 
     ShardPercolateService shardPercolateService();

+ 6 - 0
src/main/java/org/elasticsearch/index/shard/service/InternalIndexShard.java

@@ -28,6 +28,7 @@ import org.apache.lucene.util.ThreadInterruptedException;
 import org.elasticsearch.ElasticSearchException;
 import org.elasticsearch.ElasticSearchIllegalArgumentException;
 import org.elasticsearch.ElasticSearchIllegalStateException;
+import org.elasticsearch.index.translog.TranslogStats;
 import org.elasticsearch.cluster.routing.ShardRouting;
 import org.elasticsearch.cluster.routing.ShardRoutingState;
 import org.elasticsearch.common.Booleans;
@@ -561,6 +562,11 @@ public class InternalIndexShard extends AbstractIndexShardComponent implements I
         return shardIdCache.stats();
     }
 
+    @Override
+    public TranslogStats translogStats() {
+        return translog.stats();
+    }
+
     @Override
     public CompletionStats completionStats(String... fields) {
         CompletionStats completionStats = new CompletionStats();

+ 5 - 0
src/main/java/org/elasticsearch/index/translog/Translog.java

@@ -130,6 +130,11 @@ public interface Translog extends IndexShardComponent, CloseableIndexComponent {
 
     void syncOnEachOperation(boolean syncOnEachOperation);
 
+    /**
+     * return stats
+     */
+    TranslogStats stats();
+
     static class Location {
         public final long translogId;
         public final long translogLocation;

+ 79 - 0
src/main/java/org/elasticsearch/index/translog/TranslogStats.java

@@ -0,0 +1,79 @@
+/*
+ * Licensed to ElasticSearch and Shay Banon under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. ElasticSearch licenses this
+ * file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.elasticsearch.index.translog;
+
+import org.elasticsearch.common.io.stream.StreamInput;
+import org.elasticsearch.common.io.stream.StreamOutput;
+import org.elasticsearch.common.io.stream.Streamable;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentBuilderString;
+
+import java.io.IOException;
+
+/**
+ *
+ */
+public class TranslogStats implements ToXContent, Streamable {
+
+    private long translogSizeInBytes = 0;
+    private int estimatedNumberOfOperations = 0;
+
+    public TranslogStats() {}
+
+    public TranslogStats(int estimatedNumberOfOperations, long translogSizeInBytes) {
+        this.estimatedNumberOfOperations = estimatedNumberOfOperations;
+        this.translogSizeInBytes = translogSizeInBytes;
+    }
+
+    public void add(TranslogStats translogStats) {
+        if (translogStats == null) {
+            return;
+        }
+
+        this.estimatedNumberOfOperations += translogStats.estimatedNumberOfOperations;
+        this.translogSizeInBytes =+ translogStats.translogSizeInBytes;
+    }
+
+    @Override
+    public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
+        builder.startObject(Fields.TRANSLOG);
+        builder.field(Fields.OPERATIONS, estimatedNumberOfOperations);
+        builder.byteSizeField(Fields.SIZE_IN_BYTES, Fields.SIZE, translogSizeInBytes);
+        builder.endObject();
+        return builder;
+    }
+
+    static final class Fields {
+        static final XContentBuilderString TRANSLOG = new XContentBuilderString("translog");
+        static final XContentBuilderString OPERATIONS = new XContentBuilderString("operations");
+        static final XContentBuilderString SIZE = new XContentBuilderString("size");
+        static final XContentBuilderString SIZE_IN_BYTES = new XContentBuilderString("size_in_bytes");
+    }
+
+    @Override
+    public void readFrom(StreamInput in) throws IOException {
+        estimatedNumberOfOperations = in.readVInt();
+    }
+
+    @Override
+    public void writeTo(StreamOutput out) throws IOException {
+        out.writeVInt(estimatedNumberOfOperations);
+    }
+}

+ 6 - 0
src/main/java/org/elasticsearch/index/translog/fs/FsTranslog.java

@@ -21,6 +21,7 @@ package org.elasticsearch.index.translog.fs;
 
 import jsr166y.ThreadLocalRandom;
 import org.elasticsearch.ElasticSearchException;
+import org.elasticsearch.index.translog.TranslogStats;
 import org.elasticsearch.common.inject.Inject;
 import org.elasticsearch.common.io.FileSystemUtils;
 import org.elasticsearch.common.io.stream.BytesStreamOutput;
@@ -407,4 +408,9 @@ public class FsTranslog extends AbstractIndexShardComponent implements Translog
             type = FsTranslogFile.Type.BUFFERED;
         }
     }
+
+    @Override
+    public TranslogStats stats() {
+        return new TranslogStats(estimatedNumberOfOperations(), translogSizeInBytes());
+    }
 }

+ 40 - 663
src/main/java/org/elasticsearch/rest/action/admin/indices/stats/RestIndicesStatsAction.java

@@ -32,6 +32,7 @@ import org.elasticsearch.rest.*;
 import org.elasticsearch.rest.action.support.RestXContentBuilder;
 
 import java.io.IOException;
+import java.util.Set;
 
 import static org.elasticsearch.rest.RestRequest.Method.GET;
 import static org.elasticsearch.rest.RestStatus.OK;
@@ -45,60 +46,10 @@ public class RestIndicesStatsAction extends BaseRestHandler {
     public RestIndicesStatsAction(Settings settings, Client client, RestController controller) {
         super(settings, client);
         controller.registerHandler(GET, "/_stats", this);
+        controller.registerHandler(GET, "/_stats/{metric}", this);
+        controller.registerHandler(GET, "/_stats/{metric}/{indexMetric}", this);
         controller.registerHandler(GET, "/{index}/_stats", this);
-
-        controller.registerHandler(GET, "_stats/docs", new RestDocsStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/docs", new RestDocsStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/store", new RestStoreStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/store", new RestStoreStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/indexing", new RestIndexingStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/indexing", new RestIndexingStatsHandler());
-        controller.registerHandler(GET, "/_stats/indexing/{indexingTypes1}", new RestIndexingStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/indexing/{indexingTypes2}", new RestIndexingStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/search", new RestSearchStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/search", new RestSearchStatsHandler());
-        controller.registerHandler(GET, "/_stats/search/{searchGroupsStats1}", new RestSearchStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/search/{searchGroupsStats2}", new RestSearchStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/get", new RestGetStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/get", new RestGetStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/refresh", new RestRefreshStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/refresh", new RestRefreshStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/merge", new RestMergeStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/merge", new RestMergeStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/flush", new RestFlushStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/flush", new RestFlushStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/warmer", new RestWarmerStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/warmer", new RestWarmerStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/filter_cache", new RestFilterCacheStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/filter_cache", new RestFilterCacheStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/id_cache", new RestIdCacheStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/id_cache", new RestIdCacheStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/fielddata", new RestFieldDataStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/fielddata", new RestFieldDataStatsHandler());
-        controller.registerHandler(GET, "/_stats/fielddata/{fields}", new RestFieldDataStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/fielddata/{fields}", new RestFieldDataStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/completion", new RestCompletionStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/completion", new RestCompletionStatsHandler());
-        controller.registerHandler(GET, "/_stats/completion/{fields}", new RestCompletionStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/completion/{fields}", new RestCompletionStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/percolate", new RestPercolateStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/percolate", new RestPercolateStatsHandler());
-
-        controller.registerHandler(GET, "/_stats/segments", new RestSegmentsStatsHandler());
-        controller.registerHandler(GET, "/{index}/_stats/segments", new RestSegmentsStatsHandler());
+        controller.registerHandler(GET, "/{index}/_stats/{metric}", this);
     }
 
     @Override
@@ -106,39 +57,47 @@ public class RestIndicesStatsAction extends BaseRestHandler {
         IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
         indicesStatsRequest.listenerThreaded(false);
         indicesStatsRequest.indicesOptions(IndicesOptions.fromRequest(request, indicesStatsRequest.indicesOptions()));
-        boolean clear = request.paramAsBoolean("clear", false);
-        if (clear) {
-            indicesStatsRequest.clear();
-        }
-        boolean all = request.paramAsBoolean("all", false);
-        if (all) {
-            indicesStatsRequest.all();
-        }
         indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
         indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
+
         if (request.hasParam("groups")) {
             indicesStatsRequest.groups(Strings.splitStringByCommaToArray(request.param("groups")));
         }
-        /* We use "fields" as the default field list for stats that support field inclusion filters and further down
-         * a more specific list of fields that overrides this list.*/
-        final String[] defaultIncludedFields = request.paramAsStringArray("fields", null);
-        indicesStatsRequest.docs(request.paramAsBoolean("docs", indicesStatsRequest.docs()));
-        indicesStatsRequest.store(request.paramAsBoolean("store", indicesStatsRequest.store()));
-        indicesStatsRequest.indexing(request.paramAsBoolean("indexing", indicesStatsRequest.indexing()));
-        indicesStatsRequest.search(request.paramAsBoolean("search", indicesStatsRequest.search()));
-        indicesStatsRequest.get(request.paramAsBoolean("get", indicesStatsRequest.get()));
-        indicesStatsRequest.merge(request.paramAsBoolean("merge", indicesStatsRequest.merge()));
-        indicesStatsRequest.refresh(request.paramAsBoolean("refresh", indicesStatsRequest.refresh()));
-        indicesStatsRequest.flush(request.paramAsBoolean("flush", indicesStatsRequest.flush()));
-        indicesStatsRequest.warmer(request.paramAsBoolean("warmer", indicesStatsRequest.warmer()));
-        indicesStatsRequest.filterCache(request.paramAsBoolean("filter_cache", indicesStatsRequest.filterCache()));
-        indicesStatsRequest.idCache(request.paramAsBoolean("id_cache", indicesStatsRequest.idCache()));
-        indicesStatsRequest.fieldData(request.paramAsBoolean("fielddata", indicesStatsRequest.fieldData()));
-        indicesStatsRequest.fieldDataFields(request.paramAsStringArray("fielddata_fields", defaultIncludedFields));
-        indicesStatsRequest.percolate(request.paramAsBoolean("percolate", indicesStatsRequest.percolate()));
-        indicesStatsRequest.segments(request.paramAsBoolean("segments", indicesStatsRequest.segments()));
-        indicesStatsRequest.completion(request.paramAsBoolean("completion", indicesStatsRequest.completion()));
-        indicesStatsRequest.completionFields(request.paramAsStringArray("completion_fields", defaultIncludedFields));
+
+        if (request.hasParam("types")) {
+            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
+        }
+
+        Set<String> metrics = Strings.splitStringByCommaToSet(request.param("metric", "_all"));
+        // short cut, if no metrics have been specified in URI
+        if (metrics.size() == 1 && metrics.contains("_all")) {
+            indicesStatsRequest.all();
+        } else {
+            indicesStatsRequest.clear();
+            indicesStatsRequest.docs(metrics.contains("docs"));
+            indicesStatsRequest.store(metrics.contains("store"));
+            indicesStatsRequest.indexing(metrics.contains("indexing"));
+            indicesStatsRequest.search(metrics.contains("search"));
+            indicesStatsRequest.get(metrics.contains("get"));
+            indicesStatsRequest.merge(metrics.contains("merge"));
+            indicesStatsRequest.refresh(metrics.contains("refresh"));
+            indicesStatsRequest.flush(metrics.contains("flush"));
+            indicesStatsRequest.warmer(metrics.contains("warmer"));
+            indicesStatsRequest.filterCache(metrics.contains("filter_cache"));
+            indicesStatsRequest.idCache(metrics.contains("id_cache"));
+            indicesStatsRequest.percolate(metrics.contains("percolate"));
+            indicesStatsRequest.segments(metrics.contains("segments"));
+            indicesStatsRequest.fieldData(metrics.contains("fielddata"));
+            indicesStatsRequest.completion(metrics.contains("completion"));
+        }
+
+        if (indicesStatsRequest.completion() && (request.hasParam("fields") || request.hasParam("completion_fields"))) {
+            indicesStatsRequest.completionFields(request.paramAsStringArray("completion_fields", request.paramAsStringArray("fields", Strings.EMPTY_ARRAY)));
+        }
+
+        if (indicesStatsRequest.fieldData() && (request.hasParam("fields") || request.hasParam("fielddata_fields"))) {
+            indicesStatsRequest.fieldDataFields(request.paramAsStringArray("fielddata_fields", request.paramAsStringArray("fields", Strings.EMPTY_ARRAY)));
+        }
 
         client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
             @Override
@@ -166,586 +125,4 @@ public class RestIndicesStatsAction extends BaseRestHandler {
             }
         });
     }
-
-    class RestDocsStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().docs(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestStoreStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().store(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestIndexingStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().indexing(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            if (request.hasParam("types")) {
-                indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-            } else if (request.hasParam("indexingTypes1")) {
-                indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("indexingTypes1")));
-            } else if (request.hasParam("indexingTypes2")) {
-                indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("indexingTypes2")));
-            }
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestSearchStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().search(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            if (request.hasParam("groups")) {
-                indicesStatsRequest.groups(Strings.splitStringByCommaToArray(request.param("groups")));
-            } else if (request.hasParam("searchGroupsStats1")) {
-                indicesStatsRequest.groups(Strings.splitStringByCommaToArray(request.param("searchGroupsStats1")));
-            } else if (request.hasParam("searchGroupsStats2")) {
-                indicesStatsRequest.groups(Strings.splitStringByCommaToArray(request.param("searchGroupsStats2")));
-            }
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestGetStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().get(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestMergeStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().merge(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestFlushStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().flush(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestWarmerStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().warmer(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestFilterCacheStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().filterCache(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestIdCacheStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().idCache(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestFieldDataStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().fieldData(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-            indicesStatsRequest.fieldDataFields(request.paramAsStringArray("fields", null));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestCompletionStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().completion(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-            indicesStatsRequest.completionFields(request.paramAsStringArray("fields", null));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestRefreshStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().refresh(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestPercolateStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().percolate(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-            indicesStatsRequest.types(Strings.splitStringByCommaToArray(request.param("types")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
-
-    class RestSegmentsStatsHandler implements RestHandler {
-
-        @Override
-        public void handleRequest(final RestRequest request, final RestChannel channel) {
-            IndicesStatsRequest indicesStatsRequest = new IndicesStatsRequest();
-            indicesStatsRequest.listenerThreaded(false);
-            indicesStatsRequest.clear().segments(true);
-            indicesStatsRequest.indices(Strings.splitStringByCommaToArray(request.param("index")));
-
-            client.admin().indices().stats(indicesStatsRequest, new ActionListener<IndicesStatsResponse>() {
-                @Override
-                public void onResponse(IndicesStatsResponse response) {
-                    try {
-                        XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
-                        builder.startObject();
-                        builder.field("ok", true);
-                        buildBroadcastShardsHeader(builder, response);
-                        response.toXContent(builder, request);
-                        builder.endObject();
-                        channel.sendResponse(new XContentRestResponse(request, OK, builder));
-                    } catch (Throwable e) {
-                        onFailure(e);
-                    }
-                }
-
-                @Override
-                public void onFailure(Throwable e) {
-                    try {
-                        channel.sendResponse(new XContentThrowableRestResponse(request, e));
-                    } catch (IOException e1) {
-                        logger.error("Failed to send failure response", e1);
-                    }
-                }
-            });
-        }
-    }
 }

+ 13 - 12
src/test/java/org/elasticsearch/indices/stats/SimpleIndexStatsTests.java

@@ -69,17 +69,16 @@ public class SimpleIndexStatsTests extends ElasticsearchIntegrationTest {
         assertThat(stats.getPrimaries().getIndexing().getTotal().getIndexCount(), equalTo(3l));
         assertThat(stats.getTotal().getIndexing().getTotal().getIndexCount(), equalTo(6l));
         assertThat(stats.getTotal().getStore(), notNullValue());
-        // verify nulls
-        assertThat(stats.getTotal().getMerge(), nullValue());
-        assertThat(stats.getTotal().getFlush(), nullValue());
-        assertThat(stats.getTotal().getRefresh(), nullValue());
+        assertThat(stats.getTotal().getMerge(), notNullValue());
+        assertThat(stats.getTotal().getFlush(), notNullValue());
+        assertThat(stats.getTotal().getRefresh(), notNullValue());
 
         assertThat(stats.getIndex("test1").getPrimaries().getDocs().getCount(), equalTo(2l));
         assertThat(stats.getIndex("test1").getTotal().getDocs().getCount(), equalTo(4l));
         assertThat(stats.getIndex("test1").getPrimaries().getStore(), notNullValue());
-        assertThat(stats.getIndex("test1").getPrimaries().getMerge(), nullValue());
-        assertThat(stats.getIndex("test1").getPrimaries().getFlush(), nullValue());
-        assertThat(stats.getIndex("test1").getPrimaries().getRefresh(), nullValue());
+        assertThat(stats.getIndex("test1").getPrimaries().getMerge(), notNullValue());
+        assertThat(stats.getIndex("test1").getPrimaries().getFlush(), notNullValue());
+        assertThat(stats.getIndex("test1").getPrimaries().getRefresh(), notNullValue());
 
         assertThat(stats.getIndex("test2").getPrimaries().getDocs().getCount(), equalTo(1l));
         assertThat(stats.getIndex("test2").getTotal().getDocs().getCount(), equalTo(2l));
@@ -91,10 +90,7 @@ public class SimpleIndexStatsTests extends ElasticsearchIntegrationTest {
         assertThat(stats.getIndex("test1").getTotal().getSearch().getTotal().getQueryCurrent(), equalTo(0l));
 
         // check flags
-        stats = client().admin().indices().prepareStats()
-                .setDocs(false)
-                .setStore(false)
-                .setIndexing(false)
+        stats = client().admin().indices().prepareStats().clear()
                 .setFlush(true)
                 .setRefresh(true)
                 .setMerge(true)
@@ -322,7 +318,7 @@ public class SimpleIndexStatsTests extends ElasticsearchIntegrationTest {
     @Test
     public void testFlagOrdinalOrder() {
         Flag[] flags = new Flag[]{Flag.Store, Flag.Indexing, Flag.Get, Flag.Search, Flag.Merge, Flag.Flush, Flag.Refresh,
-                Flag.FilterCache, Flag.IdCache, Flag.FieldData, Flag.Docs, Flag.Warmer, Flag.Percolate, Flag.Completion, Flag.Segments};
+                Flag.FilterCache, Flag.IdCache, Flag.FieldData, Flag.Docs, Flag.Warmer, Flag.Percolate, Flag.Completion, Flag.Segments, Flag.Translog};
 
         assertThat(flags.length, equalTo(Flag.values().length));
         for (int i = 0; i < flags.length; i++) {
@@ -377,6 +373,9 @@ public class SimpleIndexStatsTests extends ElasticsearchIntegrationTest {
             case Segments:
                 builder.setSegments(set);
                 break;
+            case Translog:
+                builder.setTranslog(set);
+                break;
             default:
                 assert false : "new flag? " + flag;
                 break;
@@ -415,6 +414,8 @@ public class SimpleIndexStatsTests extends ElasticsearchIntegrationTest {
                 return response.getCompletion() != null;
             case Segments:
                 return response.getSegments() != null;
+            case Translog:
+                return response.getTranslog() != null;
             default:
                 assert false : "new flag? " + flag;
                 return false;