Skip to content

Commit e0af123

Browse files
authored
Index stats enhancement: creation date and tier_preference (elastic#116339)
* Expose tier preference as part of the index stats * Also expose index creation date in index stats * Added test
1 parent 4d210c8 commit e0af123

10 files changed

Lines changed: 135 additions & 7 deletions

File tree

docs/changelog/116339.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 116339
2+
summary: "Index stats enhancement: creation date and `tier_preference`"
3+
area: Stats
4+
type: feature
5+
issues: []
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
"Ensure index creation date and tier preference are exposed":
3+
- requires:
4+
cluster_features: ["stats.tier_creation_date"]
5+
reason: index creation date and tier preference added to stats in 8.17
6+
7+
- do:
8+
indices.create:
9+
index: myindex
10+
- do:
11+
indices.stats: {}
12+
13+
- is_true: indices.myindex.creation_date
14+
- is_true: indices.myindex.tier_preference

server/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@
419419

420420
provides org.elasticsearch.features.FeatureSpecification
421421
with
422+
org.elasticsearch.action.admin.indices.stats.IndicesStatsFeatures,
422423
org.elasticsearch.action.bulk.BulkFeatures,
423424
org.elasticsearch.features.FeatureInfrastructureFeatures,
424425
org.elasticsearch.health.HealthFeatures,

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ static TransportVersion def(int id) {
199199
public static final TransportVersion VERTEX_AI_INPUT_TYPE_ADDED = def(8_790_00_0);
200200
public static final TransportVersion SKIP_INNER_HITS_SEARCH_SOURCE = def(8_791_00_0);
201201
public static final TransportVersion QUERY_RULES_LIST_INCLUDES_TYPES = def(8_792_00_0);
202+
public static final TransportVersion INDEX_STATS_ADDITIONAL_FIELDS = def(8_793_00_0);
202203

203204
/*
204205
* STOP! READ THIS FIRST! No, really,

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.cluster.health.ClusterHealthStatus;
1313
import org.elasticsearch.cluster.metadata.IndexMetadata;
1414
import org.elasticsearch.core.Nullable;
15+
import org.elasticsearch.features.NodeFeature;
1516

1617
import java.util.ArrayList;
1718
import java.util.HashMap;
@@ -21,6 +22,8 @@
2122

2223
public class IndexStats implements Iterable<IndexShardStats> {
2324

25+
public static final NodeFeature TIER_CREATION_DATE = new NodeFeature("stats.tier_creation_date");
26+
2427
private final String index;
2528

2629
private final String uuid;
@@ -29,19 +32,27 @@ public class IndexStats implements Iterable<IndexShardStats> {
2932

3033
private final IndexMetadata.State state;
3134

35+
private final List<String> tierPreference;
36+
37+
private final Long creationDate;
38+
3239
private final ShardStats shards[];
3340

3441
public IndexStats(
3542
String index,
3643
String uuid,
3744
@Nullable ClusterHealthStatus health,
3845
@Nullable IndexMetadata.State state,
46+
@Nullable List<String> tierPreference,
47+
@Nullable Long creationDate,
3948
ShardStats[] shards
4049
) {
4150
this.index = index;
4251
this.uuid = uuid;
4352
this.health = health;
4453
this.state = state;
54+
this.tierPreference = tierPreference;
55+
this.creationDate = creationDate;
4556
this.shards = shards;
4657
}
4758

@@ -61,6 +72,14 @@ public IndexMetadata.State getState() {
6172
return state;
6273
}
6374

75+
public List<String> getTierPreference() {
76+
return tierPreference;
77+
}
78+
79+
public Long getCreationDate() {
80+
return creationDate;
81+
}
82+
6483
public ShardStats[] getShards() {
6584
return this.shards;
6685
}
@@ -129,13 +148,24 @@ public static class IndexStatsBuilder {
129148
private final String uuid;
130149
private final ClusterHealthStatus health;
131150
private final IndexMetadata.State state;
151+
private final List<String> tierPreference;
152+
private final Long creationDate;
132153
private final List<ShardStats> shards = new ArrayList<>();
133154

134-
public IndexStatsBuilder(String indexName, String uuid, @Nullable ClusterHealthStatus health, @Nullable IndexMetadata.State state) {
155+
public IndexStatsBuilder(
156+
String indexName,
157+
String uuid,
158+
@Nullable ClusterHealthStatus health,
159+
@Nullable IndexMetadata.State state,
160+
@Nullable List<String> tierPreference,
161+
@Nullable Long creationDate
162+
) {
135163
this.indexName = indexName;
136164
this.uuid = uuid;
137165
this.health = health;
138166
this.state = state;
167+
this.tierPreference = tierPreference;
168+
this.creationDate = creationDate;
139169
}
140170

141171
public IndexStatsBuilder add(ShardStats shardStats) {
@@ -144,7 +174,15 @@ public IndexStatsBuilder add(ShardStats shardStats) {
144174
}
145175

146176
public IndexStats build() {
147-
return new IndexStats(indexName, uuid, health, state, shards.toArray(new ShardStats[shards.size()]));
177+
return new IndexStats(
178+
indexName,
179+
uuid,
180+
health,
181+
state,
182+
tierPreference,
183+
creationDate,
184+
shards.toArray(new ShardStats[shards.size()])
185+
);
148186
}
149187
}
150188
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.action.admin.indices.stats;
11+
12+
import org.elasticsearch.features.FeatureSpecification;
13+
import org.elasticsearch.features.NodeFeature;
14+
15+
import java.util.Set;
16+
17+
public class IndicesStatsFeatures implements FeatureSpecification {
18+
19+
@Override
20+
public Set<NodeFeature> getFeatures() {
21+
return Set.of(IndexStats.TIER_CREATION_DATE);
22+
}
23+
}

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

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,34 @@ public class IndicesStatsResponse extends ChunkedBroadcastResponse {
4747

4848
private final Map<String, IndexMetadata.State> indexStateMap;
4949

50+
private final Map<String, List<String>> indexTierPreferenceMap;
51+
52+
private final Map<String, Long> indexCreationDateMap;
53+
5054
private final ShardStats[] shards;
5155

5256
private Map<ShardRouting, ShardStats> shardStatsMap;
5357

5458
IndicesStatsResponse(StreamInput in) throws IOException {
5559
super(in);
5660
shards = in.readArray(ShardStats::new, ShardStats[]::new);
57-
if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_1_0)) {
61+
if (in.getTransportVersion().onOrAfter(TransportVersions.INDEX_STATS_ADDITIONAL_FIELDS)) {
5862
indexHealthMap = in.readMap(ClusterHealthStatus::readFrom);
5963
indexStateMap = in.readMap(IndexMetadata.State::readFrom);
64+
indexTierPreferenceMap = in.readMap(StreamInput::readStringCollectionAsList);
65+
indexCreationDateMap = in.readMap(StreamInput::readLong);
66+
} else if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_1_0)) {
67+
// Between 8.1 and INDEX_STATS_ADDITIONAL_FIELDS, we had a different format for the response
68+
// where we only had health and state available.
69+
indexHealthMap = in.readMap(ClusterHealthStatus::readFrom);
70+
indexStateMap = in.readMap(IndexMetadata.State::readFrom);
71+
indexTierPreferenceMap = Map.of();
72+
indexCreationDateMap = Map.of();
6073
} else {
6174
indexHealthMap = Map.of();
6275
indexStateMap = Map.of();
76+
indexTierPreferenceMap = Map.of();
77+
indexCreationDateMap = Map.of();
6378
}
6479
}
6580

@@ -79,6 +94,8 @@ public class IndicesStatsResponse extends ChunkedBroadcastResponse {
7994
Objects.requireNonNull(shards);
8095
Map<String, ClusterHealthStatus> indexHealthModifiableMap = new HashMap<>();
8196
Map<String, IndexMetadata.State> indexStateModifiableMap = new HashMap<>();
97+
Map<String, List<String>> indexTierPreferenceModifiableMap = new HashMap<>();
98+
Map<String, Long> indexCreationDateModifiableMap = new HashMap<>();
8299
for (ShardStats shard : shards) {
83100
Index index = shard.getShardRouting().index();
84101
IndexMetadata indexMetadata = metadata.index(index);
@@ -88,10 +105,14 @@ public class IndicesStatsResponse extends ChunkedBroadcastResponse {
88105
ignored -> new ClusterIndexHealth(indexMetadata, routingTable.index(index)).getStatus()
89106
);
90107
indexStateModifiableMap.computeIfAbsent(index.getName(), ignored -> indexMetadata.getState());
108+
indexTierPreferenceModifiableMap.computeIfAbsent(index.getName(), ignored -> indexMetadata.getTierPreference());
109+
indexCreationDateModifiableMap.computeIfAbsent(index.getName(), ignored -> indexMetadata.getCreationDate());
91110
}
92111
}
93112
indexHealthMap = unmodifiableMap(indexHealthModifiableMap);
94113
indexStateMap = unmodifiableMap(indexStateModifiableMap);
114+
indexTierPreferenceMap = unmodifiableMap(indexTierPreferenceModifiableMap);
115+
indexCreationDateMap = unmodifiableMap(indexCreationDateModifiableMap);
95116
}
96117

97118
public Map<ShardRouting, ShardStats> asMap() {
@@ -129,7 +150,14 @@ public Map<String, IndexStats> getIndices() {
129150
Index index = shard.getShardRouting().index();
130151
IndexStatsBuilder indexStatsBuilder = indexToIndexStatsBuilder.computeIfAbsent(
131152
index.getName(),
132-
k -> new IndexStatsBuilder(k, index.getUUID(), indexHealthMap.get(index.getName()), indexStateMap.get(index.getName()))
153+
k -> new IndexStatsBuilder(
154+
k,
155+
index.getUUID(),
156+
indexHealthMap.get(index.getName()),
157+
indexStateMap.get(index.getName()),
158+
indexTierPreferenceMap.get(index.getName()),
159+
indexCreationDateMap.get(index.getName())
160+
)
133161
);
134162
indexStatsBuilder.add(shard);
135163
}
@@ -174,7 +202,13 @@ public CommonStats getPrimaries() {
174202
public void writeTo(StreamOutput out) throws IOException {
175203
super.writeTo(out);
176204
out.writeArray(shards);
177-
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_1_0)) {
205+
if (out.getTransportVersion().onOrAfter(TransportVersions.INDEX_STATS_ADDITIONAL_FIELDS)) {
206+
out.writeMap(indexHealthMap, StreamOutput::writeWriteable);
207+
out.writeMap(indexStateMap, StreamOutput::writeWriteable);
208+
out.writeMap(indexTierPreferenceMap, StreamOutput::writeStringCollection);
209+
out.writeMap(indexCreationDateMap, StreamOutput::writeLong);
210+
211+
} else if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_1_0)) {
178212
out.writeMap(indexHealthMap, StreamOutput::writeWriteable);
179213
out.writeMap(indexStateMap, StreamOutput::writeWriteable);
180214
}
@@ -203,6 +237,12 @@ protected Iterator<ToXContent> customXContentChunks(ToXContent.Params params) {
203237
if (indexStats.getState() != null) {
204238
builder.field("status", indexStats.getState().toString().toLowerCase(Locale.ROOT));
205239
}
240+
if (indexStats.getTierPreference() != null) {
241+
builder.field("tier_preference", indexStats.getTierPreference());
242+
}
243+
if (indexStats.getCreationDate() != null) {
244+
builder.field("creation_date", indexStats.getCreationDate());
245+
}
206246
builder.startObject("primaries");
207247
indexStats.getPrimaries().toXContent(builder, p);
208248
builder.endObject();

server/src/main/resources/META-INF/services/org.elasticsearch.features.FeatureSpecification

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
# License v3.0 only", or the "Server Side Public License, v 1".
88
#
99

10+
org.elasticsearch.action.admin.indices.stats.IndicesStatsFeatures
1011
org.elasticsearch.action.bulk.BulkFeatures
1112
org.elasticsearch.features.FeatureInfrastructureFeatures
1213
org.elasticsearch.health.HealthFeatures

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/WaitForNoFollowersStepTests.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,10 @@ public void testNoShardStats() {
189189
shardStats[0] = sStats;
190190

191191
mockXPackInfo(true, true);
192-
mockIndexStatsCall(indexName, new IndexStats(indexName, "uuid", ClusterHealthStatus.GREEN, IndexMetadata.State.OPEN, shardStats));
192+
mockIndexStatsCall(
193+
indexName,
194+
new IndexStats(indexName, "uuid", ClusterHealthStatus.GREEN, IndexMetadata.State.OPEN, null, null, shardStats)
195+
);
193196

194197
final SetOnce<Boolean> conditionMetHolder = new SetOnce<>();
195198
final SetOnce<ToXContentObject> stepInfoHolder = new SetOnce<>();
@@ -289,7 +292,7 @@ private IndexStats randomIndexStats(boolean isLeaderIndex, int numOfShards) {
289292
for (int i = 0; i < numOfShards; i++) {
290293
shardStats[i] = randomShardStats(isLeaderIndex);
291294
}
292-
return new IndexStats(randomAlphaOfLength(5), randomAlphaOfLength(10), null, null, shardStats);
295+
return new IndexStats(randomAlphaOfLength(5), randomAlphaOfLength(10), null, null, null, null, shardStats);
293296
}
294297

295298
private ShardStats randomShardStats(boolean isLeaderIndex) {

x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndicesStatsMonitoringDocTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public void setUp() throws Exception {
5353
"dcvO5uZATE-EhIKc3tk9Bg",
5454
null,
5555
null,
56+
null,
57+
null,
5658
new ShardStats[] {
5759
// Primaries
5860
new ShardStats(mockShardRouting(true), mockShardPath(), mockCommonStats(), null, null, null, false, 0),

0 commit comments

Comments
 (0)