diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java index 88fe0e3407130..9086b440ac285 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java @@ -26,6 +26,7 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.flush.FlushStats; +import org.elasticsearch.index.get.GetStats; import org.elasticsearch.index.indexing.IndexingStats; import org.elasticsearch.index.merge.MergeStats; import org.elasticsearch.index.refresh.RefreshStats; @@ -44,6 +45,8 @@ public class CommonStats implements Streamable, ToXContent { @Nullable IndexingStats indexing; + @Nullable GetStats get; + @Nullable MergeStats merge; @Nullable RefreshStats refresh; @@ -75,6 +78,14 @@ public void add(CommonStats stats) { } else { indexing.add(stats.indexing()); } + if (get == null) { + if (stats.get() != null) { + get = new GetStats(); + get.add(stats.get()); + } + } else { + get.add(stats.get()); + } if (merge == null) { if (stats.merge() != null) { merge = new MergeStats(); @@ -125,6 +136,14 @@ public void add(CommonStats stats) { return indexing; } + @Nullable public GetStats get() { + return get; + } + + @Nullable public GetStats getGet() { + return get; + } + @Nullable public MergeStats merge() { return merge; } @@ -165,6 +184,9 @@ public static CommonStats readCommonStats(StreamInput in) throws IOException { if (in.readBoolean()) { indexing = IndexingStats.readIndexingStats(in); } + if (in.readBoolean()) { + get = GetStats.readGetStats(in); + } if (in.readBoolean()) { merge = MergeStats.readMergeStats(in); } @@ -195,6 +217,12 @@ public static CommonStats readCommonStats(StreamInput in) throws IOException { out.writeBoolean(true); indexing.writeTo(out); } + if (get == null) { + out.writeBoolean(false); + } else { + out.writeBoolean(true); + get.writeTo(out); + } if (merge == null) { out.writeBoolean(false); } else { @@ -226,6 +254,9 @@ public static CommonStats readCommonStats(StreamInput in) throws IOException { if (indexing != null) { indexing.toXContent(builder, params); } + if (get != null) { + get.toXContent(builder, params); + } if (merge != null) { merge.toXContent(builder, params); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsRequest.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsRequest.java index 4019bc1c532a7..43e1b3b05c69a 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsRequest.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/IndicesStatsRequest.java @@ -39,6 +39,7 @@ public class IndicesStatsRequest extends BroadcastOperationRequest { private boolean docs = true; private boolean store = true; private boolean indexing = true; + private boolean get = true; private boolean merge = false; private boolean refresh = false; private boolean flush = false; @@ -55,6 +56,7 @@ public IndicesStatsRequest indices(String... indices) { public IndicesStatsRequest clear() { docs = false; store = false; + get = false; indexing = false; merge = false; refresh = false; @@ -106,6 +108,15 @@ public boolean indexing() { return this.indexing; } + public IndicesStatsRequest get(boolean get) { + this.get = get; + return this; + } + + public boolean get() { + return this.get; + } + public IndicesStatsRequest merge(boolean merge) { this.merge = merge; return this; @@ -138,6 +149,7 @@ public boolean flush() { out.writeBoolean(docs); out.writeBoolean(store); out.writeBoolean(indexing); + out.writeBoolean(get); out.writeBoolean(merge); out.writeBoolean(flush); out.writeBoolean(refresh); @@ -156,6 +168,7 @@ public boolean flush() { docs = in.readBoolean(); store = in.readBoolean(); indexing = in.readBoolean(); + get = in.readBoolean(); merge = in.readBoolean(); flush = in.readBoolean(); refresh = in.readBoolean(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java index 39335edf68aff..efa31c8554f0e 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java @@ -135,6 +135,9 @@ public class TransportIndicesStatsAction extends TransportBroadcastOperationActi if (request.request.indexing()) { stats.stats.indexing = indexShard.indexingStats(request.request.types()); } + if (request.request.get()) { + stats.stats.get = indexShard.getStats(); + } if (request.request.merge()) { stats.stats.merge = indexShard.mergeStats(); } diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/GetStats.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/GetStats.java new file mode 100644 index 0000000000000..f792c121d51a6 --- /dev/null +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/GetStats.java @@ -0,0 +1,180 @@ +/* + * Licensed to Elastic Search and Shay Banon under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Elastic Search 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.get; + +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.unit.TimeValue; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentBuilderString; + +import java.io.IOException; + +/** + */ +public class GetStats implements Streamable, ToXContent { + + private long existsCount; + private long existsTimeInMillis; + private long missingCount; + private long missingTimeInMillis; + + public GetStats() { + } + + public GetStats(long existsCount, long existsTimeInMillis, long missingCount, long missingTimeInMillis) { + this.existsCount = existsCount; + this.existsTimeInMillis = existsTimeInMillis; + this.missingCount = missingCount; + this.missingTimeInMillis = missingTimeInMillis; + } + + public void add(GetStats stats) { + if (stats == null) { + return; + } + existsCount += stats.existsCount; + existsTimeInMillis += stats.existsTimeInMillis; + missingCount += stats.missingCount; + missingTimeInMillis += stats.missingTimeInMillis; + } + + public long count() { + return existsCount + missingCount; + } + + public long getCount() { + return count(); + } + + public long timeInMillis() { + return existsTimeInMillis + missingTimeInMillis; + } + + public long getTimeInMillis() { + return timeInMillis(); + } + + public TimeValue time() { + return new TimeValue(timeInMillis()); + } + + public TimeValue getTime() { + return time(); + } + + public long existsCount() { + return this.existsCount; + } + + public long getExistsCount() { + return this.existsCount; + } + + public long existsTimeInMillis() { + return this.existsTimeInMillis; + } + + public long getExistsTimeInMillis() { + return this.existsTimeInMillis; + } + + public TimeValue existsTime() { + return new TimeValue(existsTimeInMillis); + } + + public TimeValue getExistsTime() { + return existsTime(); + } + + public long missingCount() { + return this.missingCount; + } + + public long getMissingCount() { + return this.missingCount; + } + + public long missingTimeInMillis() { + return this.missingTimeInMillis; + } + + public long getMissingTimeInMillis() { + return this.missingTimeInMillis; + } + + public TimeValue missingTime() { + return new TimeValue(missingTimeInMillis); + } + + public TimeValue getMissingTime() { + return missingTime(); + } + + @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(Fields.GET); + builder.field(Fields.TOTAL, count()); + builder.field(Fields.TIME, time().toString()); + builder.field(Fields.TIME_IN_MILLIS, timeInMillis()); + builder.field(Fields.EXISTS_TOTAL, existsCount); + builder.field(Fields.EXISTS_TIME, existsTime().toString()); + builder.field(Fields.EXISTS_TIME_IN_MILLIS, existsTimeInMillis); + builder.field(Fields.MISSING_TOTAL, missingCount); + builder.field(Fields.MISSING_TIME, missingTime().toString()); + builder.field(Fields.MISSING_TIME_IN_MILLIS, missingTimeInMillis); + builder.endObject(); + return builder; + } + + static final class Fields { + static final XContentBuilderString GET = new XContentBuilderString("get"); + static final XContentBuilderString TOTAL = new XContentBuilderString("total"); + static final XContentBuilderString TIME = new XContentBuilderString("time"); + static final XContentBuilderString TIME_IN_MILLIS = new XContentBuilderString("time_in_millis"); + static final XContentBuilderString EXISTS_TOTAL = new XContentBuilderString("exists_total"); + static final XContentBuilderString EXISTS_TIME = new XContentBuilderString("exists_time"); + static final XContentBuilderString EXISTS_TIME_IN_MILLIS = new XContentBuilderString("exists_time_in_millis"); + static final XContentBuilderString MISSING_TOTAL = new XContentBuilderString("missing_total"); + static final XContentBuilderString MISSING_TIME = new XContentBuilderString("missing_time"); + static final XContentBuilderString MISSING_TIME_IN_MILLIS = new XContentBuilderString("missing_time_in_millis"); + } + + public static GetStats readGetStats(StreamInput in) throws IOException { + GetStats stats = new GetStats(); + stats.readFrom(in); + return stats; + } + + @Override public void readFrom(StreamInput in) throws IOException { + existsCount = in.readVLong(); + existsTimeInMillis = in.readVLong(); + missingCount = in.readVLong(); + missingTimeInMillis = in.readVLong(); + } + + @Override public void writeTo(StreamOutput out) throws IOException { + out.writeVLong(existsCount); + out.writeVLong(existsTimeInMillis); + out.writeVLong(missingCount); + out.writeVLong(missingTimeInMillis); + } +} diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/ShardGetService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/ShardGetService.java index 795a9d8ae8322..871da35b37643 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/ShardGetService.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/get/ShardGetService.java @@ -26,6 +26,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.lucene.document.ResetFieldSelector; import org.elasticsearch.common.lucene.uid.UidField; +import org.elasticsearch.common.metrics.MeanMetric; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.cache.IndexCache; import org.elasticsearch.index.engine.Engine; @@ -63,6 +64,9 @@ public class ShardGetService extends AbstractIndexShardComponent { private IndexShard indexShard; + private final MeanMetric existsMetric = new MeanMetric(); + private final MeanMetric missingMetric = new MeanMetric(); + @Inject public ShardGetService(ShardId shardId, @IndexSettings Settings indexSettings, ScriptService scriptService, MapperService mapperService, IndexCache indexCache) { super(shardId, indexSettings); @@ -71,6 +75,10 @@ public class ShardGetService extends AbstractIndexShardComponent { this.indexCache = indexCache; } + public GetStats stats() { + return new GetStats(existsMetric.count(), existsMetric.sum(), missingMetric.count(), missingMetric.sum()); + } + // sadly, to overcome cyclic dep, we need to do this and inject it ourselves... public ShardGetService setIndexShard(IndexShard indexShard) { this.indexShard = indexShard; @@ -78,6 +86,17 @@ public ShardGetService setIndexShard(IndexShard indexShard) { } public GetResult get(String type, String id, String[] gFields, boolean realtime) throws ElasticSearchException { + long now = System.nanoTime(); + GetResult getResult = innerGet(type, id, gFields, realtime); + if (getResult.exists()) { + existsMetric.inc(System.nanoTime() - now); + } else { + missingMetric.inc(System.nanoTime() - now); + } + return getResult; + } + + public GetResult innerGet(String type, String id, String[] gFields, boolean realtime) throws ElasticSearchException { boolean loadSource = gFields == null || gFields.length > 0; Engine.GetResult get = null; if (type == null || type.equals("_all")) { diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/IndexShard.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/IndexShard.java index 04a59a7d6938f..766e435f36d41 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/IndexShard.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/IndexShard.java @@ -26,6 +26,7 @@ import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.engine.EngineException; import org.elasticsearch.index.flush.FlushStats; +import org.elasticsearch.index.get.GetStats; import org.elasticsearch.index.get.ShardGetService; import org.elasticsearch.index.indexing.IndexingStats; import org.elasticsearch.index.indexing.ShardIndexingService; @@ -56,6 +57,8 @@ public interface IndexShard extends IndexShardComponent { IndexingStats indexingStats(String... types); + GetStats getStats(); + MergeStats mergeStats(); RefreshStats refreshStats(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/InternalIndexShard.java b/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/InternalIndexShard.java index b98101ccb4b63..c861ee58eea00 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/InternalIndexShard.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/index/shard/service/InternalIndexShard.java @@ -47,6 +47,7 @@ import org.elasticsearch.index.engine.OptimizeFailedEngineException; import org.elasticsearch.index.engine.RefreshFailedEngineException; import org.elasticsearch.index.flush.FlushStats; +import org.elasticsearch.index.get.GetStats; import org.elasticsearch.index.get.ShardGetService; import org.elasticsearch.index.indexing.IndexingStats; import org.elasticsearch.index.indexing.ShardIndexingService; @@ -412,6 +413,10 @@ public InternalIndexShard start(String reason) throws IndexShardStartedException return indexingService.stats(types); } + @Override public GetStats getStats() { + return getService.stats(); + } + @Override public StoreStats storeStats() { try { return store.stats(); diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/indices/InternalIndicesService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/indices/InternalIndicesService.java index 6827147665519..5662712041f49 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/indices/InternalIndicesService.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/indices/InternalIndicesService.java @@ -54,6 +54,7 @@ import org.elasticsearch.index.flush.FlushStats; import org.elasticsearch.index.gateway.IndexGateway; import org.elasticsearch.index.gateway.IndexGatewayModule; +import org.elasticsearch.index.get.GetStats; import org.elasticsearch.index.indexing.IndexingStats; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperServiceModule; @@ -178,12 +179,14 @@ public class InternalIndicesService extends AbstractLifecycleComponent