mirror of
https://gitee.com/huoyo/ko-time.git
synced 2025-12-06 08:48:30 +08:00
feature-addThreadCpuUsage (#1)
* 增加线程的CPU使用率 * 修改版本号 * 增加排序 --------- Co-authored-by: zhaoxiang <zhaoxiang@tianyancha.com>
This commit is contained in:
parent
fb7c64cde7
commit
427d99f93e
10
.idea/jarRepositories.xml
generated
10
.idea/jarRepositories.xml
generated
@ -6,6 +6,16 @@
|
|||||||
<option name="name" value="Central Repository" />
|
<option name="name" value="Central Repository" />
|
||||||
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
<option name="url" value="https://repo.maven.apache.org/maven2" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="central" />
|
||||||
|
<option name="name" value="Central Repository" />
|
||||||
|
<option name="url" value="http://maven.jindidata.com/nexus/content/groups/public/" />
|
||||||
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="nexus" />
|
||||||
|
<option name="name" value="Nexus" />
|
||||||
|
<option name="url" value="http://maven.jindidata.com/nexus/content/groups/public/" />
|
||||||
|
</remote-repository>
|
||||||
<remote-repository>
|
<remote-repository>
|
||||||
<option name="id" value="central" />
|
<option name="id" value="central" />
|
||||||
<option name="name" value="Maven Central repository" />
|
<option name="name" value="Maven Central repository" />
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>cn.langpy</groupId>
|
<groupId>cn.langpy</groupId>
|
||||||
<artifactId>ko-time</artifactId>
|
<artifactId>ko-time</artifactId>
|
||||||
<version>2.4.3</version>
|
<version>2.4.4</version>
|
||||||
<name>KoTime</name>
|
<name>KoTime</name>
|
||||||
<description>A springboot tool for tracking the paths of the methods,which can help you find method's performances easily.</description>
|
<description>A springboot tool for tracking the paths of the methods,which can help you find method's performances easily.</description>
|
||||||
<licenses>
|
<licenses>
|
||||||
|
|||||||
@ -25,6 +25,8 @@ import java.util.*;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static cn.langpy.kotime.model.ThreadInfo.COMPARATOR;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zhangchang
|
* zhangchang
|
||||||
*/
|
*/
|
||||||
@ -372,7 +374,7 @@ public class KoTimeController {
|
|||||||
public Map getThreadsInfo(String state) {
|
public Map getThreadsInfo(String state) {
|
||||||
ThreadUsageService usageService = ThreadUsageService.newInstance();
|
ThreadUsageService usageService = ThreadUsageService.newInstance();
|
||||||
List<ThreadInfo> threads = usageService.getThreads();
|
List<ThreadInfo> threads = usageService.getThreads();
|
||||||
threads = threads.stream().sorted(Comparator.comparing(ThreadInfo::getState)).collect(Collectors.toList());
|
threads = threads.stream().sorted(COMPARATOR).collect(Collectors.toList());
|
||||||
|
|
||||||
Map<String, Long> stateCounting = threads.stream().collect(Collectors.groupingBy(ThreadInfo::getState, Collectors.counting()));
|
Map<String, Long> stateCounting = threads.stream().collect(Collectors.groupingBy(ThreadInfo::getState, Collectors.counting()));
|
||||||
stateCounting.put("all",(long)threads.size());
|
stateCounting.put("all",(long)threads.size());
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
package cn.langpy.kotime.model;
|
package cn.langpy.kotime.model;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ThreadInfo {
|
public class ThreadInfo {
|
||||||
|
|
||||||
|
public static final ThreadInfoComparator COMPARATOR = new ThreadInfoComparator();
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private String classType;
|
private String classType;
|
||||||
@ -10,6 +15,7 @@ public class ThreadInfo {
|
|||||||
private Boolean isInterrupted;
|
private Boolean isInterrupted;
|
||||||
private Boolean isDaemon;
|
private Boolean isDaemon;
|
||||||
private Integer priority;
|
private Integer priority;
|
||||||
|
private BigDecimal cpuUsage;
|
||||||
private List<StackTraceElement> stacks;
|
private List<StackTraceElement> stacks;
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
@ -68,6 +74,14 @@ public class ThreadInfo {
|
|||||||
this.priority = priority;
|
this.priority = priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BigDecimal getCpuUsage() {
|
||||||
|
return cpuUsage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCpuUsage(BigDecimal cpuUsage) {
|
||||||
|
this.cpuUsage = cpuUsage;
|
||||||
|
}
|
||||||
|
|
||||||
public List<StackTraceElement> getStacks() {
|
public List<StackTraceElement> getStacks() {
|
||||||
return stacks;
|
return stacks;
|
||||||
}
|
}
|
||||||
@ -75,4 +89,18 @@ public class ThreadInfo {
|
|||||||
public void setStacks(List<StackTraceElement> stacks) {
|
public void setStacks(List<StackTraceElement> stacks) {
|
||||||
this.stacks = stacks;
|
this.stacks = stacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 状态码排序 + CPU使用率倒排
|
||||||
|
*/
|
||||||
|
public static class ThreadInfoComparator implements Comparator<ThreadInfo> {
|
||||||
|
@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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,16 @@
|
|||||||
package cn.langpy.kotime.service;
|
package cn.langpy.kotime.service;
|
||||||
|
|
||||||
import cn.langpy.kotime.model.ThreadInfo;
|
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.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -17,6 +24,7 @@ public class ThreadUsageService {
|
|||||||
|
|
||||||
public List<ThreadInfo> getThreads() {
|
public List<ThreadInfo> getThreads() {
|
||||||
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
|
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
|
||||||
|
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();;
|
||||||
int activeCount = threadGroup.activeCount();
|
int activeCount = threadGroup.activeCount();
|
||||||
Thread[] threads = new Thread[activeCount];
|
Thread[] threads = new Thread[activeCount];
|
||||||
threadGroup.enumerate(threads);
|
threadGroup.enumerate(threads);
|
||||||
@ -25,6 +33,8 @@ public class ThreadUsageService {
|
|||||||
Thread thread = threads[i];
|
Thread thread = threads[i];
|
||||||
ThreadInfo threadInfo = new ThreadInfo();
|
ThreadInfo threadInfo = new ThreadInfo();
|
||||||
threadInfo.setId(thread.getId());
|
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.setName(thread.getName());
|
||||||
threadInfo.setClassType(thread.getClass().getSimpleName());
|
threadInfo.setClassType(thread.getClass().getSimpleName());
|
||||||
threadInfo.setState(thread.getState().name());
|
threadInfo.setState(thread.getState().name());
|
||||||
@ -35,6 +45,7 @@ public class ThreadUsageService {
|
|||||||
threadInfo.setStacks(Arrays.stream(stackTrace).collect(Collectors.toList()));
|
threadInfo.setStacks(Arrays.stream(stackTrace).collect(Collectors.toList()));
|
||||||
list.add(threadInfo);
|
list.add(threadInfo);
|
||||||
}
|
}
|
||||||
|
Collections.sort(list, Comparator.comparing(ThreadInfo::getCpuUsage).reversed());
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
let threadMap = new Map();
|
||||||
function loadThreadsInfo(queryState) {
|
function loadThreadsInfo(queryState) {
|
||||||
queryState = queryState || '';
|
queryState = queryState || '';
|
||||||
@ -586,8 +602,10 @@
|
|||||||
let classType = thread['classType'];
|
let classType = thread['classType'];
|
||||||
let state = thread['state'];
|
let state = thread['state'];
|
||||||
let stacks = thread['stacks'];
|
let stacks = thread['stacks'];
|
||||||
|
let cpuUsage = thread['cpuUsage'];
|
||||||
|
let cpuUsageColor = getCpuUsageColor(cpuUsage);
|
||||||
threadMap[id+''] = stacks;
|
threadMap[id+''] = stacks;
|
||||||
html+=`<li onclick="showThreadInfo('${id}')" style='color: #333;font-weight: 400;font-size: 14px;'>id=<span style="font-size: 16px;font-weight: 500;">${id}</span> name=${name} class=${classType} <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span></li>`;
|
html+=`<li onclick="showThreadInfo('${id}')" style='color: #333;font-weight: 400;font-size: 14px;'>id=<span style="font-size: 16px;font-weight: 500;">${id}</span> name=${name} class=${classType} <span style="font-size: 10px;background-color: ${cpuUsageColor};" class="uk-label uk-label-success">CPU-UsagePercent:${cpuUsage}%</span> <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span></li>`;
|
||||||
}
|
}
|
||||||
element.innerHTML = html;
|
element.innerHTML = 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();
|
let threadMap = new Map();
|
||||||
function loadThreadsInfo(queryState) {
|
function loadThreadsInfo(queryState) {
|
||||||
queryState = queryState || '';
|
queryState = queryState || '';
|
||||||
@ -579,8 +594,10 @@
|
|||||||
let classType = thread['classType'];
|
let classType = thread['classType'];
|
||||||
let state = thread['state'];
|
let state = thread['state'];
|
||||||
let stacks = thread['stacks'];
|
let stacks = thread['stacks'];
|
||||||
|
let cpuUsage = thread['cpuUsage'];
|
||||||
|
let cpuUsageColor = getCpuUsageColor(cpuUsage);
|
||||||
threadMap[id+''] = stacks;
|
threadMap[id+''] = stacks;
|
||||||
html+=`<li onclick="showThreadInfo('${id}')" style='color: #333;font-weight: 400;font-size: 14px;'>id=<span style="font-size: 16px;font-weight: 500;">${id}</span> name=${name} class=${classType} <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span></li>`;
|
html+=`<li onclick="showThreadInfo('${id}')" style='color: #333;font-weight: 400;font-size: 14px;'>id=<span style="font-size: 16px;font-weight: 500;">${id}</span> name=${name} class=${classType} <span style="font-size: 10px;background-color: ${cpuUsageColor};" class="uk-label uk-label-success">CPU使用率:${cpuUsage}%</span> <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span></li>`;
|
||||||
}
|
}
|
||||||
element.innerHTML = html;
|
element.innerHTML = html;
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user