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
This commit is contained in:
Alexander Reelsen 2013-12-11 12:09:59 +01:00
parent 3024cc24a6
commit 33878be1e8
14 changed files with 236 additions and 727 deletions

View File

@ -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
--------------------------------------------------

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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,6 +174,7 @@ public class IndicesStatsResponse extends BroadcastOperationResponse implements
builder.endObject();
if ("indices".equalsIgnoreCase(level) || "shards".equalsIgnoreCase(level)) {
builder.startObject(Fields.INDICES);
for (IndexStats indexStats : getIndices().values()) {
builder.startObject(indexStats.getIndex(), XContentBuilder.FieldCaseConversion.NONE);
@ -180,7 +187,7 @@ public class IndicesStatsResponse extends BroadcastOperationResponse implements
indexStats.getTotal().toXContent(builder, params);
builder.endObject();
if ("shards".equalsIgnoreCase(params.param("level", null))) {
if ("shards".equalsIgnoreCase(level)) {
builder.startObject(Fields.SHARDS);
for (IndexShardStats indexShardStats : indexStats) {
builder.startArray(Integer.toString(indexShardStats.getShardId().id()));
@ -193,10 +200,10 @@ public class IndicesStatsResponse extends BroadcastOperationResponse implements
}
builder.endObject();
}
builder.endObject();
}
builder.endObject();
}
return builder;
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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();

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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,157 +57,46 @@ 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));
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 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")));
}
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>() {
@ -286,466 +126,3 @@ public class RestIndicesStatsAction extends BaseRestHandler {
});
}
}
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);
}
}
});
}
}
}

View File

@ -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;