From d92b2e0c98ce20b4b2f15c0024326af11db16fac Mon Sep 17 00:00:00 2001 From: weizijun Date: Mon, 23 Mar 2020 21:27:13 +0800 Subject: [PATCH] /_cat/shards support path stats (#53461) * _cat/shards support path stats * fix some style case * fix some style case * fix rest-api-spec cat.shards error * fix rest-api-spec cat.shards bwc error Co-authored-by: Elastic Machine --- .../test/cat.shards/10_basic.yml | 6 +- .../rest/action/cat/RestShardsAction.java | 9 +- .../action/cat/RestShardsActionTests.java | 121 ++++++++++++++++++ 3 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 server/src/test/java/org/elasticsearch/rest/action/cat/RestShardsActionTests.java diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml index de5e632975752..aa4abc7a11eae 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/cat.shards/10_basic.yml @@ -1,8 +1,8 @@ --- "Help": - skip: - version: " - 7.1.99" - reason: external refresh stats were added in 7.2.0 + version: " - 7.99.99" + reason: shard path stats were added in 8.0.0 - do: cat.shards: help: true @@ -78,6 +78,8 @@ warmer.current .+ \n warmer.total .+ \n warmer.total_time .+ \n + path.data .+ \n + path.state .+ \n $/ --- "Test cat shards output": diff --git a/server/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java b/server/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java index 9a321476efda7..b0002f5777744 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java +++ b/server/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java @@ -202,6 +202,9 @@ protected Table getTableWithHeader(final RestRequest request) { table.addCell("warmer.total", "alias:wto,warmerTotal;default:false;text-align:right;desc:total warmer ops"); table.addCell("warmer.total_time", "alias:wtt,warmerTotalTime;default:false;text-align:right;desc:time spent in warmers"); + table.addCell("path.data", "alias:pd,dataPath;default:false;text-align:right;desc:shard data path"); + table.addCell("path.state", "alias:ps,statsPath;default:false;text-align:right;desc:shard state path"); + table.endHeaders(); return table; } @@ -216,7 +219,8 @@ private static Object getOrNull(S stats, Function accessor, Functio return null; } - private Table buildTable(RestRequest request, ClusterStateResponse state, IndicesStatsResponse stats) { + // package private for testing + Table buildTable(RestRequest request, ClusterStateResponse state, IndicesStatsResponse stats) { Table table = getTableWithHeader(request); for (ShardRouting shard : state.getState().routingTable().allShards()) { @@ -353,6 +357,9 @@ private Table buildTable(RestRequest request, ClusterStateResponse state, Indice table.addCell(getOrNull(commonStats, CommonStats::getWarmer, WarmerStats::total)); table.addCell(getOrNull(commonStats, CommonStats::getWarmer, WarmerStats::totalTime)); + table.addCell(getOrNull(shardStats, ShardStats::getDataPath, s -> s)); + table.addCell(getOrNull(shardStats, ShardStats::getStatePath, s -> s)); + table.endRow(); } diff --git a/server/src/test/java/org/elasticsearch/rest/action/cat/RestShardsActionTests.java b/server/src/test/java/org/elasticsearch/rest/action/cat/RestShardsActionTests.java new file mode 100644 index 0000000000000..f661521376cf5 --- /dev/null +++ b/server/src/test/java/org/elasticsearch/rest/action/cat/RestShardsActionTests.java @@ -0,0 +1,121 @@ +/* + * 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.rest.action.cat; + +import org.elasticsearch.Version; +import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse; +import org.elasticsearch.action.admin.indices.stats.CommonStats; +import org.elasticsearch.action.admin.indices.stats.IndexStats; +import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; +import org.elasticsearch.action.admin.indices.stats.ShardStats; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.routing.RoutingTable; +import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.routing.ShardRoutingState; +import org.elasticsearch.cluster.routing.TestShardRouting; +import org.elasticsearch.common.Table; +import org.elasticsearch.index.shard.ShardPath; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.test.rest.FakeRestRequest; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class RestShardsActionTests extends ESTestCase { + + public void testBuildTable() { + final int numShards = randomIntBetween(1, 5); + DiscoveryNode localNode = new DiscoveryNode("local", buildNewFakeTransportAddress(), Version.CURRENT); + + List shardRoutings = new ArrayList<>(numShards); + Map shardStatsMap = new HashMap<>(); + String index = "index"; + for (int i = 0; i < numShards; i++) { + ShardRoutingState shardRoutingState = ShardRoutingState.fromValue((byte) randomIntBetween(2, 3)); + ShardRouting shardRouting = TestShardRouting.newShardRouting(index, i, localNode.getId(), randomBoolean(), shardRoutingState); + Path path = createTempDir().resolve("indices").resolve(shardRouting.shardId().getIndex().getUUID()) + .resolve(String.valueOf(shardRouting.shardId().id())); + ShardStats shardStats = new ShardStats(shardRouting, new ShardPath(false, path, path, shardRouting.shardId()), + null, null, null, null); + shardStatsMap.put(shardRouting, shardStats); + shardRoutings.add(shardRouting); + } + + IndexStats indexStats = mock(IndexStats.class); + when(indexStats.getPrimaries()).thenReturn(new CommonStats()); + when(indexStats.getTotal()).thenReturn(new CommonStats()); + + IndicesStatsResponse stats = mock(IndicesStatsResponse.class); + when(stats.asMap()).thenReturn(shardStatsMap); + + DiscoveryNodes discoveryNodes = mock(DiscoveryNodes.class); + when(discoveryNodes.get(localNode.getId())).thenReturn(localNode); + + ClusterStateResponse state = mock(ClusterStateResponse.class); + RoutingTable routingTable = mock(RoutingTable.class); + when(routingTable.allShards()).thenReturn(shardRoutings); + ClusterState clusterState = mock(ClusterState.class); + when(clusterState.routingTable()).thenReturn(routingTable); + when(clusterState.nodes()).thenReturn(discoveryNodes); + when(state.getState()).thenReturn(clusterState); + + final RestShardsAction action = new RestShardsAction(); + final Table table = action.buildTable(new FakeRestRequest(), state, stats); + + // now, verify the table is correct + List headers = table.getHeaders(); + assertThat(headers.get(0).value, equalTo("index")); + assertThat(headers.get(1).value, equalTo("shard")); + assertThat(headers.get(2).value, equalTo("prirep")); + assertThat(headers.get(3).value, equalTo("state")); + assertThat(headers.get(4).value, equalTo("docs")); + assertThat(headers.get(5).value, equalTo("store")); + assertThat(headers.get(6).value, equalTo("ip")); + assertThat(headers.get(7).value, equalTo("id")); + assertThat(headers.get(8).value, equalTo("node")); + + final List> rows = table.getRows(); + assertThat(rows.size(), equalTo(numShards)); + + Iterator shardRoutingsIt = shardRoutings.iterator(); + for (final List row : rows) { + ShardRouting shardRouting = shardRoutingsIt.next(); + ShardStats shardStats = shardStatsMap.get(shardRouting); + assertThat(row.get(0).value, equalTo(shardRouting.getIndexName())); + assertThat(row.get(1).value, equalTo(shardRouting.getId())); + assertThat(row.get(2).value, equalTo(shardRouting.primary() ? "p" : "r")); + assertThat(row.get(3).value, equalTo(shardRouting.state())); + assertThat(row.get(6).value, equalTo(localNode.getHostAddress())); + assertThat(row.get(7).value, equalTo(localNode.getId())); + assertThat(row.get(69).value, equalTo(shardStats.getDataPath())); + assertThat(row.get(70).value, equalTo(shardStats.getStatePath())); + } + } +}