Skip to content

Commit 22d6425

Browse files
authored
Fetch node and shard heap metrics in a single call (#158087)
- Exposes method to fetch node and shard heap metrics in one call using one snapshot of memory metrics - Adds tests - Closes #4520
1 parent 72aa4d4 commit 22d6425

10 files changed

Lines changed: 454 additions & 149 deletions

File tree

server/src/internalClusterTest/java/org/elasticsearch/index/shard/IndexShardIT.java

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.cluster.ClusterInfoServiceUtils;
2323
import org.elasticsearch.cluster.ClusterState;
2424
import org.elasticsearch.cluster.EstimatedHeapUsageCollector;
25+
import org.elasticsearch.cluster.EstimatedHeapUsageStats;
2526
import org.elasticsearch.cluster.InternalClusterInfoService;
2627
import org.elasticsearch.cluster.NodeHeapEstimates;
2728
import org.elasticsearch.cluster.NodeHeapMetrics;
@@ -1008,29 +1009,19 @@ public BogusEstimatedEstimatedHeapUsageCollector(BogusEstimatedHeapUsagePlugin p
10081009
}
10091010

10101011
@Override
1011-
public void collectClusterHeapUsage(ActionListener<Map<String, NodeHeapEstimates>> listener) {
1012+
public void collectEstimatedHeapUsage(ActionListener<EstimatedHeapUsageStats> listener) {
10121013
final long totalHeapUsageBytes = randomNonNegativeLong();
1013-
ActionListener.completeWith(
1014-
listener,
1015-
() -> plugin.getClusterService()
1016-
.state()
1017-
.nodes()
1014+
ActionListener.completeWith(listener, () -> {
1015+
ClusterState state = plugin.getClusterService().state();
1016+
Map<String, NodeHeapEstimates> nodeHeapEstimates = state.nodes()
10181017
.stream()
10191018
.collect(
10201019
Collectors.toUnmodifiableMap(
10211020
DiscoveryNode::getId,
10221021
node -> new NodeHeapEstimates(totalHeapUsageBytes, randomLongBetween(0, totalHeapUsageBytes))
10231022
)
1024-
)
1025-
);
1026-
}
1027-
1028-
@Override
1029-
public void collectShardHeapUsage(ActionListener<ShardHeapUsageEstimates> listener) {
1030-
ActionListener.completeWith(listener, () -> {
1031-
var perShard = plugin.getClusterService()
1032-
.state()
1033-
.getRoutingNodes()
1023+
);
1024+
var perShard = state.getRoutingNodes()
10341025
.stream()
10351026
.map(node -> node.started())
10361027
.flatMap(nodeIt -> StreamSupport.stream(nodeIt.spliterator(), false))
@@ -1040,7 +1031,10 @@ public void collectShardHeapUsage(ActionListener<ShardHeapUsageEstimates> listen
10401031
shardRouting -> new ShardAndIndexHeapUsage(randomShardHeapUsage(), randomIndexHeapUsage())
10411032
)
10421033
);
1043-
return new ShardHeapUsageEstimates(perShard, new ShardAndIndexHeapUsage(randomShardHeapUsage(), randomIndexHeapUsage()));
1034+
return new EstimatedHeapUsageStats(
1035+
nodeHeapEstimates,
1036+
new ShardHeapUsageEstimates(perShard, new ShardAndIndexHeapUsage(randomShardHeapUsage(), randomIndexHeapUsage()))
1037+
);
10441038
});
10451039
}
10461040
}

server/src/main/java/org/elasticsearch/cluster/EstimatedHeapUsageCollector.java

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@
1111

1212
import org.elasticsearch.action.ActionListener;
1313

14-
import java.util.Map;
15-
1614
/**
17-
* Collect the estimated heap usage for each node in the cluster.
18-
* <p>
19-
* Results are returned as a map of node ID to estimated heap usage in bytes
15+
* Collects node and shard heap usage estimates for {@link ClusterInfo}.
2016
*
2117
* @see NodeHeapMetrics
2218
*/
@@ -25,29 +21,12 @@ public interface EstimatedHeapUsageCollector {
2521
/**
2622
* This will be used when there is no EstimatedHeapUsageCollector available
2723
*/
28-
EstimatedHeapUsageCollector EMPTY = new EstimatedHeapUsageCollector() {
29-
@Override
30-
public void collectClusterHeapUsage(ActionListener<Map<String, NodeHeapEstimates>> listener) {
31-
listener.onResponse(Map.of());
32-
}
33-
34-
@Override
35-
public void collectShardHeapUsage(ActionListener<ShardHeapUsageEstimates> listener) {
36-
listener.onResponse(ShardHeapUsageEstimates.empty());
37-
}
38-
};
39-
40-
/**
41-
* Collect the estimated heap usage for every node in the cluster
42-
*
43-
* @param listener The listener which will receive the results
44-
*/
45-
void collectClusterHeapUsage(ActionListener<Map<String, NodeHeapEstimates>> listener);
24+
EstimatedHeapUsageCollector EMPTY = listener -> listener.onResponse(EstimatedHeapUsageStats.EMPTY);
4625

4726
/**
48-
* Collects the estimated heap usage for every shard in the cluster.
27+
* Collects node and shard heap usage estimates from a single source snapshot.
4928
*
5029
* @param listener The listener which will receive the results
5130
*/
52-
void collectShardHeapUsage(ActionListener<ShardHeapUsageEstimates> listener);
31+
void collectEstimatedHeapUsage(ActionListener<EstimatedHeapUsageStats> listener);
5332
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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.cluster;
11+
12+
import java.util.Map;
13+
14+
/**
15+
* Node heap usage estimates and individual shard heap usage estimates collected from the same source snapshot.
16+
*/
17+
public record EstimatedHeapUsageStats(Map<String, NodeHeapEstimates> nodeHeapEstimates, ShardHeapUsageEstimates shardHeapUsageEstimates) {
18+
19+
public static final EstimatedHeapUsageStats EMPTY = new EstimatedHeapUsageStats(Map.of(), ShardHeapUsageEstimates.empty());
20+
21+
public EstimatedHeapUsageStats {
22+
nodeHeapEstimates = Map.copyOf(nodeHeapEstimates);
23+
assert shardHeapUsageEstimates != null;
24+
}
25+
}

server/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -376,28 +376,17 @@ public void onFailure(Exception e) {
376376
}
377377

378378
private void fetchEstimatedHeapUsage() {
379-
estimatedHeapUsageCollector.collectClusterHeapUsage(ActionListener.releaseAfter(new ActionListener<>() {
379+
estimatedHeapUsageCollector.collectEstimatedHeapUsage(ActionListener.releaseAfter(new ActionListener<>() {
380380
@Override
381-
public void onResponse(Map<String, NodeHeapEstimates> currentNodeHeapEstimates) {
382-
nodeHeapEstimates = currentNodeHeapEstimates;
381+
public void onResponse(EstimatedHeapUsageStats estimatedHeapUsageStats) {
382+
nodeHeapEstimates = estimatedHeapUsageStats.nodeHeapEstimates();
383+
estimatedShardHeapUsageEstimates = estimatedHeapUsageStats.shardHeapUsageEstimates();
383384
}
384385

385386
@Override
386387
public void onFailure(Exception e) {
387-
logger.warn("failed to fetch heap usage for nodes", e);
388+
logger.warn("failed to fetch node heap estimates and shard heap usage estimates", e);
388389
nodeHeapEstimates = Map.of();
389-
}
390-
}, fetchRefs.acquire()));
391-
392-
estimatedHeapUsageCollector.collectShardHeapUsage(ActionListener.releaseAfter(new ActionListener<>() {
393-
@Override
394-
public void onResponse(ShardHeapUsageEstimates currentEstimatedHeapUsages) {
395-
estimatedShardHeapUsageEstimates = currentEstimatedHeapUsages;
396-
}
397-
398-
@Override
399-
public void onFailure(Exception e) {
400-
logger.warn("failed to fetch heap usage for shards", e);
401390
estimatedShardHeapUsageEstimates = ShardHeapUsageEstimates.empty();
402391
}
403392
}, fetchRefs.acquire()));

0 commit comments

Comments
 (0)