mirror of
https://gitee.com/huoyo/ko-time.git
synced 2025-12-07 01:08:26 +08:00
optimize thread statistics
This commit is contained in:
parent
9fe09cc00d
commit
fd249db452
11
README.md
11
README.md
@ -9,7 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<img src='https://shields.io/badge/version-2.3.7-green.svg'>
|
<img src='https://shields.io/badge/version-2.3.9-green.svg'>
|
||||||
<img src='https://shields.io/badge/author-Chang Zhang-dbab09.svg'>
|
<img src='https://shields.io/badge/author-Chang Zhang-dbab09.svg'>
|
||||||
<img src='https://shields.io/badge/dependencies-Spring|aspectjweaver|tomcat|UIKit|Metricflow-r.svg'>
|
<img src='https://shields.io/badge/dependencies-Spring|aspectjweaver|tomcat|UIKit|Metricflow-r.svg'>
|
||||||
</div>
|
</div>
|
||||||
@ -22,6 +22,7 @@
|
|||||||
- ✅ Find exceptions occurred in methods
|
- ✅ Find exceptions occurred in methods
|
||||||
- ✅ Email you after finding an overtime method
|
- ✅ Email you after finding an overtime method
|
||||||
- ✅ Hot update online:you needn't restart it
|
- ✅ Hot update online:you needn't restart it
|
||||||
|
- ✅ Thread manage:show threads information
|
||||||
- ✅ Easy to use:you needn't additional learning costs
|
- ✅ Easy to use:you needn't additional learning costs
|
||||||
- ✅ Enough to add a pom dependency:you needn't additional deployment costs
|
- ✅ Enough to add a pom dependency:you needn't additional deployment costs
|
||||||
|
|
||||||
@ -35,6 +36,7 @@
|
|||||||
- ✅ 追踪系统异常,精确定位到方法
|
- ✅ 追踪系统异常,精确定位到方法
|
||||||
- ✅ 接口超时邮件通知,无需实时查看
|
- ✅ 接口超时邮件通知,无需实时查看
|
||||||
- ✅ 线上热更新:无需重启更新代码
|
- ✅ 线上热更新:无需重启更新代码
|
||||||
|
- ✅ 线程管理:线程实时统计与状态查看
|
||||||
- ✅ 使用简单,无技术学习成本
|
- ✅ 使用简单,无技术学习成本
|
||||||
- ✅ pom依赖即可,无代码侵入,无多余部署成本
|
- ✅ pom依赖即可,无代码侵入,无多余部署成本
|
||||||
|
|
||||||
@ -87,6 +89,13 @@ v2.2.5开始加入了邮件通知功能,当方法耗时超过阈值之后,
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
5.线程管理
|
||||||
|
|
||||||
|
v2.3.9开始加入了线程管理功能,可以统计线程状态和查看线程堆栈信息
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
## 重要版本说明
|
## 重要版本说明
|
||||||
|
|
||||||
> V1.0:基本功能
|
> V1.0:基本功能
|
||||||
|
|||||||
BIN
docs/v220/xcgl.png
Normal file
BIN
docs/v220/xcgl.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
BIN
docs/v220/xcgl2.png
Normal file
BIN
docs/v220/xcgl2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
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.3.8</version>
|
<version>2.3.9</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>
|
||||||
|
|||||||
@ -21,11 +21,9 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* zhangchang
|
* zhangchang
|
||||||
@ -71,7 +69,7 @@ public class KoTimeController {
|
|||||||
if (StringUtils.hasText(kotoken)) {
|
if (StringUtils.hasText(kotoken)) {
|
||||||
if (kotoken.equals(Context.getConfig().getStaticToken())) {
|
if (kotoken.equals(Context.getConfig().getStaticToken())) {
|
||||||
checkLogin = true;
|
checkLogin = true;
|
||||||
}else {
|
} else {
|
||||||
checkLogin = KoUtil.isLogin(kotoken);
|
checkLogin = KoUtil.isLogin(kotoken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,7 +79,7 @@ public class KoTimeController {
|
|||||||
|
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public void index(String kotoken,String test, HttpServletResponse response, HttpServletRequest request) {
|
public void index(String kotoken, String test, HttpServletResponse response, HttpServletRequest request) {
|
||||||
if (!Context.getConfig().getEnable()) {
|
if (!Context.getConfig().getEnable()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -121,14 +119,14 @@ public class KoTimeController {
|
|||||||
line = line.replace("UIKitJs", uiKitJsText);
|
line = line.replace("UIKitJs", uiKitJsText);
|
||||||
} else if (line.indexOf("MetricFlowJs") > -1) {
|
} else if (line.indexOf("MetricFlowJs") > -1) {
|
||||||
line = line.replace("MetricFlowJs", metricFlowJsText);
|
line = line.replace("MetricFlowJs", metricFlowJsText);
|
||||||
}else if (line.indexOf("jQueryJs") > -1) {
|
} else if (line.indexOf("jQueryJs") > -1) {
|
||||||
line = line.replace("jQueryJs", jQueryJsText);
|
line = line.replace("jQueryJs", jQueryJsText);
|
||||||
}else if (line.indexOf("uiKitIconsJs") > -1) {
|
} else if (line.indexOf("uiKitIconsJs") > -1) {
|
||||||
line = line.replace("uiKitIconsJs", uiKitIconsJs);
|
line = line.replace("uiKitIconsJs", uiKitIconsJs);
|
||||||
}else if (line.indexOf("staticTokenVisitValue") > -1) {
|
} else if (line.indexOf("staticTokenVisitValue") > -1) {
|
||||||
line = line.replace("staticTokenVisitValue", staticTokenVisit+"");
|
line = line.replace("staticTokenVisitValue", staticTokenVisit + "");
|
||||||
}else if (line.indexOf("staticTokenValue") > -1) {
|
} else if (line.indexOf("staticTokenValue") > -1) {
|
||||||
line = line.replace("staticTokenValue", "'"+kotoken+"'");
|
line = line.replace("staticTokenValue", "'" + kotoken + "'");
|
||||||
}
|
}
|
||||||
stringBuilder.append(line + "\n");
|
stringBuilder.append(line + "\n");
|
||||||
}
|
}
|
||||||
@ -139,6 +137,7 @@ public class KoTimeController {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getResourceText(String fileName) {
|
private String getResourceText(String fileName) {
|
||||||
ClassPathResource classPathResource = new ClassPathResource(fileName);
|
ClassPathResource classPathResource = new ClassPathResource(fileName);
|
||||||
try (InputStream inputStream = classPathResource.getInputStream();
|
try (InputStream inputStream = classPathResource.getInputStream();
|
||||||
@ -229,9 +228,9 @@ public class KoTimeController {
|
|||||||
@GetMapping("/getMethodsByExceptionId")
|
@GetMapping("/getMethodsByExceptionId")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@Auth
|
@Auth
|
||||||
public List<ExceptionInfo> getMethodsByExceptionId(String exceptionId,String message) {
|
public List<ExceptionInfo> getMethodsByExceptionId(String exceptionId, String message) {
|
||||||
GraphService graphService = GraphService.getInstance();
|
GraphService graphService = GraphService.getInstance();
|
||||||
List<ExceptionInfo> exceptionInfos = graphService.getExceptionInfos(exceptionId,message);
|
List<ExceptionInfo> exceptionInfos = graphService.getExceptionInfos(exceptionId, message);
|
||||||
return exceptionInfos;
|
return exceptionInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,12 +256,13 @@ public class KoTimeController {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/updateClass")
|
@PostMapping("/updateClass")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@Auth
|
@Auth
|
||||||
public Map updateClass(@RequestParam("classFile") MultipartFile classFile,String className) {
|
public Map updateClass(@RequestParam("classFile") MultipartFile classFile, String className) {
|
||||||
Map map = new HashMap();
|
Map map = new HashMap();
|
||||||
if (classFile==null || classFile.isEmpty()) {
|
if (classFile == null || classFile.isEmpty()) {
|
||||||
map.put("state", 0);
|
map.put("state", 0);
|
||||||
map.put("message", "文件不能为空");
|
map.put("message", "文件不能为空");
|
||||||
return map;
|
return map;
|
||||||
@ -288,7 +288,7 @@ public class KoTimeController {
|
|||||||
map.put("message", "请确认类名是否正确");
|
map.put("message", "请确认类名是否正确");
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
file = uploadFile(classFile.getBytes(),filename[0]);
|
file = uploadFile(classFile.getBytes(), filename[0]);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.severe("Error class file!");
|
log.severe("Error class file!");
|
||||||
map.put("state", 0);
|
map.put("state", 0);
|
||||||
@ -296,7 +296,7 @@ public class KoTimeController {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
final ClassService classService = ClassService.getInstance();
|
final ClassService classService = ClassService.getInstance();
|
||||||
classService.updateClass(className,file.getAbsolutePath());
|
classService.updateClass(className, file.getAbsolutePath());
|
||||||
file.deleteOnExit();
|
file.deleteOnExit();
|
||||||
|
|
||||||
map.put("state", 1);
|
map.put("state", 1);
|
||||||
@ -305,19 +305,18 @@ public class KoTimeController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static File uploadFile(byte[] file, String fileName) throws IOException {
|
||||||
private static File uploadFile(byte[] file,String fileName) throws IOException {
|
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
File targetFile = File.createTempFile(fileName, ".class", new File(System.getProperty("java.io.tmpdir")));
|
File targetFile = File.createTempFile(fileName, ".class", new File(System.getProperty("java.io.tmpdir")));
|
||||||
out = new FileOutputStream(targetFile.getAbsolutePath());
|
out = new FileOutputStream(targetFile.getAbsolutePath());
|
||||||
out.write(file);
|
out.write(file);
|
||||||
out.flush();
|
out.flush();
|
||||||
return targetFile;
|
return targetFile;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.severe("" + e);
|
log.severe("" + e);
|
||||||
}finally {
|
} finally {
|
||||||
if(out !=null){
|
if (out != null) {
|
||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
@ -342,6 +341,7 @@ public class KoTimeController {
|
|||||||
HeapMemoryInfo heapMemoryInfo = usageService.getHeapMemoryInfo();
|
HeapMemoryInfo heapMemoryInfo = usageService.getHeapMemoryInfo();
|
||||||
return heapMemoryInfo;
|
return heapMemoryInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/getPhysicalMemoryInfo")
|
@GetMapping("/getPhysicalMemoryInfo")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@Auth
|
@Auth
|
||||||
@ -363,9 +363,20 @@ public class KoTimeController {
|
|||||||
@GetMapping("/getThreadsInfo")
|
@GetMapping("/getThreadsInfo")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@Auth
|
@Auth
|
||||||
public List getThreadsInfo() {
|
public Map getThreadsInfo(String state) {
|
||||||
ThreadUsageService usageService = ThreadUsageService.newInstance();
|
ThreadUsageService usageService = ThreadUsageService.newInstance();
|
||||||
List<ThreadInfo> threads = usageService.getThreads();
|
List<ThreadInfo> threads = usageService.getThreads();
|
||||||
return threads;
|
threads = threads.stream().sorted(Comparator.comparing(ThreadInfo::getState)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
Map<String, Long> stateCounting = threads.stream().collect(Collectors.groupingBy(ThreadInfo::getState, Collectors.counting()));
|
||||||
|
stateCounting.put("all",(long)threads.size());
|
||||||
|
|
||||||
|
Map map = new HashMap();
|
||||||
|
map.put("statistics", stateCounting);
|
||||||
|
if (StringUtils.hasText(state)) {
|
||||||
|
threads = threads.stream().filter(a -> a.getState().equals(state)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
map.put("threads", threads);
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,4 +37,9 @@ public class ThreadUsageService {
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ThreadInfo> getThreads(String state) {
|
||||||
|
List<ThreadInfo> threads = getThreads();
|
||||||
|
return threads.stream().filter(a -> a.getState().equals(state)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -505,9 +505,68 @@
|
|||||||
loadCpuInfo();
|
loadCpuInfo();
|
||||||
loadHeapMemoryInfo();
|
loadHeapMemoryInfo();
|
||||||
loadPhysicalMemoryInfo();
|
loadPhysicalMemoryInfo();
|
||||||
|
loadThreadsInfo();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
let threadMap = new Map();
|
||||||
|
function loadThreadsInfo(queryState) {
|
||||||
|
queryState = queryState || '';
|
||||||
|
$.get(concatToken('contextPath/koTime/getThreadsInfo?state='+queryState), function (data) {
|
||||||
|
let statistics = data['statistics'];
|
||||||
|
let all = statistics['all'];
|
||||||
|
let RUNNABLE = statistics['RUNNABLE'] || 0;
|
||||||
|
let BLOCKED = statistics['BLOCKED'] || 0;
|
||||||
|
let WAITING = statistics['WAITING'] || 0;
|
||||||
|
let TIMED_WAITING = statistics['TIMED_WAITING'] || 0;
|
||||||
|
|
||||||
|
document.querySelector("#threadNum").innerHTML = all;
|
||||||
|
document.querySelector("#runnableNum").innerHTML = RUNNABLE;
|
||||||
|
document.querySelector("#blockedNum").innerHTML = BLOCKED;
|
||||||
|
document.querySelector("#waitingNum").innerHTML = WAITING;
|
||||||
|
document.querySelector("#timedWaitingNum").innerHTML = TIMED_WAITING;
|
||||||
|
|
||||||
|
let element = document.getElementById('threadList');
|
||||||
|
let html = '';
|
||||||
|
let threads = data['threads'];
|
||||||
|
let colors = {
|
||||||
|
'RUNNABLE':'#32d296',
|
||||||
|
'BLOCKED':'#cc0c0c',
|
||||||
|
'WAITING':'#ad7070',
|
||||||
|
'TIMED_WAITING':'#ad7070'
|
||||||
|
}
|
||||||
|
for (let i = 0; i < threads.length; i++) {
|
||||||
|
let thread = threads[i];
|
||||||
|
let id = thread['id'];
|
||||||
|
let name = thread['name'];
|
||||||
|
let classType = thread['classType'];
|
||||||
|
let state = thread['state'];
|
||||||
|
let stacks = thread['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>`;
|
||||||
|
}
|
||||||
|
element.innerHTML = html;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showThreadInfo(id) {
|
||||||
|
let stacks = threadMap[id];
|
||||||
|
let html = '';
|
||||||
|
for (let i = 0; i < stacks.length; i++) {
|
||||||
|
let stack = stacks[i];
|
||||||
|
let className = stack['className']
|
||||||
|
let methodName = stack['methodName']
|
||||||
|
let fileName = stack['fileName']
|
||||||
|
let lineNumber = stack['lineNumber']
|
||||||
|
html+=`<li style='color: #333;font-weight: 400;font-size: 14px;'>${className}.${methodName} <span style='font-size: 10px;background-color: darkslategray;text-transform: unset' class="uk-label uk-label-success">${fileName}:${lineNumber}</span></li>`;
|
||||||
|
|
||||||
|
}
|
||||||
|
let threadDetailDom = document.getElementById('thread-detail');
|
||||||
|
threadDetailDom.innerHTML = html;
|
||||||
|
UIkit.notification.closeAll();
|
||||||
|
UIkit.modal(document.getElementById("modal-thread")).show();
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
refreshData();
|
refreshData();
|
||||||
});
|
});
|
||||||
@ -529,6 +588,7 @@
|
|||||||
<li id="zl" class="uk-active"><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Summary</a></li>
|
<li id="zl" class="uk-active"><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Summary</a></li>
|
||||||
<li id="jklb"><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Interfaces</a></li>
|
<li id="jklb"><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Interfaces</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Exceptions</a></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Exceptions</a></li>
|
||||||
|
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Threads</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Hot update</a></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Hot update</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Configurations</a></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Configurations</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Contact me</a><span title="Latest release" style="position: absolute;top:-10px;left: 90%;border-radius: 5px;text-transform: unset" class="uk-label" id="version-notice" onclick="window.location.href='http://www.kotime.cn/docs/kaiyuan#/v220/introduce'"></span></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px;text-transform: capitalize">Contact me</a><span title="Latest release" style="position: absolute;top:-10px;left: 90%;border-radius: 5px;text-transform: unset" class="uk-label" id="version-notice" onclick="window.location.href='http://www.kotime.cn/docs/kaiyuan#/v220/introduce'"></span></li>
|
||||||
@ -648,6 +708,50 @@
|
|||||||
<li>exception 1 1 <span class="uk-label uk-label-danger">closed</span></li>
|
<li>exception 1 1 <span class="uk-label uk-label-danger">closed</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li style="margin-left: 30%;margin-right: 30%;">
|
||||||
|
<ul class="uk-flex-left" uk-tab>
|
||||||
|
<li class="uk-active"><a href="#" style="text-transform: capitalize">Number of thread</a></li>
|
||||||
|
</ul>
|
||||||
|
<div style="margin-top: 20px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('')" id="threadNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">ALL</span><br>
|
||||||
|
<span style="font-size: 30px;color: #020718;font-weight: bold" id="threadNum" >0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('RUNNABLE')" id="runnableNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">RUNNABLE</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #29da93;font-weight: bold" id="runnableNum">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('BLOCKED')" id="blockedNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">BLOCKED</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #cc0c0c;font-weight: bold" id="blockedNum">0</span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('WAITING')" id="waitingNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">WAITING</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #ad7070;font-weight: bold" id="waitingNum">0</span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('TIMED_WAITING')" id="timedWaitingNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">TIMED_WAITING</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #ad7070;font-weight: bold" id="timedWaitingNum">0</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="uk-flex-left" uk-tab>
|
||||||
|
<li class="uk-active"><a href="#" style="text-transform: capitalize">Threads</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul id="threadList" style="background-color: rgba(245,242,242,0.96);padding: 10px;overflow-y: auto;max-height: 70%" class="uk-list uk-list-divider">
|
||||||
|
<li>thread 1 1 <span class="uk-label uk-label-success">0</span></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
<li style="margin-left: 35%;margin-right: 35%;">
|
<li style="margin-left: 35%;margin-right: 35%;">
|
||||||
<div class="uk-card uk-card-default uk-card-body">
|
<div class="uk-card uk-card-default uk-card-body">
|
||||||
<div id="classForm" >
|
<div id="classForm" >
|
||||||
@ -709,7 +813,19 @@
|
|||||||
<a href="http://www.kotime.cn/person?version=v2.3.7">Local plugin</a></div>
|
<a href="http://www.kotime.cn/person?version=v2.3.7">Local plugin</a></div>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div id="modal-thread" uk-modal>
|
||||||
|
<div class="uk-modal-dialog" style="width: 75%">
|
||||||
|
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||||
|
<div class="uk-modal-body uk-margin-auto-vertical" uk-overflow-auto>
|
||||||
|
<ul id="thread-detail" style="background-color: rgba(245,242,242,0.96);padding: 10px;overflow-y: auto;max-height: 70%" class="uk-list uk-list-divider">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="uk-modal-footer uk-text-right">
|
||||||
|
<button class="uk-button uk-button-primary uk-modal-close" type="button">OK</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="modal-exception" uk-modal>
|
<div id="modal-exception" uk-modal>
|
||||||
<div class="uk-modal-dialog">
|
<div class="uk-modal-dialog">
|
||||||
<button class="uk-modal-close-default" type="button" uk-close></button>
|
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||||
|
|||||||
@ -5,10 +5,10 @@
|
|||||||
<style>
|
<style>
|
||||||
UIKitCss
|
UIKitCss
|
||||||
</style>
|
</style>
|
||||||
<!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.2.2/dist/css/uikit.min.css"/>-->
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.2.2/dist/css/uikit.min.css"/>
|
||||||
<!-- UIkit JS -->
|
<!-- UIkit JS -->
|
||||||
<!-- <script src="https://cdn.jsdelivr.net/npm/uikit@3.2.2/dist/js/uikit.min.js"></script>-->
|
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.2/dist/js/uikit.min.js"></script>
|
||||||
<!-- <script src="https://cdn.jsdelivr.net/npm/uikit@3.2.2/dist/js/uikit-icons.min.js"></script>-->
|
<script src="https://cdn.jsdelivr.net/npm/uikit@3.2.2/dist/js/uikit-icons.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
UIKitJs;
|
UIKitJs;
|
||||||
uiKitIconsJs;
|
uiKitIconsJs;
|
||||||
@ -49,6 +49,7 @@
|
|||||||
loadCpuInfo();
|
loadCpuInfo();
|
||||||
loadHeapMemoryInfo();
|
loadHeapMemoryInfo();
|
||||||
loadPhysicalMemoryInfo();
|
loadPhysicalMemoryInfo();
|
||||||
|
loadThreadsInfo();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -430,7 +431,7 @@
|
|||||||
|
|
||||||
function loadLatestVersion(){
|
function loadLatestVersion(){
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'http://www.kotime.cn/common/latestVersion?version=2.3.7',
|
url: 'http://www.kotime.cn/common/latestVersion?version=2.3.8',
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
cache: false,
|
cache: false,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
@ -501,6 +502,65 @@
|
|||||||
document.querySelector("#thisUsed").innerHTML = `${thisUsedValue.toFixed()}M`;
|
document.querySelector("#thisUsed").innerHTML = `${thisUsedValue.toFixed()}M`;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let threadMap = new Map();
|
||||||
|
function loadThreadsInfo(queryState) {
|
||||||
|
queryState = queryState || '';
|
||||||
|
$.get(concatToken('contextPath/koTime/getThreadsInfo?state='+queryState), function (data) {
|
||||||
|
let statistics = data['statistics'];
|
||||||
|
let all = statistics['all'];
|
||||||
|
let RUNNABLE = statistics['RUNNABLE'] || 0;
|
||||||
|
let BLOCKED = statistics['BLOCKED'] || 0;
|
||||||
|
let WAITING = statistics['WAITING'] || 0;
|
||||||
|
let TIMED_WAITING = statistics['TIMED_WAITING'] || 0;
|
||||||
|
|
||||||
|
document.querySelector("#threadNum").innerHTML = all;
|
||||||
|
document.querySelector("#runnableNum").innerHTML = RUNNABLE;
|
||||||
|
document.querySelector("#blockedNum").innerHTML = BLOCKED;
|
||||||
|
document.querySelector("#waitingNum").innerHTML = WAITING;
|
||||||
|
document.querySelector("#timedWaitingNum").innerHTML = TIMED_WAITING;
|
||||||
|
|
||||||
|
let element = document.getElementById('threadList');
|
||||||
|
let html = '';
|
||||||
|
let threads = data['threads'];
|
||||||
|
let colors = {
|
||||||
|
'RUNNABLE':'#32d296',
|
||||||
|
'BLOCKED':'#cc0c0c',
|
||||||
|
'WAITING':'#ad7070',
|
||||||
|
'TIMED_WAITING':'#ad7070'
|
||||||
|
}
|
||||||
|
for (let i = 0; i < threads.length; i++) {
|
||||||
|
let thread = threads[i];
|
||||||
|
let id = thread['id'];
|
||||||
|
let name = thread['name'];
|
||||||
|
let classType = thread['classType'];
|
||||||
|
let state = thread['state'];
|
||||||
|
let stacks = thread['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>`;
|
||||||
|
}
|
||||||
|
element.innerHTML = html;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showThreadInfo(id) {
|
||||||
|
let stacks = threadMap[id];
|
||||||
|
let html = '';
|
||||||
|
for (let i = 0; i < stacks.length; i++) {
|
||||||
|
let stack = stacks[i];
|
||||||
|
let className = stack['className']
|
||||||
|
let methodName = stack['methodName']
|
||||||
|
let fileName = stack['fileName']
|
||||||
|
let lineNumber = stack['lineNumber']
|
||||||
|
html+=`<li style='color: #333;font-weight: 400;font-size: 14px;'>${className}.${methodName} <span style='font-size: 10px;background-color: darkslategray;text-transform: unset' class="uk-label uk-label-success">${fileName}:${lineNumber}</span></li>`;
|
||||||
|
|
||||||
|
}
|
||||||
|
let threadDetailDom = document.getElementById('thread-detail');
|
||||||
|
threadDetailDom.innerHTML = html;
|
||||||
|
UIkit.notification.closeAll();
|
||||||
|
UIkit.modal(document.getElementById("modal-thread")).show();
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
refreshData();
|
refreshData();
|
||||||
});
|
});
|
||||||
@ -525,6 +585,7 @@
|
|||||||
<li id="zl" class="uk-active"><a href="#" style="color: #edeef1;font-size: 14px">总览</a></li>
|
<li id="zl" class="uk-active"><a href="#" style="color: #edeef1;font-size: 14px">总览</a></li>
|
||||||
<li id="jklb"><a href="#" style="color: #edeef1;font-size: 14px">接口列表</a></li>
|
<li id="jklb"><a href="#" style="color: #edeef1;font-size: 14px">接口列表</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px">异常列表</a></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px">异常列表</a></li>
|
||||||
|
<li><a href="#" style="color: #edeef1;font-size: 14px">线程列表</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px">热更新</a></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px">热更新</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px">配置</a></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px">配置</a></li>
|
||||||
<li><a href="#" style="color: #edeef1;font-size: 14px">技术支持</a><span title="点击查看版本发布信息" style="position: absolute;top:-10px;left: 90%;border-radius: 5px;text-transform: unset" class="uk-label" id="version-notice" onclick="window.location.href='http://www.kotime.cn/docs/kaiyuan#/v220/introduce'"></span></li>
|
<li><a href="#" style="color: #edeef1;font-size: 14px">技术支持</a><span title="点击查看版本发布信息" style="position: absolute;top:-10px;left: 90%;border-radius: 5px;text-transform: unset" class="uk-label" id="version-notice" onclick="window.location.href='http://www.kotime.cn/docs/kaiyuan#/v220/introduce'"></span></li>
|
||||||
@ -640,6 +701,50 @@
|
|||||||
<li>exception 1 1 <span class="uk-label uk-label-danger">未开启</span></li>
|
<li>exception 1 1 <span class="uk-label uk-label-danger">未开启</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
<li style="margin-left: 30%;margin-right: 30%;">
|
||||||
|
<ul class="uk-flex-left" uk-tab>
|
||||||
|
<li class="uk-active"><a href="#" >线程统计</a></li>
|
||||||
|
</ul>
|
||||||
|
<div style="margin-top: 20px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('')" id="threadNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">ALL</span><br>
|
||||||
|
<span style="font-size: 30px;color: #020718;font-weight: bold" id="threadNum" >0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('RUNNABLE')" id="runnableNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">RUNNABLE</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #29da93;font-weight: bold" id="runnableNum">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('BLOCKED')" id="blockedNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">BLOCKED</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #cc0c0c;font-weight: bold" id="blockedNum">0</span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('WAITING')" id="waitingNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">WAITING</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #ad7070;font-weight: bold" id="waitingNum">0</span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div onclick="loadThreadsInfo('TIMED_WAITING')" id="timedWaitingNum-div" style="cursor:pointer;border-radius: 10px;background-color: #fefffe;padding: 20px" class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||||
|
<span style="font-size: 10px;color: #3b3f4f">TIMED_WAITING</span>
|
||||||
|
<br>
|
||||||
|
<span style="font-size: 30px;color: #ad7070;font-weight: bold" id="timedWaitingNum">0</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul class="uk-flex-left" uk-tab>
|
||||||
|
<li class="uk-active"><a href="#" >线程列表</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul id="threadList" style="background-color: rgba(245,242,242,0.96);padding: 10px;overflow-y: auto;max-height: 70%" class="uk-list uk-list-divider">
|
||||||
|
<li>thread 1 1 <span class="uk-label uk-label-success">0</span></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
<li style="margin-left: 35%;margin-right: 35%;">
|
<li style="margin-left: 35%;margin-right: 35%;">
|
||||||
<div class="uk-card uk-card-default uk-card-body" style="border-radius: 5px">
|
<div class="uk-card uk-card-default uk-card-body" style="border-radius: 5px">
|
||||||
<div id="classForm" >
|
<div id="classForm" >
|
||||||
@ -702,6 +807,20 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<div id="modal-thread" uk-modal>
|
||||||
|
<div class="uk-modal-dialog" style="width: 75%">
|
||||||
|
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||||
|
<div class="uk-modal-body uk-margin-auto-vertical" uk-overflow-auto>
|
||||||
|
<ul id="thread-detail" style="background-color: rgba(245,242,242,0.96);padding: 10px;overflow-y: auto;max-height: 70%" class="uk-list uk-list-divider">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="uk-modal-footer uk-text-right">
|
||||||
|
<button class="uk-button uk-button-primary uk-modal-close" type="button">朕知道了</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="modal-exception" uk-modal>
|
<div id="modal-exception" uk-modal>
|
||||||
<div class="uk-modal-dialog">
|
<div class="uk-modal-dialog">
|
||||||
<button class="uk-modal-close-default" type="button" uk-close></button>
|
<button class="uk-modal-close-default" type="button" uk-close></button>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user