Skip to content

Commit b6439c5

Browse files
authored
Add other time accounting in HotThreads (#79392)
Currently, the HotThreads CPU report contains only the CPU cycles that a thread executes, excluding time spent in I/O or the JVM runtime (e.g. GC). This PR introduces the 'other' time accounting to augment the CPU time for better understanding of user visible time impact.
1 parent ceaf53c commit b6439c5

File tree

9 files changed

+488
-223
lines changed

9 files changed

+488
-223
lines changed

server/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
package org.elasticsearch.action.admin.cluster.node.hotthreads;
1010

11+
import org.elasticsearch.Version;
1112
import org.elasticsearch.action.support.nodes.BaseNodesRequest;
1213
import org.elasticsearch.cluster.node.DiscoveryNode;
1314
import org.elasticsearch.common.io.stream.StreamInput;
@@ -22,6 +23,7 @@ public class NodesHotThreadsRequest extends BaseNodesRequest<NodesHotThreadsRequ
2223

2324
int threads = 3;
2425
HotThreads.ReportType type = HotThreads.ReportType.CPU;
26+
HotThreads.SortOrder sortOrder = HotThreads.SortOrder.TOTAL;
2527
TimeValue interval = new TimeValue(500, TimeUnit.MILLISECONDS);
2628
int snapshots = 10;
2729
boolean ignoreIdleThreads = true;
@@ -34,6 +36,9 @@ public NodesHotThreadsRequest(StreamInput in) throws IOException {
3436
type = HotThreads.ReportType.of(in.readString());
3537
interval = in.readTimeValue();
3638
snapshots = in.readInt();
39+
if (in.getVersion().onOrAfter(Version.V_8_0_0)) {
40+
sortOrder = HotThreads.SortOrder.of(in.readString());
41+
}
3742
}
3843

3944
/**
@@ -78,6 +83,15 @@ public HotThreads.ReportType type() {
7883
return this.type;
7984
}
8085

86+
public NodesHotThreadsRequest sortOrder(HotThreads.SortOrder sortOrder) {
87+
this.sortOrder = sortOrder;
88+
return this;
89+
}
90+
91+
public HotThreads.SortOrder sortOrder() {
92+
return this.sortOrder;
93+
}
94+
8195
public NodesHotThreadsRequest interval(TimeValue interval) {
8296
this.interval = interval;
8397
return this;
@@ -104,5 +118,8 @@ public void writeTo(StreamOutput out) throws IOException {
104118
out.writeString(type.getTypeValue());
105119
out.writeTimeValue(interval);
106120
out.writeInt(snapshots);
121+
if (out.getVersion().onOrAfter(Version.V_8_0_0)) {
122+
out.writeString(sortOrder.getOrderValue());
123+
}
107124
}
108125
}

server/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequestBuilder.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ public NodesHotThreadsRequestBuilder setType(HotThreads.ReportType type) {
3535
return this;
3636
}
3737

38+
public NodesHotThreadsRequestBuilder setSortOrder(HotThreads.SortOrder sortOrder) {
39+
request.sortOrder(sortOrder);
40+
return this;
41+
}
42+
3843
public NodesHotThreadsRequestBuilder setInterval(TimeValue interval) {
3944
request.interval(interval);
4045
return this;

server/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/TransportNodesHotThreadsAction.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ protected NodeHotThreads nodeOperation(NodeRequest request, Task task) {
5959
HotThreads hotThreads = new HotThreads()
6060
.busiestThreads(request.request.threads)
6161
.type(request.request.type)
62+
.sortOrder(request.request.sortOrder)
6263
.interval(request.request.interval)
6364
.threadElementsSnapshotCount(request.request.snapshots)
6465
.ignoreIdleThreads(request.request.ignoreIdleThreads);

server/src/main/java/org/elasticsearch/bootstrap/Bootstrap.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.elasticsearch.core.internal.io.IOUtils;
3232
import org.elasticsearch.env.Environment;
3333
import org.elasticsearch.jdk.JarHell;
34+
import org.elasticsearch.monitor.jvm.HotThreads;
3435
import org.elasticsearch.monitor.jvm.JvmInfo;
3536
import org.elasticsearch.monitor.os.OsProbe;
3637
import org.elasticsearch.monitor.process.ProcessProbe;
@@ -156,6 +157,7 @@ static void initializeProbes() {
156157
ProcessProbe.getInstance();
157158
OsProbe.getInstance();
158159
JvmInfo.jvmInfo();
160+
HotThreads.initializeRuntimeMonitoring();
159161
}
160162

161163
private void setup(boolean addShutdownHook, Environment environment) throws BootstrapException {

server/src/main/java/org/elasticsearch/monitor/jvm/HotThreads.java

Lines changed: 202 additions & 88 deletions
Large diffs are not rendered by default.

server/src/main/java/org/elasticsearch/rest/action/admin/cluster/RestNodesHotThreadsAction.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,13 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
9191
String[] nodesIds = Strings.splitStringByCommaToArray(request.param("nodeId"));
9292
NodesHotThreadsRequest nodesHotThreadsRequest = new NodesHotThreadsRequest(nodesIds);
9393
nodesHotThreadsRequest.threads(request.paramAsInt("threads", nodesHotThreadsRequest.threads()));
94-
nodesHotThreadsRequest.ignoreIdleThreads(request.paramAsBoolean("ignore_idle_threads", nodesHotThreadsRequest.ignoreIdleThreads()));
94+
nodesHotThreadsRequest.ignoreIdleThreads(
95+
request.paramAsBoolean("ignore_idle_threads", nodesHotThreadsRequest.ignoreIdleThreads()));
9596
nodesHotThreadsRequest.type(HotThreads.ReportType.of(request.param("type", nodesHotThreadsRequest.type().getTypeValue())));
96-
nodesHotThreadsRequest.interval(TimeValue.parseTimeValue(request.param("interval"), nodesHotThreadsRequest.interval(), "interval"));
97+
nodesHotThreadsRequest.sortOrder(
98+
HotThreads.SortOrder.of(request.param("sort", nodesHotThreadsRequest.sortOrder().getOrderValue())));
99+
nodesHotThreadsRequest.interval(
100+
TimeValue.parseTimeValue(request.param("interval"), nodesHotThreadsRequest.interval(), "interval"));
97101
nodesHotThreadsRequest.snapshots(request.paramAsInt("snapshots", nodesHotThreadsRequest.snapshots()));
98102
nodesHotThreadsRequest.timeout(request.param("timeout"));
99103
return channel -> client.admin().cluster().nodesHotThreads(

server/src/main/resources/org/elasticsearch/bootstrap/security.policy

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@ grant codeBase "${codebase.elasticsearch-secure-sm}" {
2222
grant codeBase "${codebase.elasticsearch}" {
2323
// needed for loading plugins which may expect the context class loader to be set
2424
permission java.lang.RuntimePermission "setContextClassLoader";
25-
// needed by HotThreads to enable wait/block time accounting on demand
26-
permission java.lang.management.ManagementPermission "control";
2725
};
2826

2927
//// Very special jar permissions:

server/src/test/java/org/elasticsearch/action/admin/cluster/hotthreads/NodesHotThreadsRequestTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void testBWCSerialization() throws IOException {
5555
out.setVersion(previous);
5656
request.writeTo(out);
5757
try (StreamInput in = out.bytes().streamInput()) {
58-
in.setVersion(latest);
58+
in.setVersion(previous);
5959
NodesHotThreadsRequest deserialized = new NodesHotThreadsRequest(in);
6060
assertEquals(request.threads(), deserialized.threads());
6161
assertEquals(request.ignoreIdleThreads(), deserialized.ignoreIdleThreads());

0 commit comments

Comments
 (0)