Skip to content

Commit 41aa94d

Browse files
available_processors field in CAT Nodes
Cat nodes REST action will return an extra field: available_processors. It is now also part of all responses which contain Os Stats. Closes #134692
1 parent 51599b4 commit 41aa94d

File tree

15 files changed

+151
-17
lines changed

15 files changed

+151
-17
lines changed

distribution/docker/src/yamlRestTest/resources/rest-api-spec/test/11_nodes.yml

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,41 @@
11
---
2-
"Test cat nodes output":
2+
"Test cat nodes output for all fields with available_processors":
3+
- requires:
4+
capabilities:
5+
- method: GET
6+
path: /_cat/nodes
7+
capabilities: [ available_processors ]
8+
test_runner_features: [ capabilities ]
9+
reason: available_processors capability required to run test
10+
11+
- do:
12+
cat.nodes: {}
13+
14+
- match:
15+
$body: |
16+
/ #ip heap.percent ram.percent cpu load_1m load_5m load_15m available_processors node.role master name
17+
^ ((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)?\s+ ((-)?\d*(\.\d+)?)? \s+ (\d+)? \s+ (-|[cdfhilmrstvw]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
18+
19+
- do:
20+
cat.nodes:
21+
v: true
22+
23+
- match:
24+
$body: |
25+
/^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ available_processors \s+ node\.role \s+ master \s+ name \n
26+
((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (\d+)? \s+ (-|[cdfhilmrstvw]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
27+
28+
---
29+
"Test cat nodes output for all fields before available_processors was added":
30+
- requires:
31+
test_runner_features: [ capabilities ]
32+
33+
- skip:
34+
capabilities:
35+
- method: GET
36+
path: /_cat/nodes
37+
capabilities: [ available_processors ]
38+
reason: available_processors capability must be missing to run this test
339

440
- do:
541
cat.nodes: {}
@@ -15,9 +51,11 @@
1551

1652
- match:
1753
$body: |
18-
/^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ node\.role \s+ master \s+ name \n
19-
((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvw]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
54+
/^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ node\.role \s+ master \s+ name \n
55+
((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvw]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
2056
57+
---
58+
"Test cat nodes output for selected fields":
2159
- do:
2260
cat.nodes:
2361
h: heap.current,heap.percent,heap.max

rest-api-spec/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ tasks.named("yamlRestCompatTestTransform").configure ({ task ->
100100
task.skipTest("logsdb/10_settings/end time not allowed in logs mode", "we don't validate for index_mode=tsdb when setting start_date/end_date anymore")
101101
task.skipTest("tsdb/10_settings/set start_time and end_time without timeseries mode", "we don't validate for index_mode=tsdb when setting start_date/end_date anymore")
102102
task.skipTest("tsdb/10_settings/set start_time, end_time and routing_path via put settings api without time_series mode", "we don't validate for index_mode=tsdb when setting start_date/end_date anymore")
103+
task.skipTest("cat.nodes/10_basic/Test cat nodes output", "a new field 'available_processors' was added")
103104
// Expected deprecation warning to compat yaml tests:
104105
task.addAllowedWarningRegex("Use of the \\[max_size\\] rollover condition has been deprecated in favour of the \\[max_primary_shard_size\\] condition and will be removed in a later version")
105106
})

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.nodes/10_basic.yml

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,62 @@
11
---
2-
"Test cat nodes output":
2+
"Test cat nodes output for all fields with available_processors":
3+
- requires:
4+
capabilities:
5+
- method: GET
6+
path: /_cat/nodes
7+
capabilities: [ available_processors ]
8+
test_runner_features: [ capabilities ]
9+
reason: available_processors capability required to run test
310

411
- do:
512
cat.nodes: {}
613

714
- match:
815
$body: |
9-
/ #ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
10-
^ ((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)?\s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
16+
/ #ip heap.percent ram.percent cpu load_1m load_5m load_15m available_processors node.role master name
17+
^ ((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)?\s+ ((-)?\d*(\.\d+)?)? \s+ (\d+)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
1118
1219
- do:
1320
cat.nodes:
1421
v: true
1522

1623
- match:
1724
$body: |
18-
/^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ node\.role \s+ master \s+ name \n
19-
((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
25+
/^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ available_processors \s+ node\.role \s+ master \s+ name \n
26+
((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (\d+)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
2027
28+
---
29+
"Test cat nodes output for all fields before available_processors was added":
30+
31+
- requires:
32+
test_runner_features: [ capabilities ]
33+
34+
- skip:
35+
capabilities:
36+
- method: GET
37+
path: /_cat/nodes
38+
capabilities: [ available_processors ]
39+
reason: available_processors capability must be missing to run this test
40+
41+
- do:
42+
cat.nodes: {}
43+
44+
- match:
45+
$body: |
46+
/ #ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role master name
47+
^ ((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)?\s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
48+
49+
- do:
50+
cat.nodes:
51+
v: true
52+
53+
- match:
54+
$body: |
55+
/^ ip \s+ heap\.percent \s+ ram\.percent \s+ cpu \s+ load_1m \s+ load_5m \s+ load_15m \s+ node\.role \s+ master \s+ name \n
56+
((\d{1,3}\.){3}\d{1,3} \s+ \d+ \s+ \d* \s+ (-)?\d* \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ ((-)?\d*(\.\d+)?)? \s+ (-|[cdfhilmrstvwIS]{1,11}) \s+ [-*x] \s+ .* \n)+ $/
57+
58+
---
59+
"Test cat nodes output for selected fields":
2160
- do:
2261
cat.nodes:
2362
h: heap.current,heap.percent,heap.max

server/src/main/java/org/elasticsearch/monitor/os/OsProbe.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public class OsProbe {
7272
private static final Method getTotalSwapSpaceSize;
7373
private static final Method getSystemLoadAverage;
7474
private static final Method getSystemCpuLoad;
75+
private static final Method getAvailableProcessors;
7576

7677
static {
7778
getFreePhysicalMemorySize = getMethod("getFreePhysicalMemorySize");
@@ -80,6 +81,7 @@ public class OsProbe {
8081
getTotalSwapSpaceSize = getMethod("getTotalSwapSpaceSize");
8182
getSystemLoadAverage = getMethod("getSystemLoadAverage");
8283
getSystemCpuLoad = getMethod("getSystemCpuLoad");
84+
getAvailableProcessors = getMethod("getAvailableProcessors");
8385
}
8486

8587
/**
@@ -259,6 +261,24 @@ public static short getSystemCpuPercent() {
259261
return Probes.getLoadAndScaleToPercent(getSystemCpuLoad, osMxBean);
260262
}
261263

264+
public static int getAvailableProcessors() {
265+
if (getAvailableProcessors == null) {
266+
logger.warn("getAvailableProcessors is not available");
267+
return 0;
268+
}
269+
try {
270+
int availableProcessors = (int) getAvailableProcessors.invoke(osMxBean);
271+
if (availableProcessors <= 0) {
272+
logger.debug("OS reported a non-positive number of available processors [{}]", availableProcessors);
273+
return 0;
274+
}
275+
return availableProcessors;
276+
} catch (Exception e) {
277+
logger.warn("exception retrieving available processors", e);
278+
return 0;
279+
}
280+
}
281+
262282
/**
263283
* Reads a file containing a single line.
264284
*
@@ -902,7 +922,7 @@ OsStats.Cgroup getCgroup(boolean isLinux) {
902922
}
903923

904924
public OsStats osStats() {
905-
final OsStats.Cpu cpu = new OsStats.Cpu(getSystemCpuPercent(), getSystemLoadAverage());
925+
final OsStats.Cpu cpu = new OsStats.Cpu(getSystemCpuPercent(), getSystemLoadAverage(), getAvailableProcessors());
906926
final OsStats.Mem mem = new OsStats.Mem(getTotalPhysicalMemorySize(), getAdjustedTotalMemorySize(), getFreePhysicalMemorySize());
907927
final OsStats.Swap swap = new OsStats.Swap(getTotalSwapSpaceSize(), getFreeSwapSpaceSize());
908928
final OsStats.Cgroup cgroup = getCgroup(Constants.LINUX);

server/src/main/java/org/elasticsearch/monitor/os/OsService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ private static class OsStatsCache extends SingleObjectCache<OsStats> {
5555

5656
private static final OsStats MISSING = new OsStats(
5757
0L,
58-
new OsStats.Cpu((short) 0, new double[0]),
58+
new OsStats.Cpu((short) 0, new double[0], 0),
5959
new OsStats.Mem(0, 0, 0),
6060
new OsStats.Swap(0, 0),
6161
null

server/src/main/java/org/elasticsearch/monitor/os/OsStats.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.apache.logging.log4j.LogManager;
1313
import org.apache.logging.log4j.Logger;
14+
import org.elasticsearch.TransportVersion;
1415
import org.elasticsearch.TransportVersions;
1516
import org.elasticsearch.common.io.stream.StreamInput;
1617
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -86,6 +87,7 @@ static final class Fields {
8687
static final String LOAD_AVERAGE_1M = "1m";
8788
static final String LOAD_AVERAGE_5M = "5m";
8889
static final String LOAD_AVERAGE_15M = "15m";
90+
static final String AVAILABLE_PROCESSORS = "available_processors";
8991

9092
static final String MEM = "mem";
9193
static final String SWAP = "swap";
@@ -118,12 +120,16 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
118120

119121
public static class Cpu implements Writeable, ToXContentFragment {
120122

123+
private static final String AVAILABLE_PROCESSORS_TRANSPORT_VERSION = "available_processors_in_os_stats";
124+
121125
private final short percent;
122126
private final double[] loadAverage;
127+
private final int availableProcessors;
123128

124-
public Cpu(short systemCpuPercent, double[] systemLoadAverage) {
129+
public Cpu(short systemCpuPercent, double[] systemLoadAverage, int availableProcessors) {
125130
this.percent = systemCpuPercent;
126131
this.loadAverage = systemLoadAverage;
132+
this.availableProcessors = availableProcessors;
127133
}
128134

129135
public Cpu(StreamInput in) throws IOException {
@@ -133,6 +139,9 @@ public Cpu(StreamInput in) throws IOException {
133139
} else {
134140
this.loadAverage = null;
135141
}
142+
this.availableProcessors = in.getTransportVersion().supports(TransportVersion.fromName(AVAILABLE_PROCESSORS_TRANSPORT_VERSION))
143+
? in.readInt()
144+
: 0;
136145
}
137146

138147
@Override
@@ -144,6 +153,9 @@ public void writeTo(StreamOutput out) throws IOException {
144153
out.writeBoolean(true);
145154
out.writeDoubleArray(loadAverage);
146155
}
156+
if (out.getTransportVersion().supports(TransportVersion.fromName(AVAILABLE_PROCESSORS_TRANSPORT_VERSION))) {
157+
out.writeInt(availableProcessors);
158+
}
147159
}
148160

149161
public short getPercent() {
@@ -154,6 +166,10 @@ public double[] getLoadAverage() {
154166
return loadAverage;
155167
}
156168

169+
public int getAvailableProcessors() {
170+
return availableProcessors;
171+
}
172+
157173
@Override
158174
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
159175
builder.startObject(Fields.CPU);
@@ -171,6 +187,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
171187
}
172188
builder.endObject();
173189
}
190+
builder.field(Fields.AVAILABLE_PROCESSORS, getAvailableProcessors());
174191
builder.endObject();
175192
return builder;
176193
}

server/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.elasticsearch.common.network.NetworkAddress;
2929
import org.elasticsearch.common.transport.TransportAddress;
3030
import org.elasticsearch.common.unit.ByteSizeValue;
31+
import org.elasticsearch.common.util.set.Sets;
3132
import org.elasticsearch.http.HttpInfo;
3233
import org.elasticsearch.index.bulk.stats.BulkStats;
3334
import org.elasticsearch.index.cache.query.QueryCacheStats;
@@ -58,6 +59,7 @@
5859
import org.elasticsearch.search.suggest.completion.CompletionStats;
5960

6061
import java.util.List;
62+
import java.util.Set;
6163
import java.util.concurrent.atomic.AtomicReference;
6264

6365
import static org.elasticsearch.rest.RestRequest.Method.GET;
@@ -66,6 +68,8 @@
6668
@ServerlessScope(Scope.INTERNAL)
6769
public class RestNodesAction extends AbstractCatAction {
6870

71+
private static final String CAPABILITY_AVAILABLE_PROCESSORS_AVAILABILITY = "available_processors_availability";
72+
6973
@Override
7074
public List<Route> routes() {
7175
return List.of(new Route(GET, "/_cat/nodes"));
@@ -168,6 +172,7 @@ protected Table getTableWithHeader(final RestRequest request) {
168172
table.addCell("load_1m", "alias:l;text-align:right;desc:1m load avg");
169173
table.addCell("load_5m", "alias:l;text-align:right;desc:5m load avg");
170174
table.addCell("load_15m", "alias:l;text-align:right;desc:15m load avg");
175+
table.addCell("available_processors", "alias:ap;text-align:right;desc:available processors");
171176
table.addCell("uptime", "default:false;alias:u;text-align:right;desc:node uptime");
172177
table.addCell(
173178
"node.role",
@@ -335,6 +340,11 @@ protected Table getTableWithHeader(final RestRequest request) {
335340
return table;
336341
}
337342

343+
@Override
344+
public Set<String> supportedCapabilities() {
345+
return Sets.union(super.supportedCapabilities(), Set.of(CAPABILITY_AVAILABLE_PROCESSORS_AVAILABILITY));
346+
}
347+
338348
Table buildTable(
339349
boolean fullId,
340350
RestRequest req,
@@ -425,6 +435,8 @@ Table buildTable(
425435
? null
426436
: RestTable.FormattedDouble.format2DecimalPlaces(osStats.getCpu().getLoadAverage()[2])
427437
);
438+
table.addCell(osStats == null ? null : osStats.getCpu().getAvailableProcessors());
439+
428440
table.addCell(jvmStats == null ? null : jvmStats.getUptime());
429441

430442
table.addCell(node.getRoleAbbreviationString());
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
9190000
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
esql_resolve_fields_response_created,9189000
1+
available_processors_in_os_stats,9190000

server/src/test/java/org/elasticsearch/action/admin/cluster/node/stats/NodeStatsTests.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,10 @@ public void testSerialization() throws IOException {
130130
assertEquals(nodeStats.getOs().getMem().getFreePercent(), deserializedNodeStats.getOs().getMem().getFreePercent());
131131
assertEquals(nodeStats.getOs().getMem().getUsedPercent(), deserializedNodeStats.getOs().getMem().getUsedPercent());
132132
assertEquals(nodeStats.getOs().getCpu().getPercent(), deserializedNodeStats.getOs().getCpu().getPercent());
133+
assertEquals(
134+
nodeStats.getOs().getCpu().getAvailableProcessors(),
135+
deserializedNodeStats.getOs().getCpu().getAvailableProcessors()
136+
);
133137
assertEquals(
134138
nodeStats.getOs().getCgroup().getCpuAcctControlGroup(),
135139
deserializedNodeStats.getOs().getCgroup().getCpuAcctControlGroup()
@@ -711,7 +715,7 @@ public static NodeStats createNodeStats() {
711715
long swapTotal = randomNonNegativeLong();
712716
osStats = new OsStats(
713717
System.currentTimeMillis(),
714-
new OsStats.Cpu(randomShort(), loadAverages),
718+
new OsStats.Cpu(randomShort(), loadAverages, randomInt()),
715719
new OsStats.Mem(memTotal, randomLongBetween(0, memTotal), randomLongBetween(0, memTotal)),
716720
new OsStats.Swap(swapTotal, randomLongBetween(0, swapTotal)),
717721
new OsStats.Cgroup(

0 commit comments

Comments
 (0)