[HLRC] Added support for Follow Stats API (#36253)
This change also adds documentation for the Follow Stats API. Relates to #33824
This commit is contained in:
parent
633ab24017
commit
f4aac8d3f1
|
@ -23,6 +23,8 @@ import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsResponse;
|
import org.elasticsearch.client.ccr.CcrStatsResponse;
|
||||||
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsResponse;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse;
|
||||||
import org.elasticsearch.client.ccr.PauseFollowRequest;
|
import org.elasticsearch.client.ccr.PauseFollowRequest;
|
||||||
|
@ -385,7 +387,7 @@ public final class CcrClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all CCR stats.
|
* Asynchronously gets all CCR stats.
|
||||||
*
|
*
|
||||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-stats.html">
|
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-stats.html">
|
||||||
* the docs</a> for more.
|
* the docs</a> for more.
|
||||||
|
@ -406,4 +408,48 @@ public final class CcrClient {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets follow stats for specific indices.
|
||||||
|
*
|
||||||
|
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-follow-stats.html">
|
||||||
|
* the docs</a> for more.
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||||
|
* @return the response
|
||||||
|
* @throws IOException in case there is a problem sending the request or parsing back the response
|
||||||
|
*/
|
||||||
|
public FollowStatsResponse getFollowStats(FollowStatsRequest request,
|
||||||
|
RequestOptions options) throws IOException {
|
||||||
|
return restHighLevelClient.performRequestAndParseEntity(
|
||||||
|
request,
|
||||||
|
CcrRequestConverters::getFollowStats,
|
||||||
|
options,
|
||||||
|
FollowStatsResponse::fromXContent,
|
||||||
|
Collections.emptySet()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously gets follow stats for specific indices.
|
||||||
|
*
|
||||||
|
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-follow-stats.html">
|
||||||
|
* the docs</a> for more.
|
||||||
|
*
|
||||||
|
* @param request the request
|
||||||
|
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||||
|
*/
|
||||||
|
public void getFollowStatsAsync(FollowStatsRequest request,
|
||||||
|
RequestOptions options,
|
||||||
|
ActionListener<FollowStatsResponse> listener) {
|
||||||
|
restHighLevelClient.performRequestAsyncAndParseEntity(
|
||||||
|
request,
|
||||||
|
CcrRequestConverters::getFollowStats,
|
||||||
|
options,
|
||||||
|
FollowStatsResponse::fromXContent,
|
||||||
|
listener,
|
||||||
|
Collections.emptySet()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpPut;
|
import org.apache.http.client.methods.HttpPut;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
||||||
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsRequest;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
||||||
import org.elasticsearch.client.ccr.PauseFollowRequest;
|
import org.elasticsearch.client.ccr.PauseFollowRequest;
|
||||||
import org.elasticsearch.client.ccr.PutAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.PutAutoFollowPatternRequest;
|
||||||
|
@ -108,4 +109,12 @@ final class CcrRequestConverters {
|
||||||
return new Request(HttpGet.METHOD_NAME, endpoint);
|
return new Request(HttpGet.METHOD_NAME, endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Request getFollowStats(FollowStatsRequest followStatsRequest) {
|
||||||
|
String endpoint = new RequestConverters.EndpointBuilder()
|
||||||
|
.addPathPart(followStatsRequest.getFollowerIndex())
|
||||||
|
.addPathPartAsIs("_ccr", "stats")
|
||||||
|
.build();
|
||||||
|
return new Request(HttpGet.METHOD_NAME, endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch 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.client.ccr;
|
||||||
|
|
||||||
|
import org.elasticsearch.client.Validatable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public final class FollowStatsRequest implements Validatable {
|
||||||
|
|
||||||
|
private final String followerIndex;
|
||||||
|
|
||||||
|
public FollowStatsRequest(String followerIndex) {
|
||||||
|
this.followerIndex = Objects.requireNonNull(followerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFollowerIndex() {
|
||||||
|
return followerIndex;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch 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.client.ccr;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
|
|
||||||
|
public final class FollowStatsResponse {
|
||||||
|
|
||||||
|
public static FollowStatsResponse fromXContent(XContentParser parser) {
|
||||||
|
return new FollowStatsResponse(IndicesFollowStats.PARSER.apply(parser, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final IndicesFollowStats indicesFollowStats;
|
||||||
|
|
||||||
|
public FollowStatsResponse(IndicesFollowStats indicesFollowStats) {
|
||||||
|
this.indicesFollowStats = indicesFollowStats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndicesFollowStats getIndicesFollowStats() {
|
||||||
|
return indicesFollowStats;
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ import org.elasticsearch.action.support.WriteRequest;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsResponse;
|
import org.elasticsearch.client.ccr.CcrStatsResponse;
|
||||||
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsResponse;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse;
|
||||||
import org.elasticsearch.client.ccr.IndicesFollowStats.ShardFollowStats;
|
import org.elasticsearch.client.ccr.IndicesFollowStats.ShardFollowStats;
|
||||||
|
@ -108,9 +110,10 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
|
||||||
assertThat(leaderSearchResponse.getHits().getTotalHits().value, equalTo(1L));
|
assertThat(leaderSearchResponse.getHits().getTotalHits().value, equalTo(1L));
|
||||||
|
|
||||||
assertBusy(() -> {
|
assertBusy(() -> {
|
||||||
CcrStatsRequest ccrStatsRequest = new CcrStatsRequest();
|
FollowStatsRequest followStatsRequest = new FollowStatsRequest("follower");
|
||||||
CcrStatsResponse ccrStatsResponse = execute(ccrStatsRequest, ccrClient::getCcrStats, ccrClient::getCcrStatsAsync);
|
FollowStatsResponse followStatsResponse =
|
||||||
List<ShardFollowStats> shardFollowStats = ccrStatsResponse.getIndicesFollowStats().getShardFollowStats("follower");
|
execute(followStatsRequest, ccrClient::getFollowStats, ccrClient::getFollowStatsAsync);
|
||||||
|
List<ShardFollowStats> shardFollowStats = followStatsResponse.getIndicesFollowStats().getShardFollowStats("follower");
|
||||||
long followerGlobalCheckpoint = shardFollowStats.stream()
|
long followerGlobalCheckpoint = shardFollowStats.stream()
|
||||||
.mapToLong(ShardFollowStats::getFollowerGlobalCheckpoint)
|
.mapToLong(ShardFollowStats::getFollowerGlobalCheckpoint)
|
||||||
.max()
|
.max()
|
||||||
|
@ -133,9 +136,10 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
|
||||||
assertThat(resumeFollowResponse.isAcknowledged(), is(true));
|
assertThat(resumeFollowResponse.isAcknowledged(), is(true));
|
||||||
|
|
||||||
assertBusy(() -> {
|
assertBusy(() -> {
|
||||||
CcrStatsRequest ccrStatsRequest = new CcrStatsRequest();
|
FollowStatsRequest followStatsRequest = new FollowStatsRequest("follower");
|
||||||
CcrStatsResponse ccrStatsResponse = execute(ccrStatsRequest, ccrClient::getCcrStats, ccrClient::getCcrStatsAsync);
|
FollowStatsResponse followStatsResponse =
|
||||||
List<ShardFollowStats> shardFollowStats = ccrStatsResponse.getIndicesFollowStats().getShardFollowStats("follower");
|
execute(followStatsRequest, ccrClient::getFollowStats, ccrClient::getFollowStatsAsync);
|
||||||
|
List<ShardFollowStats> shardFollowStats = followStatsResponse.getIndicesFollowStats().getShardFollowStats("follower");
|
||||||
long followerGlobalCheckpoint = shardFollowStats.stream()
|
long followerGlobalCheckpoint = shardFollowStats.stream()
|
||||||
.mapToLong(ShardFollowStats::getFollowerGlobalCheckpoint)
|
.mapToLong(ShardFollowStats::getFollowerGlobalCheckpoint)
|
||||||
.max()
|
.max()
|
||||||
|
|
|
@ -323,7 +323,7 @@ public class CcrStatsResponseTests extends ESTestCase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IndicesFollowStats randomIndicesFollowStats() {
|
static IndicesFollowStats randomIndicesFollowStats() {
|
||||||
int numIndices = randomIntBetween(0, 16);
|
int numIndices = randomIntBetween(0, 16);
|
||||||
NavigableMap<String, List<ShardFollowStats>> shardFollowStats = new TreeMap<>();
|
NavigableMap<String, List<ShardFollowStats>> shardFollowStats = new TreeMap<>();
|
||||||
for (int i = 0; i < numIndices; i++) {
|
for (int i = 0; i < numIndices; i++) {
|
||||||
|
|
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch 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.client.ccr;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.client.ccr.IndicesFollowStats.ShardFollowStats;
|
||||||
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
|
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||||
|
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.elasticsearch.client.ccr.CcrStatsResponseTests.randomIndicesFollowStats;
|
||||||
|
import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester;
|
||||||
|
import static org.hamcrest.Matchers.anyOf;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.instanceOf;
|
||||||
|
|
||||||
|
public class FollowStatsResponseTests extends ESTestCase {
|
||||||
|
|
||||||
|
public void testFromXContent() throws IOException {
|
||||||
|
xContentTester(this::createParser,
|
||||||
|
FollowStatsResponseTests::createTestInstance,
|
||||||
|
FollowStatsResponseTests::toXContent,
|
||||||
|
FollowStatsResponse::fromXContent)
|
||||||
|
.supportsUnknownFields(false)
|
||||||
|
.assertEqualsConsumer(FollowStatsResponseTests::assertEqualInstances)
|
||||||
|
.assertToXContentEquivalence(false)
|
||||||
|
.test();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Needed, because exceptions in IndicesFollowStats cannot be compared
|
||||||
|
private static void assertEqualInstances(FollowStatsResponse expectedInstance, FollowStatsResponse newInstance) {
|
||||||
|
assertNotSame(expectedInstance, newInstance);
|
||||||
|
{
|
||||||
|
IndicesFollowStats newIndicesFollowStats = newInstance.getIndicesFollowStats();
|
||||||
|
IndicesFollowStats expectedIndicesFollowStats = expectedInstance.getIndicesFollowStats();
|
||||||
|
assertThat(newIndicesFollowStats.getShardFollowStats().size(),
|
||||||
|
equalTo(expectedIndicesFollowStats.getShardFollowStats().size()));
|
||||||
|
assertThat(newIndicesFollowStats.getShardFollowStats().keySet(),
|
||||||
|
equalTo(expectedIndicesFollowStats.getShardFollowStats().keySet()));
|
||||||
|
for (Map.Entry<String, List<ShardFollowStats>> indexEntry : newIndicesFollowStats.getShardFollowStats().entrySet()) {
|
||||||
|
List<ShardFollowStats> newStats = indexEntry.getValue();
|
||||||
|
List<ShardFollowStats> expectedStats = expectedIndicesFollowStats.getShardFollowStats(indexEntry.getKey());
|
||||||
|
assertThat(newStats.size(), equalTo(expectedStats.size()));
|
||||||
|
for (int i = 0; i < newStats.size(); i++) {
|
||||||
|
ShardFollowStats actualShardFollowStats = newStats.get(i);
|
||||||
|
ShardFollowStats expectedShardFollowStats = expectedStats.get(i);
|
||||||
|
|
||||||
|
assertThat(actualShardFollowStats.getRemoteCluster(), equalTo(expectedShardFollowStats.getRemoteCluster()));
|
||||||
|
assertThat(actualShardFollowStats.getLeaderIndex(), equalTo(expectedShardFollowStats.getLeaderIndex()));
|
||||||
|
assertThat(actualShardFollowStats.getFollowerIndex(), equalTo(expectedShardFollowStats.getFollowerIndex()));
|
||||||
|
assertThat(actualShardFollowStats.getShardId(), equalTo(expectedShardFollowStats.getShardId()));
|
||||||
|
assertThat(actualShardFollowStats.getLeaderGlobalCheckpoint(),
|
||||||
|
equalTo(expectedShardFollowStats.getLeaderGlobalCheckpoint()));
|
||||||
|
assertThat(actualShardFollowStats.getLeaderMaxSeqNo(), equalTo(expectedShardFollowStats.getLeaderMaxSeqNo()));
|
||||||
|
assertThat(actualShardFollowStats.getFollowerGlobalCheckpoint(),
|
||||||
|
equalTo(expectedShardFollowStats.getFollowerGlobalCheckpoint()));
|
||||||
|
assertThat(actualShardFollowStats.getLastRequestedSeqNo(), equalTo(expectedShardFollowStats.getLastRequestedSeqNo()));
|
||||||
|
assertThat(actualShardFollowStats.getOutstandingReadRequests(),
|
||||||
|
equalTo(expectedShardFollowStats.getOutstandingReadRequests()));
|
||||||
|
assertThat(actualShardFollowStats.getOutstandingWriteRequests(),
|
||||||
|
equalTo(expectedShardFollowStats.getOutstandingWriteRequests()));
|
||||||
|
assertThat(actualShardFollowStats.getWriteBufferOperationCount(),
|
||||||
|
equalTo(expectedShardFollowStats.getWriteBufferOperationCount()));
|
||||||
|
assertThat(actualShardFollowStats.getFollowerMappingVersion(),
|
||||||
|
equalTo(expectedShardFollowStats.getFollowerMappingVersion()));
|
||||||
|
assertThat(actualShardFollowStats.getFollowerSettingsVersion(),
|
||||||
|
equalTo(expectedShardFollowStats.getFollowerSettingsVersion()));
|
||||||
|
assertThat(actualShardFollowStats.getTotalReadTimeMillis(),
|
||||||
|
equalTo(expectedShardFollowStats.getTotalReadTimeMillis()));
|
||||||
|
assertThat(actualShardFollowStats.getSuccessfulReadRequests(),
|
||||||
|
equalTo(expectedShardFollowStats.getSuccessfulReadRequests()));
|
||||||
|
assertThat(actualShardFollowStats.getFailedReadRequests(), equalTo(expectedShardFollowStats.getFailedReadRequests()));
|
||||||
|
assertThat(actualShardFollowStats.getOperationsReads(), equalTo(expectedShardFollowStats.getOperationsReads()));
|
||||||
|
assertThat(actualShardFollowStats.getBytesRead(), equalTo(expectedShardFollowStats.getBytesRead()));
|
||||||
|
assertThat(actualShardFollowStats.getTotalWriteTimeMillis(),
|
||||||
|
equalTo(expectedShardFollowStats.getTotalWriteTimeMillis()));
|
||||||
|
assertThat(actualShardFollowStats.getSuccessfulWriteRequests(),
|
||||||
|
equalTo(expectedShardFollowStats.getSuccessfulWriteRequests()));
|
||||||
|
assertThat(actualShardFollowStats.getFailedWriteRequests(),
|
||||||
|
equalTo(expectedShardFollowStats.getFailedWriteRequests()));
|
||||||
|
assertThat(actualShardFollowStats.getOperationWritten(), equalTo(expectedShardFollowStats.getOperationWritten()));
|
||||||
|
assertThat(actualShardFollowStats.getReadExceptions().size(),
|
||||||
|
equalTo(expectedShardFollowStats.getReadExceptions().size()));
|
||||||
|
assertThat(actualShardFollowStats.getReadExceptions().keySet(),
|
||||||
|
equalTo(expectedShardFollowStats.getReadExceptions().keySet()));
|
||||||
|
for (final Map.Entry<Long, Tuple<Integer, ElasticsearchException>> entry :
|
||||||
|
actualShardFollowStats.getReadExceptions().entrySet()) {
|
||||||
|
final Tuple<Integer, ElasticsearchException> expectedTuple =
|
||||||
|
expectedShardFollowStats.getReadExceptions().get(entry.getKey());
|
||||||
|
assertThat(entry.getValue().v1(), equalTo(expectedTuple.v1()));
|
||||||
|
// x-content loses the exception
|
||||||
|
final ElasticsearchException expected = expectedTuple.v2();
|
||||||
|
assertThat(entry.getValue().v2().getMessage(), containsString(expected.getMessage()));
|
||||||
|
assertNotNull(entry.getValue().v2().getCause());
|
||||||
|
assertThat(
|
||||||
|
entry.getValue().v2().getCause(),
|
||||||
|
anyOf(instanceOf(ElasticsearchException.class), instanceOf(IllegalStateException.class)));
|
||||||
|
assertThat(entry.getValue().v2().getCause().getMessage(), containsString(expected.getCause().getMessage()));
|
||||||
|
}
|
||||||
|
assertThat(actualShardFollowStats.getTimeSinceLastReadMillis(),
|
||||||
|
equalTo(expectedShardFollowStats.getTimeSinceLastReadMillis()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void toXContent(FollowStatsResponse response, XContentBuilder builder) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
builder.startArray(IndicesFollowStats.INDICES_FIELD.getPreferredName());
|
||||||
|
for (Map.Entry<String, List<ShardFollowStats>> indexEntry :
|
||||||
|
response.getIndicesFollowStats().getShardFollowStats().entrySet()) {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
builder.field(IndicesFollowStats.INDEX_FIELD.getPreferredName(), indexEntry.getKey());
|
||||||
|
builder.startArray(IndicesFollowStats.SHARDS_FIELD.getPreferredName());
|
||||||
|
{
|
||||||
|
for (ShardFollowStats stats : indexEntry.getValue()) {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
builder.field(ShardFollowStats.LEADER_CLUSTER.getPreferredName(), stats.getRemoteCluster());
|
||||||
|
builder.field(ShardFollowStats.LEADER_INDEX.getPreferredName(), stats.getLeaderIndex());
|
||||||
|
builder.field(ShardFollowStats.FOLLOWER_INDEX.getPreferredName(), stats.getFollowerIndex());
|
||||||
|
builder.field(ShardFollowStats.SHARD_ID.getPreferredName(), stats.getShardId());
|
||||||
|
builder.field(ShardFollowStats.LEADER_GLOBAL_CHECKPOINT_FIELD.getPreferredName(),
|
||||||
|
stats.getLeaderGlobalCheckpoint());
|
||||||
|
builder.field(ShardFollowStats.LEADER_MAX_SEQ_NO_FIELD.getPreferredName(), stats.getLeaderMaxSeqNo());
|
||||||
|
builder.field(ShardFollowStats.FOLLOWER_GLOBAL_CHECKPOINT_FIELD.getPreferredName(),
|
||||||
|
stats.getFollowerGlobalCheckpoint());
|
||||||
|
builder.field(ShardFollowStats.FOLLOWER_MAX_SEQ_NO_FIELD.getPreferredName(),
|
||||||
|
stats.getFollowerMaxSeqNo());
|
||||||
|
builder.field(ShardFollowStats.LAST_REQUESTED_SEQ_NO_FIELD.getPreferredName(),
|
||||||
|
stats.getLastRequestedSeqNo());
|
||||||
|
builder.field(ShardFollowStats.OUTSTANDING_READ_REQUESTS.getPreferredName(),
|
||||||
|
stats.getOutstandingReadRequests());
|
||||||
|
builder.field(ShardFollowStats.OUTSTANDING_WRITE_REQUESTS.getPreferredName(),
|
||||||
|
stats.getOutstandingWriteRequests());
|
||||||
|
builder.field(ShardFollowStats.WRITE_BUFFER_OPERATION_COUNT_FIELD.getPreferredName(),
|
||||||
|
stats.getWriteBufferOperationCount());
|
||||||
|
builder.humanReadableField(
|
||||||
|
ShardFollowStats.WRITE_BUFFER_SIZE_IN_BYTES_FIELD.getPreferredName(),
|
||||||
|
"write_buffer_size",
|
||||||
|
new ByteSizeValue(stats.getWriteBufferSizeInBytes()));
|
||||||
|
builder.field(ShardFollowStats.FOLLOWER_MAPPING_VERSION_FIELD.getPreferredName(),
|
||||||
|
stats.getFollowerMappingVersion());
|
||||||
|
builder.field(ShardFollowStats.FOLLOWER_SETTINGS_VERSION_FIELD.getPreferredName(),
|
||||||
|
stats.getFollowerSettingsVersion());
|
||||||
|
builder.humanReadableField(
|
||||||
|
ShardFollowStats.TOTAL_READ_TIME_MILLIS_FIELD.getPreferredName(),
|
||||||
|
"total_read_time",
|
||||||
|
new TimeValue(stats.getTotalReadTimeMillis(), TimeUnit.MILLISECONDS));
|
||||||
|
builder.humanReadableField(
|
||||||
|
ShardFollowStats.TOTAL_READ_REMOTE_EXEC_TIME_MILLIS_FIELD.getPreferredName(),
|
||||||
|
"total_read_remote_exec_time",
|
||||||
|
new TimeValue(stats.getTotalReadRemoteExecTimeMillis(), TimeUnit.MILLISECONDS));
|
||||||
|
builder.field(ShardFollowStats.SUCCESSFUL_READ_REQUESTS_FIELD.getPreferredName(),
|
||||||
|
stats.getSuccessfulReadRequests());
|
||||||
|
builder.field(ShardFollowStats.FAILED_READ_REQUESTS_FIELD.getPreferredName(),
|
||||||
|
stats.getFailedReadRequests());
|
||||||
|
builder.field(ShardFollowStats.OPERATIONS_READ_FIELD.getPreferredName(), stats.getOperationsReads());
|
||||||
|
builder.humanReadableField(
|
||||||
|
ShardFollowStats.BYTES_READ.getPreferredName(),
|
||||||
|
"total_read",
|
||||||
|
new ByteSizeValue(stats.getBytesRead(), ByteSizeUnit.BYTES));
|
||||||
|
builder.humanReadableField(
|
||||||
|
ShardFollowStats.TOTAL_WRITE_TIME_MILLIS_FIELD.getPreferredName(),
|
||||||
|
"total_write_time",
|
||||||
|
new TimeValue(stats.getTotalWriteTimeMillis(), TimeUnit.MILLISECONDS));
|
||||||
|
builder.field(ShardFollowStats.SUCCESSFUL_WRITE_REQUESTS_FIELD.getPreferredName(),
|
||||||
|
stats.getSuccessfulWriteRequests());
|
||||||
|
builder.field(ShardFollowStats.FAILED_WRITE_REQUEST_FIELD.getPreferredName(),
|
||||||
|
stats.getFailedWriteRequests());
|
||||||
|
builder.field(ShardFollowStats.OPERATIONS_WRITTEN.getPreferredName(), stats.getOperationWritten());
|
||||||
|
builder.startArray(ShardFollowStats.READ_EXCEPTIONS.getPreferredName());
|
||||||
|
{
|
||||||
|
for (final Map.Entry<Long, Tuple<Integer, ElasticsearchException>> entry :
|
||||||
|
stats.getReadExceptions().entrySet()) {
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
builder.field(ShardFollowStats.READ_EXCEPTIONS_ENTRY_FROM_SEQ_NO.getPreferredName(),
|
||||||
|
entry.getKey());
|
||||||
|
builder.field(ShardFollowStats.READ_EXCEPTIONS_RETRIES.getPreferredName(),
|
||||||
|
entry.getValue().v1());
|
||||||
|
builder.field(ShardFollowStats.READ_EXCEPTIONS_ENTRY_EXCEPTION.getPreferredName());
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
ElasticsearchException.generateThrowableXContent(builder, ToXContent.EMPTY_PARAMS,
|
||||||
|
entry.getValue().v2());
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
builder.humanReadableField(
|
||||||
|
ShardFollowStats.TIME_SINCE_LAST_READ_MILLIS_FIELD.getPreferredName(),
|
||||||
|
"time_since_last_read",
|
||||||
|
new TimeValue(stats.getTimeSinceLastReadMillis(), TimeUnit.MILLISECONDS));
|
||||||
|
if (stats.getFatalException() != null) {
|
||||||
|
builder.field(ShardFollowStats.FATAL_EXCEPTION.getPreferredName());
|
||||||
|
builder.startObject();
|
||||||
|
{
|
||||||
|
ElasticsearchException.generateThrowableXContent(builder, ToXContent.EMPTY_PARAMS,
|
||||||
|
stats.getFatalException());
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FollowStatsResponse createTestInstance() {
|
||||||
|
return new FollowStatsResponse(randomIndicesFollowStats());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -37,6 +37,8 @@ import org.elasticsearch.client.ccr.AutoFollowStats;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
import org.elasticsearch.client.ccr.CcrStatsRequest;
|
||||||
import org.elasticsearch.client.ccr.CcrStatsResponse;
|
import org.elasticsearch.client.ccr.CcrStatsResponse;
|
||||||
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsRequest;
|
||||||
|
import org.elasticsearch.client.ccr.FollowStatsResponse;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse;
|
||||||
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse.Pattern;
|
import org.elasticsearch.client.ccr.GetAutoFollowPatternResponse.Pattern;
|
||||||
|
@ -622,6 +624,51 @@ public class CCRDocumentationIT extends ESRestHighLevelClientTestCase {
|
||||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testGetFollowStats() throws Exception {
|
||||||
|
RestHighLevelClient client = highLevelClient();
|
||||||
|
|
||||||
|
// tag::ccr-get-follow-stats-request
|
||||||
|
FollowStatsRequest request =
|
||||||
|
new FollowStatsRequest("follower"); // <1>
|
||||||
|
// end::ccr-get-follow-stats-request
|
||||||
|
|
||||||
|
// tag::ccr-get-follow-stats-execute
|
||||||
|
FollowStatsResponse response = client.ccr()
|
||||||
|
.getFollowStats(request, RequestOptions.DEFAULT);
|
||||||
|
// end::ccr-get-follow-stats-execute
|
||||||
|
|
||||||
|
// tag::ccr-get-follow-stats-response
|
||||||
|
IndicesFollowStats indicesFollowStats =
|
||||||
|
response.getIndicesFollowStats(); // <1>
|
||||||
|
// end::ccr-get-follow-stats-response
|
||||||
|
|
||||||
|
// tag::ccr-get-follow-stats-execute-listener
|
||||||
|
ActionListener<FollowStatsResponse> listener =
|
||||||
|
new ActionListener<FollowStatsResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(FollowStatsResponse response) { // <1>
|
||||||
|
IndicesFollowStats indicesFollowStats =
|
||||||
|
response.getIndicesFollowStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
// <2>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// end::ccr-get-follow-stats-execute-listener
|
||||||
|
|
||||||
|
// Replace the empty listener by a blocking listener in test
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
listener = new LatchedActionListener<>(listener, latch);
|
||||||
|
|
||||||
|
// tag::ccr-get-follow-stats-execute-async
|
||||||
|
client.ccr().getFollowStatsAsync(request,
|
||||||
|
RequestOptions.DEFAULT, listener); // <1>
|
||||||
|
// end::ccr-get-follow-stats-execute-async
|
||||||
|
|
||||||
|
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
|
||||||
static Map<String, Object> toMap(Response response) throws IOException {
|
static Map<String, Object> toMap(Response response) throws IOException {
|
||||||
return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
|
return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
--
|
||||||
|
:api: ccr-get-follow-stats
|
||||||
|
:request: FollowStatsRequest
|
||||||
|
:response: FollowStatsResponse
|
||||||
|
--
|
||||||
|
|
||||||
|
[id="{upid}-{api}"]
|
||||||
|
=== Get Follow Stats API
|
||||||
|
|
||||||
|
|
||||||
|
[id="{upid}-{api}-request"]
|
||||||
|
==== Request
|
||||||
|
|
||||||
|
The Get Follow Stats API allows you to get follow statistics for specific follower indices.
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests-file}[{api}-request]
|
||||||
|
--------------------------------------------------
|
||||||
|
<1> The follower index to get follow statistics for.
|
||||||
|
|
||||||
|
[id="{upid}-{api}-response"]
|
||||||
|
==== Response
|
||||||
|
|
||||||
|
The returned +{response}+ includes follow statistics for the specified follower indices
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests-file}[{api}-response]
|
||||||
|
--------------------------------------------------
|
||||||
|
<1> The follow stats for specified follower indices.
|
||||||
|
|
||||||
|
include::../execution.asciidoc[]
|
||||||
|
|
||||||
|
|
|
@ -486,6 +486,7 @@ The Java High Level REST Client supports the following CCR APIs:
|
||||||
* <<{upid}-ccr-delete-auto-follow-pattern>>
|
* <<{upid}-ccr-delete-auto-follow-pattern>>
|
||||||
* <<{upid}-ccr-get-auto-follow-pattern>>
|
* <<{upid}-ccr-get-auto-follow-pattern>>
|
||||||
* <<{upid}-ccr-get-stats>>
|
* <<{upid}-ccr-get-stats>>
|
||||||
|
* <<{upid}-ccr-get-follow-stats>>
|
||||||
|
|
||||||
include::ccr/put_follow.asciidoc[]
|
include::ccr/put_follow.asciidoc[]
|
||||||
include::ccr/pause_follow.asciidoc[]
|
include::ccr/pause_follow.asciidoc[]
|
||||||
|
@ -495,6 +496,7 @@ include::ccr/put_auto_follow_pattern.asciidoc[]
|
||||||
include::ccr/delete_auto_follow_pattern.asciidoc[]
|
include::ccr/delete_auto_follow_pattern.asciidoc[]
|
||||||
include::ccr/get_auto_follow_pattern.asciidoc[]
|
include::ccr/get_auto_follow_pattern.asciidoc[]
|
||||||
include::ccr/get_stats.asciidoc[]
|
include::ccr/get_stats.asciidoc[]
|
||||||
|
include::ccr/get_follow_stats.asciidoc[]
|
||||||
|
|
||||||
== Index Lifecycle Management APIs
|
== Index Lifecycle Management APIs
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue