Skip to content

Commit a8a21d8

Browse files
authored
Report shard count per node in _nodes/stats (#75760)
Backporting _nodes/stats feature This commit cherry-picks the commit from #75433, and changes it to apply to 7.15 and later.
1 parent cea22d6 commit a8a21d8

File tree

8 files changed

+246
-5
lines changed

8 files changed

+246
-5
lines changed

docs/reference/cluster/nodes-stats.asciidoc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,18 @@ Time by which recovery operations were delayed due to throttling.
959959
Time in milliseconds
960960
recovery operations were delayed due to throttling.
961961
=======
962+
963+
`shards`::
964+
(object)
965+
Contains statistics about all shards assigned to the node.
966+
+
967+
.Properties of `shards`
968+
[%collapsible%open]
969+
=======
970+
`total_count`::
971+
(integer)
972+
The total number of shards assigned to the node.
973+
=======
962974
======
963975

964976
[[cluster-nodes-stats-api-response-body-os]]

rest-api-spec/src/main/resources/rest-api-spec/api/nodes.stats.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,8 @@
127127
"segments",
128128
"store",
129129
"warmer",
130-
"suggest"
130+
"suggest",
131+
"shards"
131132
],
132133
"description":"Limit the information returned for `indices` metric to the specific index metrics. Isn't used if `indices` (or `all`) metric isn't specified."
133134
}
@@ -175,7 +176,8 @@
175176
"segments",
176177
"store",
177178
"warmer",
178-
"suggest"
179+
"suggest",
180+
"shards"
179181
],
180182
"description":"Limit the information returned for `indices` metric to the specific index metrics. Isn't used if `indices` (or `all`) metric isn't specified."
181183
},

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/nodes.stats/11_indices_metrics.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
- is_false: nodes.$node_id.indices.segments
110110
- is_false: nodes.$node_id.indices.translog
111111
- is_false: nodes.$node_id.indices.recovery
112+
- is_false: nodes.$node_id.indices.shards
112113

113114
---
114115
"Metric - multi":
@@ -166,6 +167,7 @@
166167
- is_false: nodes.$node_id.indices.segments
167168
- is_false: nodes.$node_id.indices.translog
168169
- is_true: nodes.$node_id.indices.recovery
170+
- is_false: nodes.$node_id.indices.shards
169171

170172
---
171173
"Metric - _all include_segment_file_sizes":
@@ -223,6 +225,7 @@
223225
- is_true: nodes.$node_id.indices.segments
224226
- is_false: nodes.$node_id.indices.translog
225227
- is_false: nodes.$node_id.indices.recovery
228+
- is_false: nodes.$node_id.indices.shards
226229
- is_true: nodes.$node_id.indices.segments.file_sizes
227230

228231
---
@@ -254,6 +257,7 @@
254257
- is_true: nodes.$node_id.indices.segments
255258
- is_false: nodes.$node_id.indices.translog
256259
- is_false: nodes.$node_id.indices.recovery
260+
- is_false: nodes.$node_id.indices.shards
257261

258262
---
259263
"Metric - _all include_unloaded_segments":
@@ -314,3 +318,72 @@
314318
- gte: { nodes.$node_id.http.clients.0.request_size_bytes: 0 }
315319
# values for clients.0.closed_time_millis, clients.0.x_forwarded_for, and clients.0.x_opaque_id are often
316320
# null and cannot be tested here
321+
322+
---
323+
"Metric - blank for indices shards":
324+
- skip:
325+
features: [arbitrary_key]
326+
version: " - 7.99.99"
327+
reason: "total shard count added in version 8.0"
328+
- do:
329+
nodes.info: {}
330+
- set:
331+
nodes._arbitrary_key_: node_id
332+
333+
- do:
334+
nodes.stats: {}
335+
336+
- is_true: nodes.$node_id.indices.shards
337+
- match: { nodes.$node_id.indices.shards.total_count: 0 }
338+
339+
---
340+
"Metric - _all for indices shards":
341+
- skip:
342+
features: [arbitrary_key]
343+
version: " - 7.99.99"
344+
reason: "total shard count added in version 8.0"
345+
- do:
346+
nodes.info: {}
347+
- set:
348+
nodes._arbitrary_key_: node_id
349+
350+
- do:
351+
nodes.stats: { metric: _all }
352+
353+
- is_true: nodes.$node_id.indices.shards
354+
- match: { nodes.$node_id.indices.shards.total_count: 0 }
355+
356+
357+
---
358+
"indices shards total count test":
359+
360+
- skip:
361+
features: ["allowed_warnings", arbitrary_key]
362+
version: " - 7.99.99"
363+
reason: "total shard count added in version 8.0"
364+
365+
- do:
366+
indices.create:
367+
index: index1
368+
body:
369+
settings:
370+
number_of_shards: "5"
371+
number_of_replicas: "0"
372+
373+
- do:
374+
indices.create:
375+
index: index2
376+
body:
377+
settings:
378+
number_of_shards: "3"
379+
number_of_replicas: "1"
380+
381+
- do:
382+
nodes.info: {}
383+
- set:
384+
nodes._arbitrary_key_: node_id
385+
386+
- do:
387+
nodes.stats: { metric: _all }
388+
389+
- gte: { nodes.$node_id.indices.shards.total_count: 1 }

server/src/internalClusterTest/java/org/elasticsearch/indices/stats/IndexStatsIT.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ public void testEncodeDecodeCommonStats() throws IOException {
729729
public void testFlagOrdinalOrder() {
730730
Flag[] flags = new Flag[]{Flag.Store, Flag.Indexing, Flag.Get, Flag.Search, Flag.Merge, Flag.Flush, Flag.Refresh,
731731
Flag.QueryCache, Flag.FieldData, Flag.Docs, Flag.Warmer, Flag.Completion, Flag.Segments,
732-
Flag.Translog, Flag.RequestCache, Flag.Recovery};
732+
Flag.Translog, Flag.RequestCache, Flag.Recovery, Flag.Shards};
733733

734734
assertThat(flags.length, equalTo(Flag.values().length));
735735
for (int i = 0; i < flags.length; i++) {
@@ -941,6 +941,10 @@ private static void set(Flag flag, IndicesStatsRequestBuilder builder, boolean s
941941
case Recovery:
942942
builder.setRecovery(set);
943943
break;
944+
case Shards:
945+
// We don't actually expose shards in IndexStats, but this test fails if it isn't handled
946+
builder.request().flags().set(Flag.Shards, set);
947+
break;
944948
default:
945949
fail("new flag? " + flag);
946950
break;
@@ -981,6 +985,8 @@ private static boolean isSet(Flag flag, CommonStats response) {
981985
return response.getRequestCache() != null;
982986
case Recovery:
983987
return response.getRecoveryStats() != null;
988+
case Shards:
989+
return response.getShards() != null;
984990
default:
985991
fail("new flag? " + flag);
986992
return false;

server/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStats.java

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package org.elasticsearch.action.admin.indices.stats;
1010

1111
import org.apache.lucene.store.AlreadyClosedException;
12+
import org.elasticsearch.Version;
1213
import org.elasticsearch.common.io.stream.StreamInput;
1314
import org.elasticsearch.common.io.stream.StreamOutput;
1415
import org.elasticsearch.common.io.stream.Writeable;
@@ -30,6 +31,7 @@
3031
import org.elasticsearch.index.shard.DocsStats;
3132
import org.elasticsearch.index.shard.IndexShard;
3233
import org.elasticsearch.index.shard.IndexingStats;
34+
import org.elasticsearch.index.shard.ShardCountStats;
3335
import org.elasticsearch.index.store.StoreStats;
3436
import org.elasticsearch.index.translog.TranslogStats;
3537
import org.elasticsearch.index.warmer.WarmerStats;
@@ -91,6 +93,9 @@ public class CommonStats implements Writeable, ToXContentFragment {
9193
@Nullable
9294
public RecoveryStats recoveryStats;
9395

96+
@Nullable
97+
public ShardCountStats shards;
98+
9499
public CommonStats() {
95100
this(CommonStatsFlags.NONE);
96101
}
@@ -148,6 +153,9 @@ public CommonStats(CommonStatsFlags flags) {
148153
case Recovery:
149154
recoveryStats = new RecoveryStats();
150155
break;
156+
case Shards:
157+
shards = new ShardCountStats();
158+
break;
151159
default:
152160
throw new IllegalStateException("Unknown Flag: " + flag);
153161
}
@@ -207,6 +215,10 @@ public CommonStats(IndicesQueryCache indicesQueryCache, IndexShard indexShard, C
207215
case Recovery:
208216
recoveryStats = indexShard.recoveryStats();
209217
break;
218+
case Shards:
219+
// Setting to 1 because the single IndexShard passed to this method implies 1 shard
220+
shards = new ShardCountStats(1);
221+
break;
210222
default:
211223
throw new IllegalStateException("Unknown Flag: " + flag);
212224
}
@@ -233,6 +245,9 @@ public CommonStats(StreamInput in) throws IOException {
233245
translog = in.readOptionalWriteable(TranslogStats::new);
234246
requestCache = in.readOptionalWriteable(RequestCacheStats::new);
235247
recoveryStats = in.readOptionalWriteable(RecoveryStats::new);
248+
if (in.getVersion().onOrAfter(Version.V_7_15_0)) {
249+
shards = in.readOptionalWriteable(ShardCountStats::new);
250+
}
236251
}
237252

238253
@Override
@@ -253,6 +268,9 @@ public void writeTo(StreamOutput out) throws IOException {
253268
out.writeOptionalWriteable(translog);
254269
out.writeOptionalWriteable(requestCache);
255270
out.writeOptionalWriteable(recoveryStats);
271+
if (out.getVersion().onOrAfter(Version.V_7_15_0)) {
272+
out.writeOptionalWriteable(shards);
273+
}
256274
}
257275

258276
public void add(CommonStats stats) {
@@ -385,6 +403,14 @@ public void add(CommonStats stats) {
385403
} else {
386404
recoveryStats.add(stats.getRecoveryStats());
387405
}
406+
if (stats.shards != null) {
407+
if (shards == null) {
408+
shards = stats.shards;
409+
}
410+
else {
411+
shards = shards.add(stats.shards);
412+
}
413+
}
388414
}
389415

390416
@Nullable
@@ -467,6 +493,11 @@ public RecoveryStats getRecoveryStats() {
467493
return recoveryStats;
468494
}
469495

496+
@Nullable
497+
public ShardCountStats getShards() {
498+
return shards;
499+
}
500+
470501
/**
471502
* Utility method which computes total memory by adding
472503
* FieldData, PercolatorCache, Segments (memory, index writer, version map)
@@ -492,7 +523,7 @@ public ByteSizeValue getTotalMemory() {
492523
@Override
493524
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
494525
final Stream<ToXContent> stream = Arrays.stream(new ToXContent[] {
495-
docs, store, indexing, get, search, merge, refresh, flush, warmer, queryCache,
526+
docs, shards, store, indexing, get, search, merge, refresh, flush, warmer, queryCache,
496527
fieldData, completion, segments, translog, requestCache, recoveryStats})
497528
.filter(Objects::nonNull);
498529
for (ToXContent toXContent : ((Iterable<ToXContent>)stream::iterator)) {

server/src/main/java/org/elasticsearch/action/admin/indices/stats/CommonStatsFlags.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ public enum Flag {
231231
Translog("translog", 13),
232232
// 14 was previously used for Suggest
233233
RequestCache("request_cache", 15),
234-
Recovery("recovery", 16);
234+
Recovery("recovery", 16),
235+
Shards("shards", 18);
235236

236237
private final String restName;
237238
private final int index;
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.index.shard;
10+
11+
import org.elasticsearch.common.Strings;
12+
import org.elasticsearch.common.io.stream.StreamInput;
13+
import org.elasticsearch.common.io.stream.StreamOutput;
14+
import org.elasticsearch.common.io.stream.Writeable;
15+
import org.elasticsearch.common.xcontent.ToXContentFragment;
16+
import org.elasticsearch.common.xcontent.XContentBuilder;
17+
import org.elasticsearch.core.Nullable;
18+
19+
import java.io.IOException;
20+
21+
public class ShardCountStats implements Writeable, ToXContentFragment {
22+
23+
private final long totalCount;
24+
25+
public ShardCountStats() {
26+
totalCount = 0;
27+
}
28+
29+
public ShardCountStats(StreamInput in) throws IOException {
30+
totalCount = in.readVLong();
31+
}
32+
33+
public ShardCountStats(long totalCount) {
34+
this.totalCount = totalCount;
35+
}
36+
37+
public long getTotalCount() {
38+
return this.totalCount;
39+
}
40+
41+
public ShardCountStats add(@Nullable ShardCountStats other) {
42+
return new ShardCountStats(this.totalCount + (other == null ? 0 : other.totalCount));
43+
}
44+
45+
@Override
46+
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
47+
builder.startObject(Fields.SHARDS);
48+
builder.field(Fields.TOTAL_COUNT, totalCount);
49+
builder.endObject();
50+
return builder;
51+
}
52+
53+
@Override
54+
public void writeTo(StreamOutput out) throws IOException {
55+
out.writeVLong(totalCount);
56+
}
57+
58+
static final class Fields {
59+
static final String SHARDS = "shards";
60+
static final String TOTAL_COUNT = "total_count";
61+
}
62+
63+
@Override
64+
public String toString() {
65+
return Strings.toString(this);
66+
}
67+
68+
@Override
69+
public boolean equals(Object o) {
70+
return (o instanceof ShardCountStats) && totalCount == ((ShardCountStats) o).totalCount;
71+
}
72+
73+
@Override
74+
public int hashCode() {
75+
return Long.hashCode(totalCount);
76+
}
77+
}

0 commit comments

Comments
 (0)