diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml
index 2e1bf07..0afe4b0 100644
--- a/.idea/jarRepositories.xml
+++ b/.idea/jarRepositories.xml
@@ -6,6 +6,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index e9f44dd..9056994 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
cn.langpy
ko-time
- 2.4.3
+ 2.4.4
KoTime
A springboot tool for tracking the paths of the methods,which can help you find method's performances easily.
diff --git a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java
index de62f6e..42daedb 100644
--- a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java
+++ b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java
@@ -25,6 +25,8 @@ import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import static cn.langpy.kotime.model.ThreadInfo.COMPARATOR;
+
/**
* zhangchang
*/
@@ -372,7 +374,7 @@ public class KoTimeController {
public Map getThreadsInfo(String state) {
ThreadUsageService usageService = ThreadUsageService.newInstance();
List threads = usageService.getThreads();
- threads = threads.stream().sorted(Comparator.comparing(ThreadInfo::getState)).collect(Collectors.toList());
+ threads = threads.stream().sorted(COMPARATOR).collect(Collectors.toList());
Map stateCounting = threads.stream().collect(Collectors.groupingBy(ThreadInfo::getState, Collectors.counting()));
stateCounting.put("all",(long)threads.size());
diff --git a/src/main/java/cn/langpy/kotime/model/ThreadInfo.java b/src/main/java/cn/langpy/kotime/model/ThreadInfo.java
index 2ce9845..5b8b888 100644
--- a/src/main/java/cn/langpy/kotime/model/ThreadInfo.java
+++ b/src/main/java/cn/langpy/kotime/model/ThreadInfo.java
@@ -1,8 +1,13 @@
package cn.langpy.kotime.model;
+import java.math.BigDecimal;
+import java.util.Comparator;
import java.util.List;
public class ThreadInfo {
+
+ public static final ThreadInfoComparator COMPARATOR = new ThreadInfoComparator();
+
private Long id;
private String name;
private String classType;
@@ -10,6 +15,7 @@ public class ThreadInfo {
private Boolean isInterrupted;
private Boolean isDaemon;
private Integer priority;
+ private BigDecimal cpuUsage;
private List stacks;
public Long getId() {
@@ -68,6 +74,14 @@ public class ThreadInfo {
this.priority = priority;
}
+ public BigDecimal getCpuUsage() {
+ return cpuUsage;
+ }
+
+ public void setCpuUsage(BigDecimal cpuUsage) {
+ this.cpuUsage = cpuUsage;
+ }
+
public List getStacks() {
return stacks;
}
@@ -75,4 +89,18 @@ public class ThreadInfo {
public void setStacks(List stacks) {
this.stacks = stacks;
}
+
+ /**
+ * 状态码排序 + CPU使用率倒排
+ */
+ public static class ThreadInfoComparator implements Comparator {
+ @Override
+ public int compare(ThreadInfo a, ThreadInfo b) {
+ if (a.getState().compareTo(b.getState()) == 0 ) {
+ return b.getCpuUsage().compareTo(a.getCpuUsage());
+ }
+ return a.getState().compareTo(b.getState());
+ }
+ }
+
}
diff --git a/src/main/java/cn/langpy/kotime/service/ThreadUsageService.java b/src/main/java/cn/langpy/kotime/service/ThreadUsageService.java
index 04ae1f6..94d59c3 100644
--- a/src/main/java/cn/langpy/kotime/service/ThreadUsageService.java
+++ b/src/main/java/cn/langpy/kotime/service/ThreadUsageService.java
@@ -1,9 +1,16 @@
package cn.langpy.kotime.service;
import cn.langpy.kotime.model.ThreadInfo;
+import cn.langpy.kotime.util.Context;
+import org.springframework.util.CollectionUtils;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadMXBean;
+import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@@ -17,6 +24,7 @@ public class ThreadUsageService {
public List getThreads() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
+ ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();;
int activeCount = threadGroup.activeCount();
Thread[] threads = new Thread[activeCount];
threadGroup.enumerate(threads);
@@ -25,6 +33,8 @@ public class ThreadUsageService {
Thread thread = threads[i];
ThreadInfo threadInfo = new ThreadInfo();
threadInfo.setId(thread.getId());
+ threadInfo.setCpuUsage(BigDecimal.valueOf(threadMXBean.getThreadCpuTime(thread.getId()))
+ .divide(BigDecimal.valueOf(threadMXBean.getThreadUserTime(thread.getId())), 2, BigDecimal.ROUND_HALF_UP));
threadInfo.setName(thread.getName());
threadInfo.setClassType(thread.getClass().getSimpleName());
threadInfo.setState(thread.getState().name());
@@ -35,6 +45,7 @@ public class ThreadUsageService {
threadInfo.setStacks(Arrays.stream(stackTrace).collect(Collectors.toList()));
list.add(threadInfo);
}
+ Collections.sort(list, Comparator.comparing(ThreadInfo::getCpuUsage).reversed());
return list;
}
diff --git a/src/main/resources/kotime-en.html b/src/main/resources/kotime-en.html
index d7b1e93..38cfbe9 100644
--- a/src/main/resources/kotime-en.html
+++ b/src/main/resources/kotime-en.html
@@ -553,6 +553,22 @@
}
});
}
+
+ const cpuUsageColorMap = {
+ 'RED': '#cc0c0c',
+ 'YELLOW': '#f0ad4e',
+ 'LIGHT_BLUE': '#5bc0de'
+ };
+ function getCpuUsageColor(usage) {
+ if (usage > 50) {
+ return cpuUsageColorMap['RED'];
+ } else if (usage >= 20 && usage <= 50) {
+ return cpuUsageColorMap['YELLOW'];
+ } else {
+ return cpuUsageColorMap['LIGHT_BLUE'];
+ }
+ }
+
let threadMap = new Map();
function loadThreadsInfo(queryState) {
queryState = queryState || '';
@@ -586,8 +602,10 @@
let classType = thread['classType'];
let state = thread['state'];
let stacks = thread['stacks'];
+ let cpuUsage = thread['cpuUsage'];
+ let cpuUsageColor = getCpuUsageColor(cpuUsage);
threadMap[id+''] = stacks;
- html+=`id=${id} name=${name} class=${classType} ${state}`;
+ html+=`id=${id} name=${name} class=${classType} CPU-UsagePercent:${cpuUsage}% ${state}`;
}
element.innerHTML = html;
});
diff --git a/src/main/resources/kotime.html b/src/main/resources/kotime.html
index 77b7358..48892c4 100644
--- a/src/main/resources/kotime.html
+++ b/src/main/resources/kotime.html
@@ -546,6 +546,21 @@
});
}
+ const cpuUsageColorMap = {
+ 'RED': '#cc0c0c',
+ 'YELLOW': '#f0ad4e',
+ 'LIGHT_BLUE': '#5bc0de'
+ };
+ function getCpuUsageColor(usage) {
+ if (usage > 50) {
+ return cpuUsageColorMap['RED'];
+ } else if (usage >= 20 && usage <= 50) {
+ return cpuUsageColorMap['YELLOW'];
+ } else {
+ return cpuUsageColorMap['LIGHT_BLUE'];
+ }
+ }
+
let threadMap = new Map();
function loadThreadsInfo(queryState) {
queryState = queryState || '';
@@ -579,8 +594,10 @@
let classType = thread['classType'];
let state = thread['state'];
let stacks = thread['stacks'];
+ let cpuUsage = thread['cpuUsage'];
+ let cpuUsageColor = getCpuUsageColor(cpuUsage);
threadMap[id+''] = stacks;
- html+=`id=${id} name=${name} class=${classType} ${state}`;
+ html+=`id=${id} name=${name} class=${classType} CPU使用率:${cpuUsage}% ${state}`;
}
element.innerHTML = html;
});