Skip to content

Commit 32decb6

Browse files
committed
<feature>[core]: add APIShowPoolStatus API for thread pool and task queue monitoring
Resolves: ZSTAC-68709 Change-Id: Iee14ef5d21c216e91312ac40a46be80222244fbb
1 parent 5617897 commit 32decb6

4 files changed

Lines changed: 161 additions & 1 deletion

File tree

core/src/main/java/org/zstack/core/CoreManagerImpl.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import org.zstack.core.singleflight.ExternalSingleFlightMsg;
99
import org.zstack.core.singleflight.ExternalSingleFlightReply;
1010
import org.zstack.core.singleflight.MultiNodeSingleFlightImpl;
11-
import org.zstack.core.thread.ThreadFacade;
11+
import org.zstack.core.thread.*;
1212
import org.zstack.header.AbstractService;
1313
import org.zstack.header.core.*;
1414
import org.zstack.header.core.progress.ChainInfo;
@@ -41,6 +41,8 @@ public class CoreManagerImpl extends AbstractService implements CoreManager {
4141
@Autowired
4242
private ThreadFacade thdf;
4343
@Autowired
44+
private DispatchQueue dpq;
45+
@Autowired
4446
private MultiNodeSingleFlightImpl singleFlight;
4547

4648
@Override
@@ -55,6 +57,8 @@ public void handleMessage(Message msg) {
5557
private void handleApiMessage(APIMessage msg) {
5658
if (msg instanceof APIGetChainTaskMsg) {
5759
handleMessage((APIGetChainTaskMsg) msg);
60+
} else if (msg instanceof APIShowPoolStatusMsg) {
61+
handleMessage((APIShowPoolStatusMsg) msg);
5862
}
5963
}
6064

@@ -134,6 +138,43 @@ public void done(ErrorCodeList errorCodeList) {
134138
});
135139
}
136140

141+
private void handleMessage(APIShowPoolStatusMsg msg) {
142+
APIShowPoolStatusReply reply = new APIShowPoolStatusReply();
143+
144+
// Thread pool stats
145+
if (thdf instanceof ThreadFacadeMXBean) {
146+
ThreadPoolStatistic tps = ((ThreadFacadeMXBean) thdf).getThreadPoolStatistic();
147+
reply.addEntry(new PoolStatusEntry("main-thread-pool", "ThreadPool",
148+
tps.getActiveThreadNum(), (int) tps.getQueuedTaskNum(), (int) tps.getMaxPoolSize()));
149+
}
150+
151+
// Chain task stats (top 20 by pending)
152+
Map<String, ChainTaskStatistic> chainStats = dpq.getChainTaskStatistics();
153+
chainStats.entrySet().stream()
154+
.sorted((a, b) -> Long.compare(b.getValue().getPendingTaskNum(), a.getValue().getPendingTaskNum()))
155+
.limit(20)
156+
.forEach(e -> {
157+
ChainTaskStatistic s = e.getValue();
158+
reply.addEntry(new PoolStatusEntry(
159+
"chain:" + e.getKey(), "ChainTask",
160+
s.getCurrentRunningThreadNum(), (int) s.getPendingTaskNum(), s.getSyncLevel()));
161+
});
162+
163+
// Sync task stats (top 20 by pending)
164+
Map<String, SyncTaskStatistic> syncStats = dpq.getSyncTaskStatistics();
165+
syncStats.entrySet().stream()
166+
.sorted((a, b) -> Long.compare(b.getValue().getPendingTaskNum(), a.getValue().getPendingTaskNum()))
167+
.limit(20)
168+
.forEach(e -> {
169+
SyncTaskStatistic s = e.getValue();
170+
reply.addEntry(new PoolStatusEntry(
171+
"sync:" + e.getKey(), "SyncTask",
172+
s.getCurrentRunningThreadNum(), (int) s.getPendingTaskNum(), s.getSyncLevel()));
173+
});
174+
175+
bus.reply(msg, reply);
176+
}
177+
137178
private void handle(GetLocalTaskMsg msg) {
138179
GetLocalTaskReply reply = new GetLocalTaskReply();
139180
Map<String, ChainInfo> results = msg.getSyncSignatures().stream()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.zstack.header.core;
2+
3+
import org.springframework.http.HttpMethod;
4+
import org.zstack.header.identity.Action;
5+
import org.zstack.header.message.APISyncCallMessage;
6+
import org.zstack.header.rest.RestRequest;
7+
8+
@Action(category = CoreConstant.ACTION_CATEGORY, adminOnly = true)
9+
@RestRequest(
10+
path = "/core/pool-status",
11+
method = HttpMethod.GET,
12+
responseClass = APIShowPoolStatusReply.class
13+
)
14+
public class APIShowPoolStatusMsg extends APISyncCallMessage {
15+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.zstack.header.core;
2+
3+
import org.zstack.header.message.APIReply;
4+
import org.zstack.header.rest.RestResponse;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
9+
@RestResponse(fieldsTo = {"all"})
10+
public class APIShowPoolStatusReply extends APIReply {
11+
private List<PoolStatusEntry> entries = new ArrayList<>();
12+
13+
public List<PoolStatusEntry> getEntries() {
14+
return entries;
15+
}
16+
17+
public void setEntries(List<PoolStatusEntry> entries) {
18+
this.entries = entries;
19+
}
20+
21+
public void addEntry(PoolStatusEntry entry) {
22+
entries.add(entry);
23+
}
24+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package org.zstack.header.core;
2+
3+
public class PoolStatusEntry {
4+
private String name;
5+
private String poolType;
6+
private int active;
7+
private int pending;
8+
private int max;
9+
private double utilization;
10+
private String status;
11+
12+
public PoolStatusEntry() {
13+
}
14+
15+
public PoolStatusEntry(String name, String poolType, int active, int pending, int max) {
16+
this.name = name;
17+
this.poolType = poolType;
18+
this.active = active;
19+
this.pending = pending;
20+
this.max = max;
21+
this.utilization = max > 0 ? (double) active * 100 / max : 0;
22+
this.status = utilization >= 80 ? "CRITICAL" : utilization >= 60 ? "WARNING" : "OK";
23+
}
24+
25+
public String getName() {
26+
return name;
27+
}
28+
29+
public void setName(String name) {
30+
this.name = name;
31+
}
32+
33+
public String getPoolType() {
34+
return poolType;
35+
}
36+
37+
public void setPoolType(String poolType) {
38+
this.poolType = poolType;
39+
}
40+
41+
public int getActive() {
42+
return active;
43+
}
44+
45+
public void setActive(int active) {
46+
this.active = active;
47+
}
48+
49+
public int getPending() {
50+
return pending;
51+
}
52+
53+
public void setPending(int pending) {
54+
this.pending = pending;
55+
}
56+
57+
public int getMax() {
58+
return max;
59+
}
60+
61+
public void setMax(int max) {
62+
this.max = max;
63+
}
64+
65+
public double getUtilization() {
66+
return utilization;
67+
}
68+
69+
public void setUtilization(double utilization) {
70+
this.utilization = utilization;
71+
}
72+
73+
public String getStatus() {
74+
return status;
75+
}
76+
77+
public void setStatus(String status) {
78+
this.status = status;
79+
}
80+
}

0 commit comments

Comments
 (0)