mirror of
https://gitee.com/huoyo/ko-time.git
synced 2025-12-06 08:48:30 +08:00
cherry-pick from spring2:v2.5.0
This commit is contained in:
parent
73efa549ca
commit
eb0e0c26d4
@ -0,0 +1,87 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import cn.langpy.kotime.service.metric.ClassInfoService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/classes")
|
||||
public class KoClassController {
|
||||
private static Logger log = Logger.getLogger(KoClassController.class.toString());
|
||||
|
||||
@GetMapping("/usage")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult usage() {
|
||||
ClassInfoService instance = SystemService.getInstance(ClassInfoService.class);
|
||||
return KoResult.success(instance.getClassUsage());
|
||||
}
|
||||
|
||||
@PutMapping("/{className}/replace")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult updateClass(@RequestParam("classFile") MultipartFile classFile, @PathVariable("className") String className) {
|
||||
if (classFile == null || classFile.isEmpty()) {
|
||||
return KoResult.failed("文件不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(className)) {
|
||||
return KoResult.failed("类名不能为空");
|
||||
}
|
||||
className = className.trim();
|
||||
File file = null;
|
||||
try {
|
||||
String originalFilename = classFile.getOriginalFilename();
|
||||
if (!originalFilename.endsWith(".class")) {
|
||||
return KoResult.failed("仅支持.class文件");
|
||||
}
|
||||
String[] filename = originalFilename.split("\\.");
|
||||
String substring = className.substring(className.lastIndexOf(".") + 1);
|
||||
if (!substring.equals(filename[0])) {
|
||||
return KoResult.failed("请确认类名是否正确");
|
||||
}
|
||||
file = uploadFile(classFile.getBytes(), filename[0]);
|
||||
} catch (IOException e) {
|
||||
log.severe("Error class file!");
|
||||
return KoResult.failed("无法解析文件");
|
||||
}
|
||||
final ClassInfoService classService = SystemService.getInstance(ClassInfoService.class);
|
||||
classService.updateClass(className, file.getAbsolutePath());
|
||||
file.deleteOnExit();
|
||||
return KoResult.success("更新成功");
|
||||
}
|
||||
|
||||
|
||||
private static File uploadFile(byte[] file, String fileName) throws IOException {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
File targetFile = File.createTempFile(fileName, ".class", new File(System.getProperty("java.io.tmpdir")));
|
||||
out = new FileOutputStream(targetFile.getAbsolutePath());
|
||||
out.write(file);
|
||||
out.flush();
|
||||
return targetFile;
|
||||
} catch (Exception e) {
|
||||
log.severe("" + e);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.config.DefaultConfig;
|
||||
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/configs")
|
||||
public class KoConfigController {
|
||||
private static Logger log = Logger.getLogger(KoConfigController.class.toString());
|
||||
|
||||
@GetMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult getConfig() {
|
||||
DefaultConfig config = Context.getConfig();
|
||||
return KoResult.success(config);
|
||||
}
|
||||
|
||||
|
||||
@PutMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult updateConfig(@RequestBody DefaultConfig config) {
|
||||
DefaultConfig koTimeConfig = Context.getConfig();
|
||||
if (config.getEnable() != null) {
|
||||
koTimeConfig.setEnable(config.getEnable());
|
||||
}
|
||||
if (config.getExceptionEnable() != null) {
|
||||
koTimeConfig.setExceptionEnable(config.getExceptionEnable());
|
||||
}
|
||||
if (config.getLogEnable() != null) {
|
||||
koTimeConfig.setLogEnable(config.getLogEnable());
|
||||
}
|
||||
if (config.getMailEnable() != null) {
|
||||
koTimeConfig.setMailEnable(config.getMailEnable());
|
||||
}
|
||||
if (config.getAbbreviationEnable() != null) {
|
||||
koTimeConfig.setAbbreviationEnable(config.getAbbreviationEnable());
|
||||
}
|
||||
if (config.getThreshold() != null) {
|
||||
koTimeConfig.setThreshold(config.getThreshold());
|
||||
}
|
||||
if (config.getLanguage() != null) {
|
||||
koTimeConfig.setLanguage(config.getLanguage());
|
||||
}
|
||||
return KoResult.success();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.service.metric.CpuMetricService;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/cpus")
|
||||
public class KoCpuUsageController {
|
||||
private static Logger log = Logger.getLogger(KoCpuUsageController.class.toString());
|
||||
|
||||
@GetMapping("/usage")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult usage() {
|
||||
CpuMetricService instance = SystemService.getInstance(CpuMetricService.class);
|
||||
return KoResult.success(instance.getCpuUsage());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.*;
|
||||
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/dynamicProperties")
|
||||
public class KoDynamicPropertyController {
|
||||
private static Logger log = Logger.getLogger(KoDynamicPropertyController.class.toString());
|
||||
|
||||
|
||||
@PutMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult updateDynamicProperties(@RequestBody TextParam textParam) {
|
||||
if (!StringUtils.hasText(textParam.getText())) {
|
||||
return KoResult.failed("更新失败");
|
||||
}
|
||||
String[] textSplit = textParam.getText().trim().split("\n");
|
||||
Properties dynamicProperties = Context.getDynamicProperties();
|
||||
for (String line : textSplit) {
|
||||
line = line.trim();
|
||||
if (line.length()==0 || line.startsWith("#") || line.startsWith("//")) {
|
||||
continue;
|
||||
}
|
||||
int i = line.indexOf("=");
|
||||
if (i<1) {
|
||||
continue;
|
||||
}
|
||||
String propertyStr = line.substring(0, i).trim();
|
||||
String valueStr = line.substring(i+1).trim();
|
||||
log.info("updated property: "+propertyStr+"=("+dynamicProperties.get(propertyStr)+"->"+valueStr+")");
|
||||
dynamicProperties.setProperty(propertyStr,valueStr);
|
||||
}
|
||||
|
||||
return KoResult.success();
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult getDynamicProperties() {
|
||||
Properties dynamicProperties = Context.getDynamicProperties();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (String key : dynamicProperties.stringPropertyNames()) {
|
||||
String value = dynamicProperties.getProperty(key);
|
||||
if (value!=null) {
|
||||
stringBuilder.append(key+"="+value+"\n");
|
||||
}
|
||||
}
|
||||
return KoResult.success(stringBuilder.toString());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.*;
|
||||
import cn.langpy.kotime.service.GraphService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/exceptions")
|
||||
public class KoExceptionController {
|
||||
private static Logger log = Logger.getLogger(KoExceptionController.class.toString());
|
||||
|
||||
|
||||
@GetMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult getExceptions() {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<ExceptionNode> exceptionList = graphService.getExceptions();
|
||||
return KoResult.success(exceptionList);
|
||||
}
|
||||
|
||||
@GetMapping("/{exceptionId}/details")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult getMethodsByExceptionId(@PathVariable("exceptionId") String exceptionId, String message) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<ExceptionInfo> exceptionInfos = graphService.getExceptionInfos(exceptionId, message);
|
||||
return KoResult.success(exceptionInfos);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.service.metric.GcMetricService;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/gcs")
|
||||
public class KoGcUsageController {
|
||||
private static Logger log = Logger.getLogger(KoGcUsageController.class.toString());
|
||||
|
||||
@GetMapping("/usage")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult usage() {
|
||||
GcMetricService instance = SystemService.getInstance(GcMetricService.class);
|
||||
return KoResult.success(instance.getGcUsage());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.constant.KoConstant;
|
||||
import cn.langpy.kotime.model.*;
|
||||
import cn.langpy.kotime.service.GraphService;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import cn.langpy.kotime.util.InvalidAuthInfoException;
|
||||
import cn.langpy.kotime.util.KoUtil;
|
||||
@ -44,26 +46,22 @@ public class KoInitController {
|
||||
|
||||
@PostMapping("/login")
|
||||
@ResponseBody
|
||||
public Map login(@RequestBody UserInfo userInfo) {
|
||||
public KoResult login(@RequestBody UserInfo userInfo) {
|
||||
if (null == userInfo || !StringUtils.hasText(userInfo.getUserName()) || !StringUtils.hasText(userInfo.getPassword())) {
|
||||
throw new InvalidAuthInfoException("failed to login for kotime,please fill userName and password!");
|
||||
}
|
||||
Map map = new HashMap();
|
||||
if (userName.equals(userInfo.getUserName()) && password.equals(userInfo.getPassword())) {
|
||||
String token = KoUtil.login(userInfo.getUserName());
|
||||
map.put("state", 1);
|
||||
Map map = new HashMap();
|
||||
map.put("token", token);
|
||||
return map;
|
||||
return KoResult.success(map);
|
||||
}
|
||||
map.put("state", 0);
|
||||
return map;
|
||||
return KoResult.failed("登录失败");
|
||||
}
|
||||
|
||||
@GetMapping("/isLogin")
|
||||
@ResponseBody
|
||||
public Map isLogin(String kotoken) {
|
||||
Map map = new HashMap();
|
||||
map.put("state", 1);
|
||||
public KoResult isLogin(String kotoken) {
|
||||
boolean checkLogin = false;
|
||||
if (StringUtils.hasText(kotoken)) {
|
||||
if (kotoken.equals(Context.getConfig().getStaticToken())) {
|
||||
@ -72,8 +70,18 @@ public class KoInitController {
|
||||
checkLogin = KoUtil.isLogin(kotoken);
|
||||
}
|
||||
}
|
||||
Map map = new HashMap();
|
||||
map.put("isLogin", checkLogin ? 1 : 0);
|
||||
return map;
|
||||
return KoResult.success(map);
|
||||
}
|
||||
|
||||
@PostMapping("/clearData")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult clearData() {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
graphService.clearAll();
|
||||
return KoResult.success();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,118 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.model.MethodInfo;
|
||||
import cn.langpy.kotime.model.ParamMetric;
|
||||
import cn.langpy.kotime.model.SystemStatistic;
|
||||
import cn.langpy.kotime.service.GraphService;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/interfaces")
|
||||
public class KoInterfaceController {
|
||||
private static Logger log = Logger.getLogger(KoInterfaceController.class.toString());
|
||||
|
||||
@GetMapping("/usage")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult usage() {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
SystemStatistic system = graphService.getRunStatistic();
|
||||
return KoResult.success(system);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult<List<MethodInfo>> getInterfaces(String question, String orderBy, String sort) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<MethodInfo> list = null;
|
||||
if (StringUtils.hasText(question)) {
|
||||
list = graphService.searchMethods(question);
|
||||
} else {
|
||||
list = graphService.getControllers();
|
||||
}
|
||||
|
||||
Collections.sort(list, (o1, o2) -> {
|
||||
int sortValue = -1;
|
||||
if ("asc".equals(sort)) {
|
||||
sortValue = 1;
|
||||
}
|
||||
if ("callNum".equals(orderBy)) {
|
||||
return o1.getCallNum().compareTo(o2.getCallNum()) * sortValue;
|
||||
} else {
|
||||
return o1.getAvgRunTime().compareTo(o2.getAvgRunTime()) * sortValue;
|
||||
}
|
||||
});
|
||||
return KoResult.success(list);
|
||||
}
|
||||
|
||||
@GetMapping("/export")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public void export(String question, String orderBy, String sort, HttpServletResponse response) {
|
||||
List<MethodInfo> apis = getInterfaces(question, orderBy, sort).getContent();
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.addHeader("Content-Disposition", "attachment; filename=interfaces.csv");
|
||||
|
||||
try (OutputStream out = response.getOutputStream();
|
||||
BufferedOutputStream bufferedOut = new BufferedOutputStream(out)) {
|
||||
String line = "序号,类名,方法名,路由,平均响应(ms),调用次数\n";
|
||||
if ("english".equals(Context.getConfig().getLanguage())) {
|
||||
line = "No,ClassName,Method,Route,Avg(ms),CallNum\n";
|
||||
}
|
||||
bufferedOut.write(line.getBytes("utf-8"));
|
||||
for (int i = 0; i < apis.size(); i++) {
|
||||
MethodInfo methodInfo = apis.get(i);
|
||||
line = (i + 1) + "," + methodInfo.getClassName() + "," + methodInfo.getMethodName() + "()," + methodInfo.getRouteName() + "," + methodInfo.getAvgRunTime() + "," + methodInfo.getCallNum() + "\n";
|
||||
bufferedOut.write(line.getBytes("utf-8"));
|
||||
}
|
||||
bufferedOut.flush();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/searchCondidate")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult<List<String>> searchCondidate(String question) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<String> list = graphService.getCondidates(question);
|
||||
return KoResult.success(list);
|
||||
}
|
||||
|
||||
@GetMapping("/{methodId}/paramMetric")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult<Map<String, ParamMetric>> paramMetric(@PathVariable("methodId") String methodId) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
Map<String, ParamMetric> list = graphService.getMethodParamGraph(methodId);
|
||||
return KoResult.success(list);
|
||||
}
|
||||
|
||||
@GetMapping("/{methodId}/tree")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult getTree(@PathVariable("methodId") String methodId) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
MethodInfo tree = graphService.getTree(methodId);
|
||||
return KoResult.success(tree);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.service.metric.JvmSpaceMetricService;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/jvmSpaces")
|
||||
public class KoJvmSpaceController {
|
||||
private static Logger log = Logger.getLogger(KoJvmSpaceController.class.toString());
|
||||
|
||||
@GetMapping("/edenSpace")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult edenSpace() {
|
||||
JvmSpaceMetricService instance = SystemService.getInstance(JvmSpaceMetricService.class);
|
||||
return KoResult.success(instance.getEdenSpaceInfo());
|
||||
}
|
||||
|
||||
@GetMapping("/survivorSpace")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult survivorSpace() {
|
||||
JvmSpaceMetricService instance = SystemService.getInstance(JvmSpaceMetricService.class);
|
||||
return KoResult.success(instance.getSurvivorSpaceInfo());
|
||||
}
|
||||
|
||||
@GetMapping("/oldGen")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult oldGen() {
|
||||
JvmSpaceMetricService instance = SystemService.getInstance(JvmSpaceMetricService.class);
|
||||
return KoResult.success(instance.getOldGenInfo());
|
||||
}
|
||||
|
||||
@GetMapping("/metaspace")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult metaspace() {
|
||||
JvmSpaceMetricService instance = SystemService.getInstance(JvmSpaceMetricService.class);
|
||||
return KoResult.success(instance.getMetaspaceInfo());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.*;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import cn.langpy.kotime.service.metric.MemoryMetricService;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/memories")
|
||||
public class KoMemoryController {
|
||||
private static Logger log = Logger.getLogger(KoMemoryController.class.toString());
|
||||
|
||||
@GetMapping("/heap")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult heap() {
|
||||
MemoryMetricService instance = SystemService.getInstance(MemoryMetricService.class);
|
||||
JvmMemoryInfo heapMemoryInfo = instance.getHeapMemoryInfo();
|
||||
return KoResult.success(heapMemoryInfo);
|
||||
}
|
||||
|
||||
@GetMapping("/nonHeap")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult nonHeap() {
|
||||
MemoryMetricService instance = SystemService.getInstance(MemoryMetricService.class);
|
||||
JvmMemoryInfo heapMemoryInfo = instance.getNonHeapMemoryInfo();
|
||||
return KoResult.success(heapMemoryInfo);
|
||||
}
|
||||
|
||||
@GetMapping("/physical")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult physical() {
|
||||
MemoryMetricService instance = SystemService.getInstance(MemoryMetricService.class);
|
||||
PhysicalMemoryInfo heapMemoryInfo = instance.getPhysicalMemoryInfo();
|
||||
return KoResult.success(heapMemoryInfo);
|
||||
}
|
||||
|
||||
@GetMapping("/heap/export")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public void heapExport(Boolean live, HttpServletResponse response) {
|
||||
live = live == null ? false : live;
|
||||
MemoryMetricService instance = SystemService.getInstance(MemoryMetricService.class);
|
||||
String heapDumpFile = instance.getHeapDumpFile(live);
|
||||
if (heapDumpFile == null) {
|
||||
throw new RuntimeException("Can not dumpheap file!");
|
||||
}
|
||||
log.info(heapDumpFile);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + instance.getHeapDumpFileName(live));
|
||||
try (OutputStream out = response.getOutputStream();
|
||||
BufferedOutputStream bufferedOut = new BufferedOutputStream(out);
|
||||
FileInputStream fileInputStream = new FileInputStream(heapDumpFile);
|
||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
|
||||
bufferedOut.write(buffer, 0, bytesRead);
|
||||
}
|
||||
bufferedOut.flush();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.model.KoResult;
|
||||
import cn.langpy.kotime.model.ThreadInfo;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import cn.langpy.kotime.service.metric.ThreadMetricService;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.langpy.kotime.model.ThreadInfo.COMPARATOR;
|
||||
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime/threads")
|
||||
public class KoThreadController {
|
||||
private static Logger log = Logger.getLogger(KoThreadController.class.toString());
|
||||
|
||||
@GetMapping("/usage")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult usage() {
|
||||
ThreadMetricService instance = SystemService.getInstance(ThreadMetricService.class);
|
||||
return KoResult.success(instance.getThreadUsage());
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public KoResult threads(String state) {
|
||||
ThreadMetricService instance = SystemService.getInstance(ThreadMetricService.class);
|
||||
List<ThreadInfo> threads = instance.getThreads();
|
||||
threads = threads.stream().sorted(COMPARATOR).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 KoResult.success(map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,376 +0,0 @@
|
||||
package cn.langpy.kotime.controller;
|
||||
|
||||
import cn.langpy.kotime.annotation.Auth;
|
||||
import cn.langpy.kotime.config.DefaultConfig;
|
||||
import cn.langpy.kotime.model.*;
|
||||
import cn.langpy.kotime.service.*;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.langpy.kotime.model.ThreadInfo.COMPARATOR;
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/koTime")
|
||||
public class KoTimeController {
|
||||
private static Logger log = Logger.getLogger(KoTimeController.class.toString());
|
||||
|
||||
|
||||
@GetMapping("/getConfig")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public DefaultConfig getConfig() {
|
||||
DefaultConfig config = Context.getConfig();
|
||||
return config;
|
||||
}
|
||||
|
||||
@GetMapping("/getStatistic")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public SystemStatistic getStatistic() {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
SystemStatistic system = graphService.getRunStatistic();
|
||||
return system;
|
||||
}
|
||||
|
||||
@GetMapping("/getApis")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public List<MethodInfo> getApis(String question,String orderBy,String sort) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<MethodInfo> list = null;
|
||||
if (StringUtils.hasText(question)) {
|
||||
list = graphService.searchMethods(question);
|
||||
} else {
|
||||
list = graphService.getControllers();
|
||||
}
|
||||
|
||||
Collections.sort(list, (o1, o2) -> {
|
||||
int sortValue = -1;
|
||||
if ("asc".equals(sort)) {
|
||||
sortValue = 1;
|
||||
}
|
||||
if ("callNum".equals(orderBy)) {
|
||||
return o1.getCallNum().compareTo(o2.getCallNum())* sortValue;
|
||||
}else {
|
||||
return o1.getAvgRunTime().compareTo(o2.getAvgRunTime())* sortValue;
|
||||
}
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
@GetMapping("/exportApis")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public void exportApis(String question, String orderBy, String sort, HttpServletResponse response) {
|
||||
List<MethodInfo> apis = getApis(question, orderBy, sort);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.addHeader("Content-Disposition", "attachment; filename=interfaces.csv");
|
||||
|
||||
try( OutputStream out = response.getOutputStream();
|
||||
BufferedOutputStream bufferedOut = new BufferedOutputStream(out)){
|
||||
String line = "序号,类名,方法名,路由,平均响应(ms),调用次数\n";
|
||||
if ("english".equals(Context.getConfig().getLanguage())) {
|
||||
line = "No,ClassName,Method,Route,Avg(ms),CallNum\n";
|
||||
}
|
||||
bufferedOut.write(line.getBytes("utf-8"));
|
||||
for (int i = 0; i < apis.size(); i++) {
|
||||
MethodInfo methodInfo = apis.get(i);
|
||||
line = (i+1)+","+methodInfo.getClassName()+","+methodInfo.getMethodName()+"(),"+methodInfo.getRouteName()+","+methodInfo.getAvgRunTime()+","+methodInfo.getCallNum()+"\n";
|
||||
bufferedOut.write(line.getBytes("utf-8"));
|
||||
}
|
||||
bufferedOut.flush();
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/getParamGraph")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public Map<String, ParamMetric> getParamGraph(String methodId) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
Map<String, ParamMetric> list = graphService.getMethodParamGraph(methodId);
|
||||
return list;
|
||||
}
|
||||
|
||||
@GetMapping("/getApiTips")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public List<String> getApiTips(String question) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<String> list = graphService.getCondidates(question);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/getExceptions")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public List<ExceptionNode> getExceptions() {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<ExceptionNode> exceptionList = graphService.getExceptions();
|
||||
return exceptionList;
|
||||
}
|
||||
|
||||
@GetMapping("/getTree")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public MethodInfo getTree(String methodName) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
MethodInfo tree = graphService.getTree(methodName);
|
||||
return tree;
|
||||
}
|
||||
|
||||
@GetMapping("/getMethodsByExceptionId")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public List<ExceptionInfo> getMethodsByExceptionId(String exceptionId, String message) {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
List<ExceptionInfo> exceptionInfos = graphService.getExceptionInfos(exceptionId, message);
|
||||
return exceptionInfos;
|
||||
}
|
||||
|
||||
@PostMapping("/updateConfig")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public boolean updateConfig(@RequestBody DefaultConfig config) {
|
||||
DefaultConfig koTimeConfig = Context.getConfig();
|
||||
if (config.getEnable() != null) {
|
||||
koTimeConfig.setEnable(config.getEnable());
|
||||
}
|
||||
if (config.getExceptionEnable() != null) {
|
||||
koTimeConfig.setExceptionEnable(config.getExceptionEnable());
|
||||
}
|
||||
if (config.getLogEnable() != null) {
|
||||
koTimeConfig.setLogEnable(config.getLogEnable());
|
||||
}
|
||||
if (config.getMailEnable() != null) {
|
||||
koTimeConfig.setMailEnable(config.getMailEnable());
|
||||
}
|
||||
if (config.getAbbreviationEnable() != null) {
|
||||
koTimeConfig.setAbbreviationEnable(config.getAbbreviationEnable());
|
||||
}
|
||||
if (config.getThreshold() != null) {
|
||||
koTimeConfig.setThreshold(config.getThreshold());
|
||||
}
|
||||
if (config.getLanguage() != null) {
|
||||
koTimeConfig.setLanguage(config.getLanguage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@PostMapping("/updateClass")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public Map updateClass(@RequestParam("classFile") MultipartFile classFile, String className) {
|
||||
Map map = new HashMap();
|
||||
if (classFile == null || classFile.isEmpty()) {
|
||||
map.put("state", 0);
|
||||
map.put("message", "文件不能为空");
|
||||
return map;
|
||||
}
|
||||
if (!StringUtils.hasText(className)) {
|
||||
map.put("state", 0);
|
||||
map.put("message", "类名不能为空");
|
||||
return map;
|
||||
}
|
||||
className = className.trim();
|
||||
File file = null;
|
||||
try {
|
||||
String originalFilename = classFile.getOriginalFilename();
|
||||
if (!originalFilename.endsWith(".class")) {
|
||||
map.put("state", 0);
|
||||
map.put("message", "仅支持.class文件");
|
||||
return map;
|
||||
}
|
||||
String[] filename = originalFilename.split("\\.");
|
||||
String substring = className.substring(className.lastIndexOf(".") + 1);
|
||||
if (!substring.equals(filename[0])) {
|
||||
map.put("state", 0);
|
||||
map.put("message", "请确认类名是否正确");
|
||||
return map;
|
||||
}
|
||||
file = uploadFile(classFile.getBytes(), filename[0]);
|
||||
} catch (IOException e) {
|
||||
log.severe("Error class file!");
|
||||
map.put("state", 0);
|
||||
map.put("message", "无法解析文件");
|
||||
return map;
|
||||
}
|
||||
final ClassService classService = ClassService.getInstance();
|
||||
classService.updateClass(className, file.getAbsolutePath());
|
||||
file.deleteOnExit();
|
||||
|
||||
map.put("state", 1);
|
||||
map.put("message", "更新成功");
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
private static File uploadFile(byte[] file, String fileName) throws IOException {
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
File targetFile = File.createTempFile(fileName, ".class", new File(System.getProperty("java.io.tmpdir")));
|
||||
out = new FileOutputStream(targetFile.getAbsolutePath());
|
||||
out.write(file);
|
||||
out.flush();
|
||||
return targetFile;
|
||||
} catch (Exception e) {
|
||||
log.severe("" + e);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@GetMapping("/getCpuInfo")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public CpuInfo getCpuInfo() {
|
||||
SysUsageService usageService = SysUsageService.newInstance();
|
||||
CpuInfo cpuInfo = usageService.getCpuInfo();
|
||||
return cpuInfo;
|
||||
}
|
||||
|
||||
@GetMapping("/getHeapMemoryInfo")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public HeapMemoryInfo getHeapMemoryInfo() {
|
||||
SysUsageService usageService = SysUsageService.newInstance();
|
||||
HeapMemoryInfo heapMemoryInfo = usageService.getHeapMemoryInfo();
|
||||
return heapMemoryInfo;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/dumpHeap")
|
||||
@ResponseBody
|
||||
// @Auth
|
||||
public void dumpHeap(Boolean live, HttpServletResponse response) {
|
||||
live = live==null?false:live;
|
||||
HeapDumpService heapDumpService = HeapDumpService.newInstance();
|
||||
String heapDumpFile = heapDumpService.getHeapDumpFile(live);
|
||||
if (heapDumpFile == null) {
|
||||
throw new RuntimeException("Can not dumpheap file!");
|
||||
}
|
||||
log.info(heapDumpFile);
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
||||
response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+heapDumpService.getHeapDumpFileName(live));
|
||||
try( OutputStream out = response.getOutputStream();
|
||||
BufferedOutputStream bufferedOut = new BufferedOutputStream(out);
|
||||
FileInputStream fileInputStream = new FileInputStream(heapDumpFile);
|
||||
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)){
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead;
|
||||
while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
|
||||
bufferedOut.write(buffer,0,bytesRead);
|
||||
}
|
||||
bufferedOut.flush();
|
||||
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/getPhysicalMemoryInfo")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public PhysicalMemoryInfo getPhysicalMemoryInfo() {
|
||||
SysUsageService usageService = SysUsageService.newInstance();
|
||||
PhysicalMemoryInfo physicalMemoryInfo = usageService.getPhysicalMemoryInfo();
|
||||
return physicalMemoryInfo;
|
||||
}
|
||||
|
||||
@PostMapping("/clearData")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public boolean clearData() {
|
||||
GraphService graphService = GraphService.getInstance();
|
||||
graphService.clearAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
@GetMapping("/getThreadsInfo")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public Map getThreadsInfo(String state) {
|
||||
ThreadUsageService usageService = ThreadUsageService.newInstance();
|
||||
List<ThreadInfo> threads = usageService.getThreads();
|
||||
threads = threads.stream().sorted(COMPARATOR).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;
|
||||
}
|
||||
|
||||
@PostMapping("/updateDynamicProperties")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public boolean updateDynamicProperties(@RequestBody TextParam textParam) {
|
||||
if (!StringUtils.hasText(textParam.getText())) {
|
||||
return false;
|
||||
}
|
||||
String[] textSplit = textParam.getText().trim().split("\n");
|
||||
Properties dynamicProperties = Context.getDynamicProperties();
|
||||
for (String line : textSplit) {
|
||||
line = line.trim();
|
||||
if (line.length() == 0 || line.startsWith("#") || line.startsWith("//")) {
|
||||
continue;
|
||||
}
|
||||
int i = line.indexOf("=");
|
||||
if (i < 1) {
|
||||
continue;
|
||||
}
|
||||
String propertyStr = line.substring(0, i).trim();
|
||||
String valueStr = line.substring(i + 1).trim();
|
||||
log.info("updated property: " + propertyStr + "=(" + dynamicProperties.get(propertyStr) + "->" + valueStr + ")");
|
||||
dynamicProperties.setProperty(propertyStr, valueStr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@GetMapping("/getDynamicProperties")
|
||||
@ResponseBody
|
||||
@Auth
|
||||
public Map getDynamicProperties() {
|
||||
Map map = new HashMap();
|
||||
map.put("state", 0);
|
||||
map.put("message", "文件不能为空");
|
||||
Properties dynamicProperties = Context.getDynamicProperties();
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (String key : dynamicProperties.stringPropertyNames()) {
|
||||
String value = dynamicProperties.getProperty(key);
|
||||
if (value != null) {
|
||||
stringBuilder.append(key + "=" + value + "\n");
|
||||
}
|
||||
}
|
||||
map.put("data", stringBuilder.toString());
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@ -14,6 +14,7 @@ import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@ -328,6 +329,16 @@ public class DataBase implements GraphService {
|
||||
systemStatistic.setMaxRunTime(max);
|
||||
systemStatistic.setMinRunTime(min);
|
||||
systemStatistic.setAvgRunTime(avg);
|
||||
|
||||
|
||||
int maxCallNum = controllerApis.stream().map(api -> api.getCallNum()).max(Integer::compareTo).get();
|
||||
int minCallNum = controllerApis.stream().map(api -> api.getCallNum()).min(Integer::compareTo).get();
|
||||
double avgCallNum = controllerApis.stream().map(api -> api.getCallNum()).collect(Collectors.averagingInt(Integer::intValue));
|
||||
BigDecimal bgCallNum = BigDecimal.valueOf(avgCallNum);
|
||||
avgCallNum = bgCallNum.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
||||
systemStatistic.setMaxCallNum(maxCallNum);
|
||||
systemStatistic.setMinCallNum(minCallNum);
|
||||
systemStatistic.setAvgCallNum(avgCallNum);
|
||||
return systemStatistic;
|
||||
}
|
||||
|
||||
|
||||
@ -377,6 +377,15 @@ public class MemoryBase implements GraphService {
|
||||
systemStatistic.setMaxRunTime(max);
|
||||
systemStatistic.setMinRunTime(min);
|
||||
systemStatistic.setAvgRunTime(avg);
|
||||
|
||||
int maxCallNum = controllerApis.stream().map(api -> api.getCallNum()).max(Integer::compareTo).get();
|
||||
int minCallNum = controllerApis.stream().map(api -> api.getCallNum()).min(Integer::compareTo).get();
|
||||
double avgCallNum = controllerApis.stream().map(api -> api.getCallNum()).collect(Collectors.averagingInt(Integer::intValue));
|
||||
BigDecimal bgCallNum = BigDecimal.valueOf(avgCallNum);
|
||||
avgCallNum = bgCallNum.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
||||
systemStatistic.setMaxCallNum(maxCallNum);
|
||||
systemStatistic.setMinCallNum(minCallNum);
|
||||
systemStatistic.setAvgCallNum(avgCallNum);
|
||||
return systemStatistic;
|
||||
}
|
||||
|
||||
|
||||
@ -411,6 +411,16 @@ public class RedisBase implements GraphService {
|
||||
systemStatistic.setMaxRunTime(max);
|
||||
systemStatistic.setMinRunTime(min);
|
||||
systemStatistic.setAvgRunTime(avg);
|
||||
|
||||
|
||||
int maxCallNum = controllerApis.stream().map(api -> api.getCallNum()).max(Integer::compareTo).get();
|
||||
int minCallNum = controllerApis.stream().map(api -> api.getCallNum()).min(Integer::compareTo).get();
|
||||
double avgCallNum = controllerApis.stream().map(api -> api.getCallNum()).collect(Collectors.averagingInt(Integer::intValue));
|
||||
BigDecimal bgCallNum = BigDecimal.valueOf(avgCallNum);
|
||||
avgCallNum = bgCallNum.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
|
||||
systemStatistic.setMaxCallNum(maxCallNum);
|
||||
systemStatistic.setMinCallNum(minCallNum);
|
||||
systemStatistic.setAvgCallNum(avgCallNum);
|
||||
return systemStatistic;
|
||||
}
|
||||
|
||||
|
||||
31
src/main/java/cn/langpy/kotime/model/ClassUsage.java
Normal file
31
src/main/java/cn/langpy/kotime/model/ClassUsage.java
Normal file
@ -0,0 +1,31 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
public class ClassUsage {
|
||||
private Long totalClassNum;
|
||||
private Integer currentClassNum;
|
||||
private Long unloadedClassNum;
|
||||
|
||||
public Long getTotalClassNum() {
|
||||
return totalClassNum;
|
||||
}
|
||||
|
||||
public void setTotalClassNum(Long totalClassNum) {
|
||||
this.totalClassNum = totalClassNum;
|
||||
}
|
||||
|
||||
public Integer getCurrentClassNum() {
|
||||
return currentClassNum;
|
||||
}
|
||||
|
||||
public void setCurrentClassNum(Integer currentClassNum) {
|
||||
this.currentClassNum = currentClassNum;
|
||||
}
|
||||
|
||||
public Long getUnloadedClassNum() {
|
||||
return unloadedClassNum;
|
||||
}
|
||||
|
||||
public void setUnloadedClassNum(Long unloadedClassNum) {
|
||||
this.unloadedClassNum = unloadedClassNum;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
public class CpuInfo {
|
||||
public class CpuUsage {
|
||||
private Double systemLoad;
|
||||
private Double userRate;
|
||||
private Double sysRate;
|
||||
@ -0,0 +1,40 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
public class GarbageCollectionInfo {
|
||||
private Integer youngGcNum;
|
||||
private Long youngGcTime;
|
||||
private Integer oldGcNum;
|
||||
private Long oldGcNumTime;
|
||||
|
||||
public Integer getYoungGcNum() {
|
||||
return youngGcNum;
|
||||
}
|
||||
|
||||
public void setYoungGcNum(Integer youngGcNum) {
|
||||
this.youngGcNum = youngGcNum;
|
||||
}
|
||||
|
||||
public Long getYoungGcTime() {
|
||||
return youngGcTime;
|
||||
}
|
||||
|
||||
public void setYoungGcTime(Long youngGcTime) {
|
||||
this.youngGcTime = youngGcTime;
|
||||
}
|
||||
|
||||
public Integer getOldGcNum() {
|
||||
return oldGcNum;
|
||||
}
|
||||
|
||||
public void setOldGcNum(Integer oldGcNum) {
|
||||
this.oldGcNum = oldGcNum;
|
||||
}
|
||||
|
||||
public Long getOldGcNumTime() {
|
||||
return oldGcNumTime;
|
||||
}
|
||||
|
||||
public void setOldGcNumTime(Long oldGcNumTime) {
|
||||
this.oldGcNumTime = oldGcNumTime;
|
||||
}
|
||||
}
|
||||
49
src/main/java/cn/langpy/kotime/model/GcUsage.java
Normal file
49
src/main/java/cn/langpy/kotime/model/GcUsage.java
Normal file
@ -0,0 +1,49 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
public class GcUsage {
|
||||
private Long totalNum;
|
||||
private Long minorNum;
|
||||
private Long minorCostTime;
|
||||
private Long fullNum;
|
||||
private Long fullCostTime;
|
||||
|
||||
public Long getTotalNum() {
|
||||
return totalNum;
|
||||
}
|
||||
|
||||
public void setTotalNum(Long totalNum) {
|
||||
this.totalNum = totalNum;
|
||||
}
|
||||
|
||||
public Long getMinorNum() {
|
||||
return minorNum;
|
||||
}
|
||||
|
||||
public void setMinorNum(Long minorNum) {
|
||||
this.minorNum = minorNum;
|
||||
}
|
||||
|
||||
public Long getMinorCostTime() {
|
||||
return minorCostTime;
|
||||
}
|
||||
|
||||
public void setMinorCostTime(Long minorCostTime) {
|
||||
this.minorCostTime = minorCostTime;
|
||||
}
|
||||
|
||||
public Long getFullNum() {
|
||||
return fullNum;
|
||||
}
|
||||
|
||||
public void setFullNum(Long fullNum) {
|
||||
this.fullNum = fullNum;
|
||||
}
|
||||
|
||||
public Long getFullCostTime() {
|
||||
return fullCostTime;
|
||||
}
|
||||
|
||||
public void setFullCostTime(Long fullCostTime) {
|
||||
this.fullCostTime = fullCostTime;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
public class HeapMemoryInfo {
|
||||
public class JvmMemoryInfo {
|
||||
private Long initValue;
|
||||
private Long maxValue;
|
||||
private Long usedValue;
|
||||
58
src/main/java/cn/langpy/kotime/model/KoResult.java
Normal file
58
src/main/java/cn/langpy/kotime/model/KoResult.java
Normal file
@ -0,0 +1,58 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
* @param <T>
|
||||
*/
|
||||
public class KoResult<T> {
|
||||
private Integer state = 1;
|
||||
private String message;
|
||||
private T content;
|
||||
|
||||
|
||||
public static KoResult failed(String message) {
|
||||
KoResult result = new KoResult();
|
||||
result.setState(0);
|
||||
result.setMessage(message);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static KoResult success(Object content) {
|
||||
KoResult result = new KoResult();
|
||||
result.setState(1);
|
||||
result.setMessage("成功");
|
||||
result.setContent(content);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static KoResult success() {
|
||||
KoResult result = new KoResult();
|
||||
result.setState(1);
|
||||
result.setMessage("成功");
|
||||
return result;
|
||||
}
|
||||
|
||||
public Integer getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(Integer state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public T getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(T content) {
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,9 @@ public class SystemStatistic {
|
||||
private Integer totalNum = 0 ;
|
||||
private Integer delayNum = 0;
|
||||
private Integer normalNum = 0;
|
||||
|
||||
private Double avgCallNum = 0.0;
|
||||
private Integer maxCallNum = 0;
|
||||
private Integer minCallNum = 0;
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@ -66,6 +68,30 @@ public class SystemStatistic {
|
||||
this.normalNum = normalNum;
|
||||
}
|
||||
|
||||
public Double getAvgCallNum() {
|
||||
return avgCallNum;
|
||||
}
|
||||
|
||||
public void setAvgCallNum(Double avgCallNum) {
|
||||
this.avgCallNum = avgCallNum;
|
||||
}
|
||||
|
||||
public Integer getMaxCallNum() {
|
||||
return maxCallNum;
|
||||
}
|
||||
|
||||
public void setMaxCallNum(Integer maxCallNum) {
|
||||
this.maxCallNum = maxCallNum;
|
||||
}
|
||||
|
||||
public Integer getMinCallNum() {
|
||||
return minCallNum;
|
||||
}
|
||||
|
||||
public void setMinCallNum(Integer minCallNum) {
|
||||
this.minCallNum = minCallNum;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SystemStatistic{" +
|
||||
|
||||
@ -14,10 +14,19 @@ public class ThreadInfo {
|
||||
private String state;
|
||||
private Boolean isInterrupted;
|
||||
private Boolean isDaemon;
|
||||
private Boolean deadLock;
|
||||
private Integer priority;
|
||||
private BigDecimal cpuUsage;
|
||||
private List<StackTraceElement> stacks;
|
||||
|
||||
public Boolean getDeadLock() {
|
||||
return this.deadLock;
|
||||
}
|
||||
|
||||
public void setDeadLock(Boolean deadLock) {
|
||||
this.deadLock = deadLock;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
31
src/main/java/cn/langpy/kotime/model/ThreadUsage.java
Normal file
31
src/main/java/cn/langpy/kotime/model/ThreadUsage.java
Normal file
@ -0,0 +1,31 @@
|
||||
package cn.langpy.kotime.model;
|
||||
|
||||
public class ThreadUsage {
|
||||
private Integer totalNum;
|
||||
private Integer runnableNum;
|
||||
private Integer deadLockNum;
|
||||
|
||||
public Integer getTotalNum() {
|
||||
return totalNum;
|
||||
}
|
||||
|
||||
public void setTotalNum(Integer totalNum) {
|
||||
this.totalNum = totalNum;
|
||||
}
|
||||
|
||||
public Integer getRunnableNum() {
|
||||
return runnableNum;
|
||||
}
|
||||
|
||||
public void setRunnableNum(Integer runnableNum) {
|
||||
this.runnableNum = runnableNum;
|
||||
}
|
||||
|
||||
public Integer getDeadLockNum() {
|
||||
return deadLockNum;
|
||||
}
|
||||
|
||||
public void setDeadLockNum(Integer deadLockNum) {
|
||||
this.deadLockNum = deadLockNum;
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package cn.langpy.kotime.service;
|
||||
|
||||
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public interface ClassService {
|
||||
void updateClass(String className, String classPath);
|
||||
|
||||
static ClassService getInstance() {
|
||||
return ClassServiceFactory.getInstance();
|
||||
}
|
||||
}
|
||||
|
||||
class ClassServiceFactory {
|
||||
private static Logger log = Logger.getLogger(ClassServiceFactory.class.toString());
|
||||
|
||||
private static ClassService instance = null;
|
||||
|
||||
public static ClassService getInstance() {
|
||||
if (instance == null) {
|
||||
synchronized (ClassServiceFactory.class) {
|
||||
if (instance == null) {
|
||||
instance = new JvmAttachClassService();
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,45 +0,0 @@
|
||||
package cn.langpy.kotime.service;
|
||||
|
||||
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class HeapDumpService {
|
||||
private static final String STANDARD_DUMP_NAME = "kotime-heapdump-%s.hprof";
|
||||
private static Logger log = Logger.getLogger(HeapDumpService.class.toString());
|
||||
private static final String HotSpotDiagnosticName = "com.sun.management:type=HotSpotDiagnostic";
|
||||
|
||||
public static HeapDumpService newInstance() {
|
||||
return new HeapDumpService();
|
||||
}
|
||||
|
||||
public String getHeapDumpFile(boolean live) {
|
||||
String targetFile = System.getProperty("java.io.tmpdir")+File.separator+getHeapDumpFileName(live);
|
||||
try {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
HotSpotDiagnosticMXBean hotSpotDiagnostic = ManagementFactory.newPlatformMXBeanProxy(server, HotSpotDiagnosticName, HotSpotDiagnosticMXBean.class);
|
||||
if (Files.exists(Paths.get(targetFile))) {
|
||||
new File(targetFile).delete();
|
||||
}
|
||||
hotSpotDiagnostic.dumpHeap(targetFile, live);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.severe("Can not dump heap file!");
|
||||
}
|
||||
return targetFile;
|
||||
}
|
||||
|
||||
public String getHeapDumpFileName(boolean live) {
|
||||
if (live) {
|
||||
return String.format(STANDARD_DUMP_NAME, "live");
|
||||
}
|
||||
return String.format(STANDARD_DUMP_NAME, "all");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,144 +0,0 @@
|
||||
package cn.langpy.kotime.service;
|
||||
|
||||
import cn.langpy.kotime.model.CpuInfo;
|
||||
import cn.langpy.kotime.model.HeapMemoryInfo;
|
||||
import cn.langpy.kotime.model.PhysicalMemoryInfo;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class SysUsageService {
|
||||
private static Logger log = Logger.getLogger(SysUsageService.class.toString());
|
||||
|
||||
public static SysUsageService newInstance() {
|
||||
return new SysUsageService();
|
||||
}
|
||||
|
||||
public CpuInfo getCpuInfo() {
|
||||
SystemInfo systemInfo = new SystemInfo();
|
||||
CentralProcessor processor = systemInfo.getHardware().getProcessor();
|
||||
long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
long[] ticks = processor.getSystemCpuLoadTicks();
|
||||
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.NICE.getIndex()];
|
||||
|
||||
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
|
||||
|
||||
long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
|
||||
|
||||
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
|
||||
|
||||
long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
|
||||
|
||||
long user = ticks[CentralProcessor.TickType.USER.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.USER.getIndex()];
|
||||
|
||||
long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
|
||||
|
||||
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
|
||||
|
||||
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
|
||||
CpuInfo cpuInfo = new CpuInfo();
|
||||
cpuInfo.setLogicalNum(processor.getLogicalProcessorCount());
|
||||
cpuInfo.setUserRate(user * 1.0 / totalCpu);
|
||||
cpuInfo.setSysRate(cSys * 1.0 / totalCpu);
|
||||
cpuInfo.setWaitRate(iowait * 1.0 / totalCpu);
|
||||
cpuInfo.setSystemLoad(processor.getSystemCpuLoad(1000));
|
||||
return cpuInfo;
|
||||
}
|
||||
|
||||
public HeapMemoryInfo getHeapMemoryInfo() {
|
||||
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
|
||||
MemoryUsage memoryUsage = memoryMXBean.getHeapMemoryUsage();
|
||||
long initTotalMemorySize = memoryUsage.getInit();
|
||||
long maxMemorySize = memoryUsage.getMax();
|
||||
long usedMemorySize = memoryUsage.getUsed();
|
||||
HeapMemoryInfo heapMemoryInfo = new HeapMemoryInfo();
|
||||
heapMemoryInfo.setInitValue(initTotalMemorySize);
|
||||
heapMemoryInfo.setMaxValue(maxMemorySize);
|
||||
heapMemoryInfo.setUsedValue(usedMemorySize);
|
||||
heapMemoryInfo.setUsedRate(usedMemorySize * 1.0 / maxMemorySize);
|
||||
return heapMemoryInfo;
|
||||
}
|
||||
|
||||
public PhysicalMemoryInfo getPhysicalMemoryInfo() {
|
||||
OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
|
||||
PhysicalMemoryInfo physicalMemoryInfo = new PhysicalMemoryInfo();
|
||||
physicalMemoryInfo.setInitValue(osmxb.getTotalPhysicalMemorySize());
|
||||
physicalMemoryInfo.setUsedValue(osmxb.getTotalPhysicalMemorySize() - osmxb.getFreePhysicalMemorySize());
|
||||
physicalMemoryInfo.setFreeValue(osmxb.getFreePhysicalMemorySize());
|
||||
physicalMemoryInfo.setUsedValue(physicalMemoryInfo.getInitValue() - physicalMemoryInfo.getFreeValue());
|
||||
physicalMemoryInfo.setUsedRate(physicalMemoryInfo.getUsedValue() * 1.0 / physicalMemoryInfo.getInitValue());
|
||||
if (isLinux()) {
|
||||
Map<String, String> processInfo = getProcessInfo();
|
||||
if (processInfo.containsKey("VmSize")) {
|
||||
String VmRSSStr = processInfo.get("VmRSS");
|
||||
String VmSizeStr = VmRSSStr.split(" ")[0].trim();
|
||||
long VmRSS = Long.valueOf(VmSizeStr);
|
||||
physicalMemoryInfo.setThisUsedValue(VmRSS*1024);
|
||||
double rate = physicalMemoryInfo.getThisUsedValue()*1.0 / physicalMemoryInfo.getInitValue();
|
||||
physicalMemoryInfo.setThisUsedRate(rate);
|
||||
}
|
||||
}
|
||||
return physicalMemoryInfo;
|
||||
}
|
||||
|
||||
public boolean isLinux() {
|
||||
return System.getProperty("os.name").toLowerCase().contains("linux");
|
||||
}
|
||||
|
||||
public Map<String,String> getProcessInfo() {
|
||||
Map<String,String> processMetrics = new HashMap();
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
Process process = null;
|
||||
try {
|
||||
process = runtime.exec("cat /proc/" + Context.getPid() + "/status");
|
||||
} catch (IOException e) {
|
||||
log.severe("Can not execute '"+"cat /proc/" + Context.getPid() + "/status"+"'");
|
||||
return processMetrics;
|
||||
}
|
||||
try (InputStream inputStream = process.getInputStream();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
|
||||
) {
|
||||
String line ="";
|
||||
while ((line = bufferedReader.readLine()) != null){
|
||||
String[] split = line.split(":");
|
||||
if (split.length==2) {
|
||||
String key = split[0].trim();
|
||||
String value = split[1].trim();
|
||||
processMetrics.put(key,value);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.severe("Can not read the result of '"+"cat /proc/" + Context.getPid() + "/status"+"'");
|
||||
}
|
||||
return processMetrics;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,77 @@
|
||||
package cn.langpy.kotime.service.core;
|
||||
|
||||
|
||||
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
public class SystemService {
|
||||
Logger log = Logger.getLogger(SystemService.class.toString());
|
||||
private static final String HotSpotDiagnosticName = "com.sun.management:type=HotSpotDiagnostic";
|
||||
|
||||
final static Map<String, SystemService> serviceMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static <T extends SystemService> T getInstance(Class<? extends SystemService> clazz) {
|
||||
String simpleName = clazz.getSimpleName();
|
||||
T systemService = (T) serviceMap.get(simpleName);
|
||||
if (systemService == null) {
|
||||
synchronized (SystemService.class) {
|
||||
if (!serviceMap.containsKey(simpleName)) {
|
||||
try {
|
||||
systemService = (T) clazz.newInstance();
|
||||
serviceMap.put(simpleName, systemService);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}else {
|
||||
systemService = (T) serviceMap.get(simpleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return systemService;
|
||||
}
|
||||
|
||||
protected MemoryUsage getHeapMemoryUsage() {
|
||||
return ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
|
||||
}
|
||||
|
||||
protected MemoryUsage getNonHeapMemoryUsage() {
|
||||
return ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage();
|
||||
}
|
||||
|
||||
protected List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
|
||||
return ManagementFactory.getGarbageCollectorMXBeans();
|
||||
}
|
||||
|
||||
protected List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
|
||||
return ManagementFactory.getMemoryPoolMXBeans();
|
||||
}
|
||||
|
||||
protected ThreadMXBean getThreadMXBean() {
|
||||
return ManagementFactory.getThreadMXBean();
|
||||
}
|
||||
|
||||
protected ClassLoadingMXBean getClassLoadingMXBean() {
|
||||
return ManagementFactory.getClassLoadingMXBean();
|
||||
}
|
||||
|
||||
public HotSpotDiagnosticMXBean getHotSpotDiagnosticMXBean() {
|
||||
HotSpotDiagnosticMXBean hotSpotDiagnostic = null;
|
||||
try {
|
||||
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
|
||||
hotSpotDiagnostic = ManagementFactory.newPlatformMXBeanProxy(server, HotSpotDiagnosticName, HotSpotDiagnosticMXBean.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return hotSpotDiagnostic;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package cn.langpy.kotime.service;
|
||||
package cn.langpy.kotime.service.metric;
|
||||
|
||||
import cn.langpy.kotime.model.ClassUsage;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import net.bytebuddy.agent.VirtualMachine;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
@ -8,20 +10,28 @@ import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.management.ClassLoadingMXBean;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class JvmAttachClassService implements ClassService{
|
||||
private static Logger log = Logger.getLogger(JvmAttachClassService.class.toString());
|
||||
public class ClassInfoService extends SystemService {
|
||||
Logger log = Logger.getLogger(ClassInfoService.class.toString());
|
||||
|
||||
public ClassUsage getClassUsage() {
|
||||
ClassUsage usage = new ClassUsage();
|
||||
ClassLoadingMXBean classLoadingMXBean = getClassLoadingMXBean();
|
||||
usage.setTotalClassNum(classLoadingMXBean.getTotalLoadedClassCount());
|
||||
usage.setCurrentClassNum(classLoadingMXBean.getLoadedClassCount());
|
||||
usage.setUnloadedClassNum(classLoadingMXBean.getUnloadedClassCount());
|
||||
return usage;
|
||||
}
|
||||
private File agentJar;
|
||||
|
||||
public JvmAttachClassService() {
|
||||
public ClassInfoService() {
|
||||
this.agentJar = createAgentJar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateClass(String className, String classPath) {
|
||||
try {
|
||||
if (agentJar==null || !agentJar.exists()) {
|
||||
@ -0,0 +1,57 @@
|
||||
package cn.langpy.kotime.service.metric;
|
||||
|
||||
import cn.langpy.kotime.model.CpuUsage;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import oshi.SystemInfo;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class CpuMetricService extends SystemService {
|
||||
Logger log = Logger.getLogger(CpuMetricService.class.toString());
|
||||
public CpuUsage getCpuUsage() {
|
||||
SystemInfo systemInfo = new SystemInfo();
|
||||
CentralProcessor processor = systemInfo.getHardware().getProcessor();
|
||||
long[] prevTicks = processor.getSystemCpuLoadTicks();
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
long[] ticks = processor.getSystemCpuLoadTicks();
|
||||
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.NICE.getIndex()];
|
||||
|
||||
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
|
||||
|
||||
long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
|
||||
|
||||
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
|
||||
|
||||
long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
|
||||
|
||||
long user = ticks[CentralProcessor.TickType.USER.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.USER.getIndex()];
|
||||
|
||||
long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
|
||||
|
||||
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()]
|
||||
- prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
|
||||
|
||||
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
|
||||
CpuUsage cpuInfo = new CpuUsage();
|
||||
cpuInfo.setLogicalNum(processor.getLogicalProcessorCount());
|
||||
cpuInfo.setUserRate(user * 1.0 / totalCpu);
|
||||
cpuInfo.setSysRate(cSys * 1.0 / totalCpu);
|
||||
cpuInfo.setWaitRate(iowait * 1.0 / totalCpu);
|
||||
cpuInfo.setSystemLoad(processor.getSystemCpuLoad(1000));
|
||||
return cpuInfo;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package cn.langpy.kotime.service.metric;
|
||||
|
||||
import cn.langpy.kotime.model.GcUsage;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
|
||||
import java.lang.management.GarbageCollectorMXBean;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class GcMetricService extends SystemService {
|
||||
private final static List<String> youngMemoryPool = Arrays.asList("PS Eden Space", "PS Survivor Space");
|
||||
private final static List<String> oldMemoryPool = Arrays.asList("PS Old Gen", "Metaspace");
|
||||
Logger log = Logger.getLogger(GcMetricService.class.toString());
|
||||
|
||||
public GcUsage getGcUsage() {
|
||||
GcUsage gcUsage = new GcUsage();
|
||||
gcUsage.setFullNum(0L);
|
||||
gcUsage.setMinorNum(0L);
|
||||
gcUsage.setFullCostTime(0L);
|
||||
gcUsage.setMinorCostTime(0L);
|
||||
List<GarbageCollectorMXBean> garbageCollectorMXBeans = getGarbageCollectorMXBeans();
|
||||
for (GarbageCollectorMXBean bean : garbageCollectorMXBeans) {
|
||||
if (isFullGc(bean)) {
|
||||
gcUsage.setFullNum(gcUsage.getFullNum() + bean.getCollectionCount());
|
||||
gcUsage.setFullCostTime(gcUsage.getFullCostTime() + bean.getCollectionTime());
|
||||
} else if (isMinorGc(bean)) {
|
||||
gcUsage.setMinorNum(gcUsage.getMinorNum() + bean.getCollectionCount());
|
||||
gcUsage.setMinorCostTime(gcUsage.getMinorCostTime() + bean.getCollectionTime());
|
||||
} else {
|
||||
log.warning("kotime=>Can not recognize the garbage collector: " + bean);
|
||||
}
|
||||
}
|
||||
gcUsage.setTotalNum(gcUsage.getFullNum() + gcUsage.getMinorNum());
|
||||
return gcUsage;
|
||||
}
|
||||
|
||||
private boolean isMinorGc(GarbageCollectorMXBean bean) {
|
||||
String[] memoryPoolNames = bean.getMemoryPoolNames();
|
||||
boolean isMinor = false;
|
||||
boolean isMajor = false;
|
||||
for (String memoryPoolName : memoryPoolNames) {
|
||||
if (youngMemoryPool.contains(memoryPoolName)) {
|
||||
isMinor = true;
|
||||
}
|
||||
if (oldMemoryPool.contains(memoryPoolName)) {
|
||||
isMajor = true;
|
||||
}
|
||||
}
|
||||
return isMinor && !isMajor;
|
||||
}
|
||||
|
||||
private boolean isFullGc(GarbageCollectorMXBean bean) {
|
||||
String[] memoryPoolNames = bean.getMemoryPoolNames();
|
||||
boolean isMajor = false;
|
||||
for (String memoryPoolName : memoryPoolNames) {
|
||||
if (oldMemoryPool.contains(memoryPoolName)) {
|
||||
isMajor = true;
|
||||
}
|
||||
}
|
||||
return isMajor;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package cn.langpy.kotime.service.metric;
|
||||
|
||||
import cn.langpy.kotime.model.JvmMemoryInfo;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
|
||||
|
||||
import java.lang.management.MemoryPoolMXBean;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* zhangchang
|
||||
*/
|
||||
public class JvmSpaceMetricService extends SystemService {
|
||||
Logger log = Logger.getLogger(JvmSpaceMetricService.class.toString());
|
||||
|
||||
public JvmMemoryInfo getEdenSpaceInfo() {
|
||||
return getSpaceInfo("PS Eden Space");
|
||||
}
|
||||
|
||||
public JvmMemoryInfo getSurvivorSpaceInfo() {
|
||||
return getSpaceInfo("PS Survivor Space");
|
||||
}
|
||||
|
||||
public JvmMemoryInfo getOldGenInfo() {
|
||||
return getSpaceInfo("PS Old Gen");
|
||||
}
|
||||
|
||||
public JvmMemoryInfo getMetaspaceInfo() {
|
||||
return getSpaceInfo("Metaspace");
|
||||
}
|
||||
|
||||
private JvmMemoryInfo getSpaceInfo(String name) {
|
||||
List<MemoryPoolMXBean> memoryPoolMXBeans = getMemoryPoolMXBeans();
|
||||
Map<String, MemoryPoolMXBean> mxBeanMap = memoryPoolMXBeans.stream().collect(Collectors.toMap(v -> v.getName(), v -> v));
|
||||
MemoryPoolMXBean psEdenSpace = mxBeanMap.get(name);
|
||||
JvmMemoryInfo heapMemoryInfo = new JvmMemoryInfo();
|
||||
if (psEdenSpace == null) {
|
||||
heapMemoryInfo.setInitValue(0L);
|
||||
heapMemoryInfo.setMaxValue(0L);
|
||||
heapMemoryInfo.setUsedValue(0L);
|
||||
heapMemoryInfo.setUsedRate(0.0);
|
||||
return heapMemoryInfo;
|
||||
}
|
||||
MemoryUsage usage = psEdenSpace.getUsage();
|
||||
heapMemoryInfo.setInitValue(usage.getInit());
|
||||
heapMemoryInfo.setMaxValue(usage.getMax());
|
||||
heapMemoryInfo.setUsedValue(usage.getUsed());
|
||||
heapMemoryInfo.setUsedRate(usage.getUsed() * 1.0 / usage.getMax());
|
||||
return heapMemoryInfo;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,127 @@
|
||||
package cn.langpy.kotime.service.metric;
|
||||
|
||||
import cn.langpy.kotime.model.JvmMemoryInfo;
|
||||
import cn.langpy.kotime.model.PhysicalMemoryInfo;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import com.sun.management.HotSpotDiagnosticMXBean;
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryUsage;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MemoryMetricService extends SystemService {
|
||||
Logger log = Logger.getLogger(MemoryMetricService.class.toString());
|
||||
private static final String STANDARD_DUMP_NAME = "kotime-heapdump-%s.hprof";
|
||||
|
||||
public JvmMemoryInfo getHeapMemoryInfo() {
|
||||
MemoryUsage memoryUsage = getHeapMemoryUsage();
|
||||
long initTotalMemorySize = memoryUsage.getInit();
|
||||
long maxMemorySize = memoryUsage.getMax();
|
||||
long usedMemorySize = memoryUsage.getUsed();
|
||||
JvmMemoryInfo heapMemoryInfo = new JvmMemoryInfo();
|
||||
heapMemoryInfo.setInitValue(initTotalMemorySize);
|
||||
heapMemoryInfo.setMaxValue(maxMemorySize);
|
||||
heapMemoryInfo.setUsedValue(usedMemorySize);
|
||||
heapMemoryInfo.setUsedRate(usedMemorySize * 1.0 / maxMemorySize);
|
||||
return heapMemoryInfo;
|
||||
}
|
||||
|
||||
public JvmMemoryInfo getNonHeapMemoryInfo() {
|
||||
MemoryUsage memoryUsage = getNonHeapMemoryUsage();
|
||||
long initTotalMemorySize = memoryUsage.getInit();
|
||||
long maxMemorySize = memoryUsage.getMax();
|
||||
long usedMemorySize = memoryUsage.getUsed();
|
||||
JvmMemoryInfo heapMemoryInfo = new JvmMemoryInfo();
|
||||
heapMemoryInfo.setInitValue(initTotalMemorySize);
|
||||
heapMemoryInfo.setMaxValue(maxMemorySize);
|
||||
heapMemoryInfo.setUsedValue(usedMemorySize);
|
||||
heapMemoryInfo.setUsedRate(usedMemorySize * 1.0 / maxMemorySize);
|
||||
return heapMemoryInfo;
|
||||
}
|
||||
|
||||
public PhysicalMemoryInfo getPhysicalMemoryInfo() {
|
||||
OperatingSystemMXBean osmxb = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
|
||||
PhysicalMemoryInfo physicalMemoryInfo = new PhysicalMemoryInfo();
|
||||
physicalMemoryInfo.setInitValue(osmxb.getTotalPhysicalMemorySize());
|
||||
physicalMemoryInfo.setUsedValue(osmxb.getTotalPhysicalMemorySize() - osmxb.getFreePhysicalMemorySize());
|
||||
physicalMemoryInfo.setFreeValue(osmxb.getFreePhysicalMemorySize());
|
||||
physicalMemoryInfo.setUsedValue(physicalMemoryInfo.getInitValue() - physicalMemoryInfo.getFreeValue());
|
||||
physicalMemoryInfo.setUsedRate(physicalMemoryInfo.getUsedValue() * 1.0 / physicalMemoryInfo.getInitValue());
|
||||
if (isLinux()) {
|
||||
Map<String, String> processInfo = getProcessInfo();
|
||||
if (processInfo.containsKey("VmSize")) {
|
||||
String VmRSSStr = processInfo.get("VmRSS");
|
||||
String VmSizeStr = VmRSSStr.split(" ")[0].trim();
|
||||
long VmRSS = Long.valueOf(VmSizeStr);
|
||||
physicalMemoryInfo.setThisUsedValue(VmRSS * 1024);
|
||||
double rate = physicalMemoryInfo.getThisUsedValue() * 1.0 / physicalMemoryInfo.getInitValue();
|
||||
physicalMemoryInfo.setThisUsedRate(rate);
|
||||
}
|
||||
}
|
||||
return physicalMemoryInfo;
|
||||
}
|
||||
|
||||
public boolean isLinux() {
|
||||
return System.getProperty("os.name").toLowerCase().contains("linux");
|
||||
}
|
||||
|
||||
public Map<String, String> getProcessInfo() {
|
||||
Map<String, String> processMetrics = new HashMap();
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
Process process = null;
|
||||
try {
|
||||
process = runtime.exec("cat /proc/" + Context.getPid() + "/status");
|
||||
} catch (IOException e) {
|
||||
log.severe("Can not execute '" + "cat /proc/" + Context.getPid() + "/status" + "'");
|
||||
return processMetrics;
|
||||
}
|
||||
try (InputStream inputStream = process.getInputStream();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
|
||||
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
|
||||
) {
|
||||
String line = "";
|
||||
while ((line = bufferedReader.readLine()) != null) {
|
||||
String[] split = line.split(":");
|
||||
if (split.length == 2) {
|
||||
String key = split[0].trim();
|
||||
String value = split[1].trim();
|
||||
processMetrics.put(key, value);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.severe("Can not read the result of '" + "cat /proc/" + Context.getPid() + "/status" + "'");
|
||||
}
|
||||
return processMetrics;
|
||||
}
|
||||
|
||||
public String getHeapDumpFile(boolean live) {
|
||||
String targetFile = System.getProperty("java.io.tmpdir") + File.separator + getHeapDumpFileName(live);
|
||||
try {
|
||||
HotSpotDiagnosticMXBean hotSpotDiagnostic = getHotSpotDiagnosticMXBean();
|
||||
if (Files.exists(Paths.get(targetFile))) {
|
||||
new File(targetFile).delete();
|
||||
}
|
||||
hotSpotDiagnostic.dumpHeap(targetFile, live);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.severe("Can not dump heap file!");
|
||||
}
|
||||
return targetFile;
|
||||
}
|
||||
|
||||
public String getHeapDumpFileName(boolean live) {
|
||||
if (live) {
|
||||
return String.format(STANDARD_DUMP_NAME, "live");
|
||||
}
|
||||
return String.format(STANDARD_DUMP_NAME, "all");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,10 +1,9 @@
|
||||
package cn.langpy.kotime.service;
|
||||
package cn.langpy.kotime.service.metric;
|
||||
|
||||
import cn.langpy.kotime.model.ThreadInfo;
|
||||
import cn.langpy.kotime.util.Context;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import cn.langpy.kotime.model.ThreadUsage;
|
||||
import cn.langpy.kotime.service.core.SystemService;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.ThreadMXBean;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@ -15,19 +14,38 @@ import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ThreadUsageService {
|
||||
private static Logger log = Logger.getLogger(ThreadUsageService.class.toString());
|
||||
public class ThreadMetricService extends SystemService {
|
||||
private static Logger log = Logger.getLogger(ThreadMetricService.class.toString());
|
||||
|
||||
public static ThreadUsageService newInstance() {
|
||||
return new ThreadUsageService();
|
||||
|
||||
public ThreadUsage getThreadUsage() {
|
||||
ThreadUsage usage = new ThreadUsage();
|
||||
List<ThreadInfo> threads = getThreads();
|
||||
usage.setTotalNum(threads.size());
|
||||
usage.setRunnableNum(getThreads("RUNNABLE").size());
|
||||
long[] deadlockedThreads = getThreadMXBean().findDeadlockedThreads();
|
||||
usage.setDeadLockNum(deadlockedThreads==null?0:deadlockedThreads.length);
|
||||
return usage;
|
||||
}
|
||||
|
||||
public List<Long> getDeadlockThreadIds() {
|
||||
List<Long> threads = new ArrayList<>();
|
||||
long[] deadlockedThreads = getThreadMXBean().findDeadlockedThreads();
|
||||
if (deadlockedThreads==null || deadlockedThreads.length == 0) {
|
||||
return threads;
|
||||
}
|
||||
java.lang.management.ThreadInfo[] threadInfos = getThreadMXBean().getThreadInfo(deadlockedThreads);
|
||||
List<Long> collect = Arrays.stream(threadInfos).map(a -> a.getThreadId()).collect(Collectors.toList());
|
||||
return collect;
|
||||
}
|
||||
|
||||
public List<ThreadInfo> getThreads() {
|
||||
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
|
||||
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();;
|
||||
ThreadMXBean threadMXBean = getThreadMXBean();
|
||||
int activeCount = threadGroup.activeCount();
|
||||
Thread[] threads = new Thread[activeCount];
|
||||
threadGroup.enumerate(threads);
|
||||
List<Long> deadlockThreadIds = getDeadlockThreadIds();
|
||||
List<ThreadInfo> list = new ArrayList<>();
|
||||
for (int i = 0; i < activeCount; i++) {
|
||||
Thread thread = threads[i];
|
||||
@ -48,6 +66,11 @@ public class ThreadUsageService {
|
||||
threadInfo.setPriority(thread.getPriority());
|
||||
StackTraceElement[] stackTrace = thread.getStackTrace();
|
||||
threadInfo.setStacks(Arrays.stream(stackTrace).collect(Collectors.toList()));
|
||||
if (deadlockThreadIds.contains(thread.getId())) {
|
||||
threadInfo.setDeadLock(true);
|
||||
}else {
|
||||
threadInfo.setDeadLock(false);
|
||||
}
|
||||
list.add(threadInfo);
|
||||
}
|
||||
Collections.sort(list, Comparator.comparing(ThreadInfo::getCpuUsage).reversed());
|
||||
@ -1 +1 @@
|
||||
ko-time.version=3.0.2
|
||||
ko-time.version=3.1.0
|
||||
@ -14,4 +14,56 @@
|
||||
font-size: 14px;
|
||||
font-weight: 430;
|
||||
color: #3621a5;
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
border-radius: 10px;
|
||||
background-color: #fefffe;
|
||||
padding: 10px 20px 15px 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.metric-card-summary-n {
|
||||
font-size: 12px;
|
||||
color: #1f2541;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.metric-card-summary-v {
|
||||
font-size: 18px;
|
||||
color: #020718;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.metric-card-item {
|
||||
text-align: left;
|
||||
margin-top: -13px;
|
||||
/*margin-left: -40px;*/
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.metric-card-item li {
|
||||
line-height: 5px;
|
||||
}
|
||||
|
||||
|
||||
.metric-card-item-n {
|
||||
font-size: 8px;
|
||||
color: #3b3f4f;
|
||||
}
|
||||
|
||||
.metric-card-item-v {
|
||||
font-size: 12px;
|
||||
color: #020718;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.metric-card-item-point {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
background-color: #11de71;
|
||||
display: inline-block;
|
||||
border-radius: 10px;
|
||||
margin-right: 5px;
|
||||
margin-bottom:1px;
|
||||
}
|
||||
@ -10,8 +10,9 @@ tab.configuration=配置
|
||||
tab.support=技术支持
|
||||
|
||||
tab.summary.interface-metric=接口统计
|
||||
tab.summary.response-metric=响应统计
|
||||
tab.summary.sysusage-metric=系统使用情况
|
||||
tab.summary.memory-metric=内存统计
|
||||
tab.summary.jvm-metric=JVM空间统计
|
||||
tab.summary.other-metric=其他指标
|
||||
tab.summary.bottom-normal-tip=接口根据调用情况统计,未调用的接口无法被统计到,请先调用接口
|
||||
tab.summary.bottom-close-tip=方法调用监测已关闭,数据将不会更新,需要开启请到配置面板
|
||||
|
||||
@ -23,9 +24,21 @@ tab.summary.response-metric.avg-num=平均响应(ms)
|
||||
tab.summary.response-metric.max-num=最大响应(ms)
|
||||
tab.summary.response-metric.min-num=最小响应(ms)
|
||||
|
||||
tab.summary.sysusage-metric.cpu-usage=CPU使用率
|
||||
tab.summary.interface-metric.avg-call-num=平均调用数
|
||||
tab.summary.interface-metric.max-call-num=最大调用数
|
||||
tab.summary.interface-metric.min-call-num=最小调用数
|
||||
|
||||
tab.summary.sysusage-metric.cpu-usage=CPU
|
||||
tab.summary.sysusage-metric.heap-memory=堆内存
|
||||
tab.summary.sysusage-metric.non-heap-memory=非堆内存
|
||||
tab.summary.sysusage-metric.physical-memory=物理内存
|
||||
tab.summary.sysusage-metric.eden-space=Eden
|
||||
tab.summary.sysusage-metric.survivor-space=Survivor
|
||||
tab.summary.sysusage-metric.old-gen=OldGen
|
||||
tab.summary.sysusage-metric.meta-space=Metaspace
|
||||
tab.summary.sysusage-metric.gc-num=GC次数
|
||||
tab.summary.sysusage-metric.thread-num=线程数
|
||||
tab.summary.sysusage-metric.loaded-class-num=加载类总数
|
||||
|
||||
tab.summary.sysusage-metric.cpu-usage.user-usage=用户使用率
|
||||
tab.summary.sysusage-metric.cpu-usage.sys-usage=系统使用率
|
||||
@ -39,6 +52,14 @@ tab.summary.sysusage-metric.physical-memory.total=总物理内存
|
||||
tab.summary.sysusage-metric.physical-memory.used=已使用内存
|
||||
tab.summary.sysusage-metric.physical-memory.current-used=此程序占用
|
||||
|
||||
tab.summary.sysusage-metric.gc-num.minor=Minor GC
|
||||
tab.summary.sysusage-metric.gc-num.full=Major/Full GC
|
||||
|
||||
tab.summary.sysusage-metric.thread-num.runnable=运行数
|
||||
tab.summary.sysusage-metric.thread-num.deadlock=死锁数
|
||||
|
||||
tab.summary.sysusage-metric.loaded-class-num.current=当前类总数
|
||||
tab.summary.sysusage-metric.loaded-class-num.unloaded=卸载类数
|
||||
|
||||
tab.interface.search-tip=搜索方法名或者类名...
|
||||
tab.interface.interface-list.avg-tip=平均响应
|
||||
|
||||
@ -9,9 +9,10 @@ tab.hotupdate=Hot Update
|
||||
tab.configuration=Configurations
|
||||
tab.support=Tech Support
|
||||
|
||||
tab.summary.interface-metric=Number of Interface
|
||||
tab.summary.response-metric=Response Time
|
||||
tab.summary.sysusage-metric=System Usage
|
||||
tab.summary.interface-metric=Interface Indices
|
||||
tab.summary.memory-metric=Memory Indices
|
||||
tab.summary.jvm-metric=JVM Indices
|
||||
tab.summary.other-metric=Other Indices
|
||||
tab.summary.bottom-normal-tip=Please call apis before visiting this page!
|
||||
tab.summary.bottom-close-tip=KoTime switch was closed!
|
||||
|
||||
@ -23,9 +24,21 @@ tab.summary.response-metric.avg-num=Avg(ms)
|
||||
tab.summary.response-metric.max-num=Max(ms)
|
||||
tab.summary.response-metric.min-num=Min(ms)
|
||||
|
||||
tab.summary.sysusage-metric.cpu-usage=CPU Usage
|
||||
tab.summary.interface-metric.avg-call-num=Avg Call-Number
|
||||
tab.summary.interface-metric.max-call-num=Max Call-Number
|
||||
tab.summary.interface-metric.min-call-num=Min Call-Number
|
||||
|
||||
tab.summary.sysusage-metric.cpu-usage=CPU
|
||||
tab.summary.sysusage-metric.heap-memory=Heap Memory
|
||||
tab.summary.sysusage-metric.non-heap-memory=Non-Heap Memory
|
||||
tab.summary.sysusage-metric.physical-memory=Physical Memory
|
||||
tab.summary.sysusage-metric.eden-space=Eden
|
||||
tab.summary.sysusage-metric.survivor-space=Survivor
|
||||
tab.summary.sysusage-metric.old-gen=OldGen
|
||||
tab.summary.sysusage-metric.meta-space=Metaspace
|
||||
tab.summary.sysusage-metric.gc-num=GC
|
||||
tab.summary.sysusage-metric.thread-num=Thread Number
|
||||
tab.summary.sysusage-metric.loaded-class-num=Loaded Class
|
||||
|
||||
tab.summary.sysusage-metric.cpu-usage.user-usage=User Usage
|
||||
tab.summary.sysusage-metric.cpu-usage.sys-usage=System Usage
|
||||
@ -39,6 +52,14 @@ tab.summary.sysusage-metric.physical-memory.total=Total
|
||||
tab.summary.sysusage-metric.physical-memory.used=Used
|
||||
tab.summary.sysusage-metric.physical-memory.current-used=ThisUsed
|
||||
|
||||
tab.summary.sysusage-metric.gc-num.minor=Minor GC
|
||||
tab.summary.sysusage-metric.gc-num.full=Major/Full GC
|
||||
|
||||
tab.summary.sysusage-metric.thread-num.runnable=Runnable
|
||||
tab.summary.sysusage-metric.thread-num.deadlock=Deadlock
|
||||
|
||||
tab.summary.sysusage-metric.loaded-class-num.current=Current
|
||||
tab.summary.sysusage-metric.loaded-class-num.unloaded=Unloaded
|
||||
|
||||
tab.interface.search-tip=search method name or class name...
|
||||
tab.interface.interface-list.avg-tip=avg
|
||||
|
||||
@ -1,343 +0,0 @@
|
||||
function checkLogin() {
|
||||
$.get(contextPath+'/koTime/isLogin?kotoken=' + globalToken+"&project="+globalProject, function (data) {
|
||||
globalIsLogin = data['isLogin'] == 1 ? true : false;
|
||||
});
|
||||
if (globalNeedLogin == true && globalIsLogin == false) {
|
||||
UIkit.modal(document.getElementById("modal-login")).show();
|
||||
return;
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
function loadConfig(){
|
||||
$.get(contextPath+'/koTime/getConfig?kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
// let exceptionEnable = data['exceptionEnable'];
|
||||
//
|
||||
// let exceptionEnableDom = document.getElementById('exceptionEnable');
|
||||
// exceptionEnableDom.checked = exceptionEnable;
|
||||
//
|
||||
|
||||
let kotimeEnable = data['enable'];
|
||||
// let kotimeEnableDom = document.getElementById('kotimeEnable');
|
||||
// kotimeEnableDom.checked = kotimeEnable;
|
||||
|
||||
let apiTip = document.getElementById('apiTip');
|
||||
apiTip.innerHTML = kotimeEnable==true?"接口根据调用情况统计,未调用的接口无法被统计到,请先调用接口":"方法调用监测已关闭,数据将不会更新,需要开启请到配置面板";
|
||||
|
||||
let threshold = data['threshold'];
|
||||
let timeThresholdDom = document.getElementById('timeThreshold');
|
||||
timeThresholdDom.value = threshold;
|
||||
|
||||
// let logEnable = data['logEnable'];
|
||||
// let logEnableDom = document.getElementById('logEnable');
|
||||
// logEnableDom.checked = logEnable;
|
||||
|
||||
let language = data['language'];
|
||||
$("#languageSwitch").val(language)
|
||||
});
|
||||
}
|
||||
|
||||
function addConfigEvent(){
|
||||
|
||||
|
||||
document.getElementById('languageSwitch').onchange = function(){
|
||||
let selectedObj = document.getElementById('languageSwitch');
|
||||
$.ajax({type:'POST',url:contextPath+'/koTime/updateConfig?kotoken='+globalToken+"&project="+globalProject,data:JSON.stringify({language:selectedObj.options[selectedObj.selectedIndex].value}),dataType:'json', headers: {'Content-Type': 'application/json' }});
|
||||
};
|
||||
|
||||
document.getElementById("timeThresholdYes").onclick = function(){
|
||||
$.ajax({type:'POST',url:contextPath+'/koTime/updateConfig?kotoken='+globalToken+"&project="+globalProject,data:JSON.stringify({threshold:document.getElementById('timeThreshold').value}),dataType:'json', headers: {'Content-Type': 'application/json' }});
|
||||
};
|
||||
}
|
||||
|
||||
function loadStatistic(){
|
||||
$.get(contextPath+'/koTime/getStatistic?kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
let totalNum = data['totalNum'];
|
||||
let systemTotalNum = document.getElementById("systemTotalNum");
|
||||
systemTotalNum.innerHTML=totalNum;
|
||||
|
||||
let normalNum = data['normalNum'];
|
||||
let systemNormalNum = document.getElementById("systemNormalNum");
|
||||
systemNormalNum.innerHTML=normalNum;
|
||||
|
||||
let delayNum = data['delayNum'];
|
||||
let systemDelayNum = document.getElementById("systemDelayNum");
|
||||
systemDelayNum.innerHTML=delayNum;
|
||||
if (delayNum>0) {
|
||||
document.getElementById("systemDelayNum-div").className+=' uk-label-danger';
|
||||
}else {
|
||||
document.getElementById("systemDelayNum-div").className+=' uk-label-success';
|
||||
};
|
||||
|
||||
let avgRunTime = data['avgRunTime'];
|
||||
let systemAvgRunTime = document.getElementById("systemAvgRunTime");
|
||||
systemAvgRunTime.innerHTML=avgRunTime;
|
||||
if (avgRunTime>globalThreshold) {
|
||||
document.getElementById("systemAvgRunTime-div").className+=' uk-label-danger';
|
||||
}else {
|
||||
document.getElementById("systemAvgRunTime-div").className+=' uk-label-success';
|
||||
};
|
||||
|
||||
let maxRunTime = data['maxRunTime'];
|
||||
let systemMaxRunTime = document.getElementById("systemMaxRunTime");
|
||||
systemMaxRunTime.innerHTML=maxRunTime;
|
||||
if (maxRunTime>globalThreshold) {
|
||||
document.getElementById("systemMaxRunTime-div").className+=' uk-label-danger';
|
||||
}else {
|
||||
document.getElementById("systemMaxRunTime-div").className+=' uk-label-success';
|
||||
};
|
||||
|
||||
|
||||
let minRunTime = data['minRunTime'];
|
||||
let systemMinRunTime = document.getElementById("systemMinRunTime");
|
||||
systemMinRunTime.innerHTML=minRunTime;
|
||||
if (minRunTime>globalThreshold) {
|
||||
document.getElementById("systemMinRunTime-div").className+=' uk-label-danger';
|
||||
}else {
|
||||
document.getElementById("systemMinRunTime-div").className+=' uk-label-success';
|
||||
};
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function loadApis(){
|
||||
let searchText = $("#searchText").val();
|
||||
$.get(contextPath+'/koTime/getApis?question='+searchText+'&kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
let element = document.getElementById('apiList');
|
||||
html = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let id = data[i]['id'];
|
||||
let className = data[i]['className'];
|
||||
let methodName = data[i]['methodName'];
|
||||
let avgRunTime = data[i]['avgRunTime'];
|
||||
let methodType = data[i]['methodType'];
|
||||
let routeName = data[i]['routeName'];
|
||||
|
||||
let apiId = className+"."+methodName;
|
||||
let color = avgRunTime>globalThreshold?'danger':'success';
|
||||
if (methodType=='Controller' && routeName!=null && routeName!='') {
|
||||
html += "<li onclick=\"showMethods('"+id+"')\" style='color: #333;font-weight: 400;font-size: 14px;' id=\""+apiId+"-list\">"+ className+"#<span style='font-size: 16px;font-weight: 500;'>"+methodName+"</span> (<span style='font-size: 14px;font-weight: 430;color:#032b11'>"+routeName+"</span>)   <span style='font-size: 10px;' class=\"uk-label uk-label-"+color+"\">avg "+avgRunTime+" ms</span></li>";
|
||||
}else{
|
||||
html += "<li onclick=\"showMethods('"+id+"')\" style='color: #333;font-weight: 400;font-size: 14px;' id=\""+apiId+"-list\">"+ className+"#<span style='font-size: 16px;font-weight: 500;'>"+methodName+"</span>   <span style='font-size: 10px;' class=\"uk-label uk-label-"+color+"\">avg "+avgRunTime+" ms</span></li>";
|
||||
}
|
||||
};
|
||||
element.innerHTML = html;
|
||||
});
|
||||
}
|
||||
|
||||
function loadExceptions(){
|
||||
$.get(contextPath+'/koTime/getExceptions?kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
let element = document.getElementById('exceptionList');
|
||||
html = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let id = data[i]['id'];
|
||||
let className = data[i]['className'];
|
||||
let message = data[i]['message'];
|
||||
html += "<li onclick=\"showExceptions('"+id+"','"+message+"')\" style='' id=\""+id+"\"><span style='font-size: 16px;font-weight: 500;'>"+className+"</span>   <span style='font-size: 10px;' class=\"uk-label uk-label-danger\">"+message+"</span></li>";
|
||||
};
|
||||
element.innerHTML = html;
|
||||
});
|
||||
}
|
||||
|
||||
let methodParamMap = new Map();
|
||||
function paramGraph(e) {
|
||||
let clickNode = e.currentTarget;
|
||||
if (clickNode==null){
|
||||
return
|
||||
};
|
||||
let clickNodeId = clickNode.id;
|
||||
if (methodParamMap.has(clickNodeId+"ana")) {
|
||||
graph.removeNode(clickNodeId+"ana")
|
||||
methodParamMap.delete(clickNodeId+"ana")
|
||||
}else {
|
||||
$.get(contextPath+'/koTime/getParamGraph?kotoken='+globalToken+"&methodId="+clickNodeId.replace('node','')+"&project="+globalProject, function (data) {
|
||||
let datas = []
|
||||
for(let key in data) {
|
||||
datas.push( {"name":key+":avg "+data[key]['avgRunTime']+" ms"})
|
||||
};
|
||||
let paramGraphData = {
|
||||
"id":clickNodeId+"ana",
|
||||
"from":clickNodeId,
|
||||
"title":{'name':"Combination of parameters"},
|
||||
"data":datas,
|
||||
'style':{
|
||||
'title-color':'#427b72',
|
||||
'border-color':'#427b72',
|
||||
'data-font-size':'10px',
|
||||
'title-font-size':'12px'
|
||||
}
|
||||
}
|
||||
let clickNodeX = Number(clickNode.getAttribute("x"));
|
||||
let clickNodeY = Number(clickNode.getAttribute("y"));
|
||||
graph.createNode(paramGraphData,clickNodeX,clickNodeY-100);
|
||||
// graph.createNode(paramGraphData,e.x+150,e.y-30);
|
||||
methodParamMap.set(clickNodeId+"ana","")
|
||||
});
|
||||
}
|
||||
}
|
||||
function formData(data) {
|
||||
if (data['avgRunTime']>globalThreshold) {
|
||||
data['style'] = {
|
||||
'title-color':'#c71335',
|
||||
'border-color':'#c71335',
|
||||
'data-font-size':'10px',
|
||||
'title-font-size':'12px'
|
||||
}
|
||||
}
|
||||
else{
|
||||
data['style'] = {
|
||||
'title-color':'#375d46',
|
||||
'border-color':'#375d46',
|
||||
'data-font-size':'10px',
|
||||
'title-font-size':'12px'
|
||||
}
|
||||
};
|
||||
data['title'] = {'name':data['name']};
|
||||
data['data'] = [
|
||||
{'name':'<span style="color:gray">type:</span>'+data['methodType']},
|
||||
{'name':'<span style="color:gray">avg time:</span>'+data['avgRunTime']+' ms'},
|
||||
{'name':'<span style="color:gray">max time:</span>'+data['maxRunTime']+' ms'},
|
||||
{'name':'<span style="color:gray">min time:</span>'+data['minRunTime']+' ms'}
|
||||
];
|
||||
if (data['exceptionNum']!=null && data['exceptionNum']>0) {
|
||||
data['data'].push({'name':'<span style="color:gray">number of exception:</span>'+data['exceptionNum']+' 个'});
|
||||
}
|
||||
data["dblclick"]="paramGraph";
|
||||
return data;
|
||||
};
|
||||
|
||||
|
||||
function showMethods(name) {
|
||||
let exceptionDetailDom = document.getElementById('layerDemo');
|
||||
exceptionDetailDom.innerHTML = "";
|
||||
let options = {
|
||||
'link-start-offsetx':8,
|
||||
'link-start-offsety':0,
|
||||
'link-end-offsetx':+10,
|
||||
'link-end-offsety':0,
|
||||
'link-width-offset':0
|
||||
};
|
||||
graph = new MetricFlow("layerDemo",options);
|
||||
graph.threshold = globalThreshold;
|
||||
UIkit.notification.closeAll();
|
||||
UIkit.modal(document.getElementById("modal-method")).show();
|
||||
|
||||
$.get(contextPath+'/koTime/getTree?methodName=' + name+'&kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
let rootX = 100;
|
||||
let rootY = $(window).get(0).innerHeight / 2-50;
|
||||
data['x'] = rootX;
|
||||
data['y'] = rootY;
|
||||
graph.createNodes(data,formData);
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
function showExceptions(id,message) {
|
||||
$.get(contextPath+'/koTime/getMethodsByExceptionId?exceptionId=' + id+'&message='+message+'&kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
let html = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
html +=
|
||||
"<ul class=\"uk-list uk-list-divider\">\n" +
|
||||
"\t<li id=\"exception-class\">Class:"+data[i].occurClassName+"</li>\n" +
|
||||
"\t<li id=\"exception-method\">Method:"+data[i].methodName+"</li>\n" +
|
||||
"\t<li id=\"exception-line\">Line:<span class=\"uk-label uk-label-success\">"+data[i].location+"</span></li>\n" +
|
||||
"\t<li id=\"exception-message\">Exception message:<span class=\"uk-label uk-label-danger\">"+data[i].message+"</span></li>\n" +
|
||||
"</ul>"
|
||||
if (data.length-1>i) {
|
||||
html +='<hr class="uk-divider-icon">'
|
||||
}
|
||||
};
|
||||
|
||||
let exceptionDetailDom = document.getElementById('exception-detail');
|
||||
exceptionDetailDom.innerHTML = html;
|
||||
UIkit.notification.closeAll();
|
||||
UIkit.modal(document.getElementById("modal-exception")).show();
|
||||
});
|
||||
};
|
||||
|
||||
function login() {
|
||||
let userId = $("#userName").val()
|
||||
let password = $("#userPassword").val()
|
||||
if (userId==undefined || userId.length<1 || password==undefined || password.length<1 ) {
|
||||
UIkit.notification.closeAll()
|
||||
UIkit.notification("<font color='red'>请正确输入用户名和密码</font>",{});
|
||||
return
|
||||
}
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:contextPath+"/koTime/login",
|
||||
data:JSON.stringify({'userName':userId,'password':password}),
|
||||
dataType:'json',
|
||||
headers: {'Content-Type': 'application/json' },
|
||||
success:function (re) {
|
||||
if (re['state']==1) {
|
||||
UIkit.notification("<font color='green'>Login was successful</font>",{});
|
||||
UIkit.notification.closeAll()
|
||||
sessionStorage.setItem("kotimeToken", re["token"]);
|
||||
location.reload();
|
||||
}else {
|
||||
UIkit.notification("<font color='red'>Error user or password</font>",{});
|
||||
}
|
||||
},
|
||||
error:function (re) {
|
||||
console.log(re)
|
||||
}
|
||||
});
|
||||
}
|
||||
function searchTip(e){
|
||||
let question = $('#searchText').val()
|
||||
$.get(contextPath+'/koTime/getApiTips?question='+question+'&kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
$("#condidates").html("")
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let name = data[i];
|
||||
$("#condidates").append('<option value="'+name+'"/>');
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function loadProjects(){
|
||||
$.get(contextPath+'/koTime/getProjects?kotoken='+globalToken+"&project=all", function (data) {
|
||||
$("#projects").html("")
|
||||
$("#projects").append('<option selected hidden disabled value="">Select you project</option>');
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let name = data[i];
|
||||
$("#projects").append(`<option value="${name}">${name}</option>`);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function searchApis(e) {
|
||||
if (e.keyCode == 13) {
|
||||
let question = $('#searchText').val()
|
||||
$.get(contextPath+'/koTime/getApis?question='+question+'&kotoken='+globalToken+"&project="+globalProject, function (data) {
|
||||
let element = document.getElementById('apiList');
|
||||
html = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let id = data[i]['id'];
|
||||
let className = data[i]['className'];
|
||||
let methodName = data[i]['methodName'];
|
||||
let avgRunTime = data[i]['avgRunTime'];
|
||||
let methodType = data[i]['methodType'];
|
||||
let routeName = data[i]['routeName'];
|
||||
let apiId = className+"."+methodName;
|
||||
let color = avgRunTime>globalThreshold?'danger':'success';
|
||||
|
||||
if (methodType=='Controller' && routeName!=null && routeName!='') {
|
||||
html += "<li onclick=\"showMethods('"+id+"')\" style='color: #333;font-weight: 400;font-size: 14px;' id=\""+apiId+"-list\">"+ className+"#<span style='font-size: 16px;font-weight: 500;'>"+methodName+"</span> (<span style='font-size: 14px;font-weight: 430;color:#032b11'>"+routeName+"</span>)   <span style='font-size: 10px;' class=\"uk-label uk-label-"+color+"\">avg "+avgRunTime+" ms</span></li>";
|
||||
}else{
|
||||
html += "<li onclick=\"showMethods('"+id+"')\" style='color: #333;font-weight: 400;font-size: 14px;' id=\""+apiId+"-list\">"+ className+"#<span style='font-size: 16px;font-weight: 500;'>"+methodName+"</span>   <span style='font-size: 10px;' class=\"uk-label uk-label-"+color+"\">avg "+avgRunTime+" ms</span></li>";
|
||||
}
|
||||
};
|
||||
element.innerHTML = html;
|
||||
});
|
||||
$('#searchText').val('');
|
||||
}
|
||||
}
|
||||
|
||||
function getProjectName(){
|
||||
globalProject = document.querySelector("#projects").value;
|
||||
loadStatistic();
|
||||
loadApis();
|
||||
loadExceptions();
|
||||
}
|
||||
@ -30,9 +30,26 @@ function post(url,data,successfun,errorFun) {
|
||||
});
|
||||
}
|
||||
|
||||
function postFormData(url,data,successfun,errorFun) {
|
||||
function put(url,data,successfun,errorFun) {
|
||||
fetch(url, {
|
||||
method: 'post',
|
||||
method: 'put',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}).then(response => response.json())
|
||||
.then(json => {
|
||||
successfun(json);
|
||||
}).catch(e => {
|
||||
if (errorFun) {
|
||||
errorFun(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function putFormData(url,data,successfun,errorFun) {
|
||||
fetch(url, {
|
||||
method: 'put',
|
||||
body: data
|
||||
}).then(response => response.json())
|
||||
.then(json => {
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
|
||||
function refreshData() {
|
||||
get(concatToken('contextPath/koTime/isLogin'), function (data) {
|
||||
globalIsLogin = data['isLogin'] == 1 ? true : false;
|
||||
globalIsLogin = data['content']['isLogin'] == 1 ? true : false;
|
||||
if (globalNeedLogin == true && globalIsLogin == false) {
|
||||
UIkit.modal(getDom("modal-login")).show();
|
||||
return;
|
||||
@ -47,7 +47,15 @@
|
||||
loadExceptions();
|
||||
loadCpuInfo();
|
||||
loadHeapMemoryInfo();
|
||||
loadNonHeapMemoryInfo();
|
||||
loadPhysicalMemoryInfo();
|
||||
loadEdenSpace();
|
||||
loadSurvivorSpace();
|
||||
loadOldGenSpace();
|
||||
loadMetaspace();
|
||||
loadGcUsage();
|
||||
loadThreadUsage();
|
||||
loadClassUsage();
|
||||
loadThreadsInfo();
|
||||
loadDynamicProperties();
|
||||
}
|
||||
@ -55,7 +63,12 @@
|
||||
}
|
||||
|
||||
function loadExceptions() {
|
||||
get(concatToken('contextPath/koTime/getExceptions'), function (data) {
|
||||
get(concatToken('contextPath/koTime/exceptions'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入exceptions失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let element = getDom('exceptionList');
|
||||
html = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
@ -74,7 +87,12 @@
|
||||
let searchText = searchDom.value;
|
||||
let apiSortName = getDom('apiSortName')
|
||||
let apiSortType = getDom('apiSortType')
|
||||
get(concatToken(`contextPath/koTime/getApis?question=${searchText}&orderBy=${apiSortName.value}&sort=${apiSortType.value}`), function (data) {
|
||||
get(concatToken(`contextPath/koTime/interfaces?question=${searchText}&orderBy=${apiSortName.value}&sort=${apiSortType.value}`), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入interfaces失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
searchDom.value='';
|
||||
let element = getDom('apiList');
|
||||
html = '';
|
||||
@ -104,7 +122,12 @@
|
||||
}
|
||||
|
||||
function loadStatistic() {
|
||||
get(concatToken('contextPath/koTime/getStatistic'), function (data) {
|
||||
get(concatToken('contextPath/koTime/interfaces/usage'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入interfaces/usage失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let totalNum = data['totalNum'];
|
||||
let systemTotalNum = getDom("systemTotalNum");
|
||||
systemTotalNum.innerHTML = totalNum;
|
||||
@ -145,15 +168,27 @@
|
||||
getDom("systemMinRunTime").style.color = '#cc0c0c';
|
||||
} else {
|
||||
getDom("systemMinRunTime").style.color = '#29da93';
|
||||
}
|
||||
;
|
||||
};
|
||||
|
||||
let avgCallNum = data['avgCallNum'];
|
||||
let systemAvgCallNumDom = getDom("systemAvgCallNum");
|
||||
systemAvgCallNumDom.innerHTML = avgCallNum;
|
||||
|
||||
let minCallNum = data['minCallNum'];
|
||||
let systemMinCallNumDom = getDom("systemMinCallNum");
|
||||
systemMinCallNumDom.innerHTML = minCallNum;
|
||||
|
||||
|
||||
let maxCallNum = data['maxCallNum'];
|
||||
let systemMaxCallNumDom = getDom("systemMaxCallNum");
|
||||
systemMaxCallNumDom.innerHTML = maxCallNum;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function addConfigEvent() {
|
||||
getDom('kotimeEnable').onclick = function () {
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{enable: getDom('kotimeEnable').checked},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{enable: getDom('kotimeEnable').checked},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}');
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}');
|
||||
@ -161,7 +196,7 @@
|
||||
};
|
||||
|
||||
getDom('exceptionEnable').onclick = function () {
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{exceptionEnable: getDom('exceptionEnable').checked},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{exceptionEnable: getDom('exceptionEnable').checked},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}')
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}')
|
||||
@ -169,7 +204,7 @@
|
||||
};
|
||||
|
||||
getDom('logEnable').onclick = function () {
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{logEnable: getDom('logEnable').checked},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{logEnable: getDom('logEnable').checked},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}')
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}')
|
||||
@ -177,7 +212,7 @@
|
||||
};
|
||||
|
||||
getDom('mailEnable').onclick = function () {
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{mailEnable: getDom('mailEnable').checked},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{mailEnable: getDom('mailEnable').checked},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}')
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}')
|
||||
@ -185,7 +220,7 @@
|
||||
};
|
||||
|
||||
getDom('abbreviationEnable').onclick = function () {
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{abbreviationEnable: getDom('abbreviationEnable').checked},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{abbreviationEnable: getDom('abbreviationEnable').checked},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}')
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}')
|
||||
@ -194,7 +229,7 @@
|
||||
|
||||
getDom('languageSwitch').onclick = function () {
|
||||
let selectedObj = getDom('languageSwitch');
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{language: selectedObj.options[selectedObj.selectedIndex].value},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{language: selectedObj.options[selectedObj.selectedIndex].value},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}')
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}')
|
||||
@ -202,7 +237,7 @@
|
||||
};
|
||||
|
||||
getDom('timeThresholdYes').onclick = function () {
|
||||
post(concatToken('contextPath/koTime/updateConfig'),{threshold: getDom('timeThreshold').value},function (res) {
|
||||
put(concatToken('contextPath/koTime/configs'),{threshold: getDom('timeThreshold').value},function (res) {
|
||||
noticeSuccess('{{tab.configuration.kotime-config.change-ok-tip}}')
|
||||
},function () {
|
||||
noticeError('{{tab.configuration.kotime-config.change-fail-tip}}')
|
||||
@ -220,7 +255,12 @@
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
get(concatToken('contextPath/koTime/getConfig'), function (data) {
|
||||
get(concatToken('contextPath/koTime/configs'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入configs失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let versionNoticeEnable = data['versionNotice'];
|
||||
if (versionNoticeEnable) {
|
||||
loadLatestVersion();
|
||||
@ -274,7 +314,12 @@
|
||||
graph.removeNode(clickNodeId + "ana")
|
||||
methodParamMap.delete(clickNodeId + "ana")
|
||||
} else {
|
||||
get(concatToken('contextPath/koTime/getParamGraph' + "?methodId=" + clickNodeId.replace('node', '')), function (data) {
|
||||
get(concatToken('contextPath/koTime/interfaces/'+clickNodeId.replace('node', '')+'/paramMetric'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入paramMetric失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let datas = []
|
||||
for (let key in data) {
|
||||
datas.push({"name": key + ":{{tab.interface.interface-list.show-metric.avg}} " + data[key]['avgRunTime'] + " ms"})
|
||||
@ -334,7 +379,7 @@
|
||||
};
|
||||
|
||||
|
||||
function showMethods(name) {
|
||||
function showMethods(methodId) {
|
||||
let exceptionDetailDom = getDom('layerDemo');
|
||||
exceptionDetailDom.innerHTML = "";
|
||||
let options = {
|
||||
@ -349,9 +394,14 @@
|
||||
UIkit.notification.closeAll();
|
||||
UIkit.modal(getDom("modal-method")).show();
|
||||
|
||||
get(concatToken('contextPath/koTime/getTree?methodName=' + name), function (data) {
|
||||
get(concatToken('contextPath/koTime/interfaces/'+methodId+'/tree'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入tree失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let rootX = 100;
|
||||
let rootY = $(window).get(0).innerHeight / 2 - 50;
|
||||
let rootY = window.innerHeight / 2 - 50;
|
||||
data['x'] = rootX;
|
||||
data['y'] = rootY;
|
||||
graph.createNodes(data, formData);
|
||||
@ -361,7 +411,12 @@
|
||||
};
|
||||
|
||||
function showExceptions(id, message) {
|
||||
get(concatToken('contextPath/koTime/getMethodsByExceptionId?exceptionId=' + id + '&message=' + message), function (data) {
|
||||
get(concatToken('contextPath/koTime/exceptions/' + id + '/details?message=' + message), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入tree失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let html = '';
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
html +=
|
||||
@ -394,7 +449,7 @@
|
||||
post("contextPath/koTime/login",{'userName': userId, 'password': password},function (re) {
|
||||
if (re['state'] == 1) {
|
||||
noticeSuccess('登录成功')
|
||||
sessionStorage.setItem("kotimeToken", re["token"]);
|
||||
sessionStorage.setItem("kotimeToken", re['content']["token"]);
|
||||
location.reload();
|
||||
} else {
|
||||
noticeError('用户名或密码错误')
|
||||
@ -406,7 +461,12 @@
|
||||
|
||||
function searchTip(e) {
|
||||
let question = $('#searchText').val()
|
||||
get(concatToken('contextPath/koTime/getApiTips?question=' + question), function (data) {
|
||||
get(concatToken('contextPath/koTime/interfaces/searchCondidate?question=' + question), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入interfaces/searchCondidate失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
$("#condidates").html("")
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
let name = data[i];
|
||||
@ -436,8 +496,7 @@
|
||||
return;
|
||||
}
|
||||
formData.append('classFile', file);
|
||||
formData.append('className', className);
|
||||
postFormData(concatToken('contextPath/koTime/updateClass'),formData,function (res) {
|
||||
putFormData(concatToken('contextPath/koTime/classes/'+className+'/replace'),formData,function (res) {
|
||||
if (res['state'] == 1) {
|
||||
noticeSuccess('{{tab.hotupdate.change-ok-tip}}')
|
||||
} else {
|
||||
@ -455,7 +514,7 @@
|
||||
let propertiesDom = document.querySelector("#dynamicText");
|
||||
let propertiesText = propertiesDom.value;
|
||||
if (propertiesText && propertiesText.indexOf("=") > 0) {
|
||||
post(concatToken('contextPath/koTime/updateDynamicProperties'),{text: propertiesText},function (re) {
|
||||
put(concatToken('contextPath/koTime/dynamicProperties'),{text: propertiesText.trim()},function (re) {
|
||||
noticeSuccess('{{tab.configuration.dynamic-config.change-ok-tip}}')
|
||||
},function (re) {
|
||||
noticeError('{{tab.configuration.dynamic-config.change-fail-tip}}')
|
||||
@ -467,8 +526,8 @@
|
||||
}
|
||||
|
||||
function loadDynamicProperties() {
|
||||
get(concatToken('contextPath/koTime/getDynamicProperties'), function (data) {
|
||||
let text = data['data'];
|
||||
get(concatToken('contextPath/koTime/dynamicProperties'), function (res) {
|
||||
let text = res['content'];
|
||||
document.querySelector("#dynamicText").value = text;
|
||||
});
|
||||
}
|
||||
@ -484,7 +543,12 @@
|
||||
}
|
||||
|
||||
function loadCpuInfo() {
|
||||
get(concatToken('contextPath/koTime/getCpuInfo'), function (data) {
|
||||
get(concatToken('contextPath/koTime/cpus/usage'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入cpus/usage失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let systemLoad = data['systemLoad'] * 100;
|
||||
let userRate = data['userRate'] * 100;
|
||||
let sysRate = data['sysRate'] * 100;
|
||||
@ -501,12 +565,16 @@
|
||||
document.querySelector("#cpuSysRate").innerHTML = `${sysRate.toFixed(2)}%`;
|
||||
document.querySelector("#cpuUserRate").innerHTML = `${userRate.toFixed(2)}%`;
|
||||
document.querySelector("#cpuLogicalAmount").innerHTML = `{{tab.summary.sysusage-metric.cpu-usage}}(${logicalNum}):`;
|
||||
document.querySelector("#cpuWaitRate").innerHTML = `${waitRate.toFixed(2)}%`;
|
||||
});
|
||||
}
|
||||
|
||||
function loadHeapMemoryInfo() {
|
||||
get(concatToken('contextPath/koTime/getHeapMemoryInfo'), function (data) {
|
||||
get(concatToken('contextPath/koTime/memories/heap'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入memories/heap失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
// let initValue = data['initValue'] / 1024 / 1024;
|
||||
// let maxValue = data['maxValue'] / 1024 / 1024;
|
||||
// let usedValue = data['usedValue'] / 1024 / 1024;
|
||||
@ -528,8 +596,42 @@
|
||||
});
|
||||
}
|
||||
|
||||
function loadNonHeapMemoryInfo() {
|
||||
get(concatToken('contextPath/koTime/memories/nonHeap'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入memories/nonHeap失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let initValue = getSize(data['initValue']);
|
||||
let maxValue = getSize(data['maxValue']);
|
||||
let usedValue = getSize(data['usedValue']);
|
||||
let usedRate = data['usedRate'] * 100;
|
||||
var nonheapUsedRateDom = document.querySelector("#nonHeapUsedRate");
|
||||
if (usedRate > 50) {
|
||||
nonheapUsedRateDom.style.color = '#cc0c0c';
|
||||
} else {
|
||||
nonheapUsedRateDom.style.color = '#29da93';
|
||||
}
|
||||
;
|
||||
document.querySelector("#nonHeapInit").innerHTML = initValue;
|
||||
document.querySelector("#nonHeapMax").innerHTML = maxValue;
|
||||
document.querySelector("#nonHeapUsed").innerHTML = usedValue;
|
||||
if (data['maxValue']==-1) {
|
||||
nonheapUsedRateDom.innerHTML = `-%`;
|
||||
}else {
|
||||
nonheapUsedRateDom.innerHTML = `${usedRate.toFixed(2)}%`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPhysicalMemoryInfo() {
|
||||
get(concatToken('contextPath/koTime/getPhysicalMemoryInfo'), function (data) {
|
||||
get(concatToken('contextPath/koTime/memories/physical'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入memories/physical失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
// let initValue = data['initValue'] / 1024 / 1024;
|
||||
// let thisUsedValue = data['thisUsedValue'] / 1024 / 1024;
|
||||
// let usedValue = data['usedValue'] / 1024 / 1024;
|
||||
@ -553,6 +655,171 @@
|
||||
});
|
||||
}
|
||||
|
||||
function loadEdenSpace() {
|
||||
get(concatToken('contextPath/koTime/jvmSpaces/edenSpace'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载jvmSpaces/edenSpace失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let initValue = getSize(data['initValue']);
|
||||
let maxValue = getSize(data['maxValue']);
|
||||
let usedValue = getSize(data['usedValue']);
|
||||
let usedRate = data['usedRate'] * 100;
|
||||
let edenSpaceUsedRateDom = document.querySelector("#edenSpaceUsedRate");
|
||||
if (usedRate > 50) {
|
||||
edenSpaceUsedRateDom.style.color = '#cc0c0c';
|
||||
} else {
|
||||
edenSpaceUsedRateDom.style.color = '#29da93';
|
||||
}
|
||||
;
|
||||
document.querySelector("#edenSpaceInit").innerHTML = initValue;
|
||||
document.querySelector("#edenSpaceMax").innerHTML = maxValue;
|
||||
document.querySelector("#edenSpaceUsed").innerHTML = usedValue;
|
||||
edenSpaceUsedRateDom.innerHTML = `${usedRate.toFixed(2)}%`;
|
||||
});
|
||||
}
|
||||
|
||||
function loadSurvivorSpace() {
|
||||
get(concatToken('contextPath/koTime/jvmSpaces/survivorSpace'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载jvmSpaces/survivorSpace失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let initValue = getSize(data['initValue']);
|
||||
let maxValue = getSize(data['maxValue']);
|
||||
let usedValue = getSize(data['usedValue']);
|
||||
let usedRate = data['usedRate'] * 100;
|
||||
let survivorSpaceUsedRateDom = document.querySelector("#survivorSpaceUsedRate");
|
||||
if (usedRate > 50) {
|
||||
survivorSpaceUsedRateDom.style.color = '#cc0c0c';
|
||||
} else {
|
||||
survivorSpaceUsedRateDom.style.color = '#29da93';
|
||||
}
|
||||
;
|
||||
document.querySelector("#survivorSpaceInit").innerHTML = initValue;
|
||||
document.querySelector("#survivorSpaceMax").innerHTML = maxValue;
|
||||
document.querySelector("#survivorSpaceUsed").innerHTML = usedValue;
|
||||
survivorSpaceUsedRateDom.innerHTML = `${usedRate.toFixed(2)}%`;
|
||||
});
|
||||
}
|
||||
|
||||
function loadOldGenSpace() {
|
||||
get(concatToken('contextPath/koTime/jvmSpaces/oldGen'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载jvmSpaces/oldGen失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let initValue = getSize(data['initValue']);
|
||||
let maxValue = getSize(data['maxValue']);
|
||||
let usedValue = getSize(data['usedValue']);
|
||||
let usedRate = data['usedRate'] * 100;
|
||||
let oldGenUsedRateDom = document.querySelector("#oldGenUsedRate");
|
||||
if (usedRate > 50) {
|
||||
oldGenUsedRateDom.style.color = '#cc0c0c';
|
||||
} else {
|
||||
oldGenUsedRateDom.style.color = '#29da93';
|
||||
}
|
||||
;
|
||||
document.querySelector("#oldGenInit").innerHTML = initValue;
|
||||
document.querySelector("#oldGenMax").innerHTML = maxValue;
|
||||
document.querySelector("#oldGenUsed").innerHTML = usedValue;
|
||||
oldGenUsedRateDom.innerHTML = `${usedRate.toFixed(2)}%`;
|
||||
});
|
||||
}
|
||||
|
||||
function loadMetaspace() {
|
||||
get(concatToken('contextPath/koTime/jvmSpaces/metaspace'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载jvmSpaces/metaspace失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let initValue = getSize(data['initValue']);
|
||||
let maxValue = getSize(data['maxValue']);
|
||||
let usedValue = getSize(data['usedValue']);
|
||||
let usedRate = data['usedRate'] * 100;
|
||||
let metaspaceUsedRateDom = document.querySelector("#metaspaceUsedRate");
|
||||
if (usedRate > 50) {
|
||||
metaspaceUsedRateDom.style.color = '#cc0c0c';
|
||||
} else {
|
||||
metaspaceUsedRateDom.style.color = '#29da93';
|
||||
}
|
||||
;
|
||||
document.querySelector("#metaspaceInit").innerHTML = initValue;
|
||||
document.querySelector("#metaspaceMax").innerHTML = maxValue;
|
||||
document.querySelector("#metaspaceUsed").innerHTML = usedValue;
|
||||
if (data['maxValue']==-1) {
|
||||
metaspaceUsedRateDom.innerHTML = `-%`;
|
||||
}else {
|
||||
metaspaceUsedRateDom.innerHTML = `${usedRate.toFixed(2)}%`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadGcUsage() {
|
||||
get(concatToken('contextPath/koTime/gcs/usage'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载gcs/usage失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let totalNum = data['totalNum'];
|
||||
let fullNum = data['fullNum'];
|
||||
let minorNum = data['minorNum'];
|
||||
|
||||
document.querySelector("#gcTotalNum").innerHTML = totalNum;
|
||||
document.querySelector("#gcMinorNum").innerHTML = minorNum;
|
||||
document.querySelector("#gcFullNum").innerHTML = fullNum;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function loadThreadUsage() {
|
||||
get(concatToken('contextPath/koTime/threads/usage'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载threads/usage失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let totalNum = data['totalNum'];
|
||||
let runnableNum = data['runnableNum'];
|
||||
let deadlockNum = data['deadLockNum'];
|
||||
|
||||
let threadLockNumDom = document.querySelector("#threadLockNum");
|
||||
if (deadlockNum > 0) {
|
||||
threadLockNumDom.style.color = '#cc0c0c';
|
||||
} else {
|
||||
threadLockNumDom.style.color = '#29da93';
|
||||
}
|
||||
|
||||
document.querySelector("#threadTotalNum").innerHTML = totalNum;
|
||||
document.querySelector("#threadRunnableNum").innerHTML = runnableNum;
|
||||
threadLockNumDom.innerHTML = deadlockNum;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function loadClassUsage() {
|
||||
get(concatToken('contextPath/koTime/classes/usage'), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载classes/usage失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let totalNum = data['totalClassNum'];
|
||||
let currentClassNum = data['currentClassNum'];
|
||||
let unloadedClassNum = data['unloadedClassNum'];
|
||||
|
||||
document.querySelector("#classTotalNum").innerHTML = totalNum;
|
||||
document.querySelector("#classCurrentNum").innerHTML = currentClassNum;
|
||||
document.querySelector("#classDeleteNum").innerHTML = unloadedClassNum;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
const cpuUsageColorMap = {
|
||||
'RED': '#cc0c0c',
|
||||
'YELLOW': '#f0ad4e',
|
||||
@ -573,7 +840,12 @@
|
||||
|
||||
function loadThreadsInfo(queryState) {
|
||||
queryState = queryState || '';
|
||||
get(concatToken('contextPath/koTime/getThreadsInfo?state=' + queryState), function (data) {
|
||||
get(concatToken('contextPath/koTime/threads?state=' + queryState), function (res) {
|
||||
if (res['state']==0) {
|
||||
noticeError("载入threads失败!");
|
||||
return;
|
||||
}
|
||||
let data = res['content'];
|
||||
let statistics = data['statistics'];
|
||||
let all = statistics['all'];
|
||||
let RUNNABLE = statistics['RUNNABLE'] || 0;
|
||||
@ -592,9 +864,9 @@
|
||||
let threads = data['threads'];
|
||||
let colors = {
|
||||
'RUNNABLE': '#32d296',
|
||||
'BLOCKED': '#cc0c0c',
|
||||
'WAITING': '#ad7070',
|
||||
'TIMED_WAITING': '#ad7070'
|
||||
'BLOCKED': '#e0ce86',
|
||||
'WAITING': '#eec793',
|
||||
'TIMED_WAITING': '#d99292'
|
||||
}
|
||||
for (let i = 0; i < threads.length; i++) {
|
||||
let thread = threads[i];
|
||||
@ -604,9 +876,14 @@
|
||||
let state = thread['state'];
|
||||
let stacks = thread['stacks'];
|
||||
let cpuUsage = thread['cpuUsage'];
|
||||
let deadLock = thread['deadLock'];
|
||||
let cpuUsageColor = getCpuUsageColor(cpuUsage);
|
||||
threadMap[id + ''] = stacks;
|
||||
html += `<li onclick="showThreadInfo('${id}')" class='common-li'>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">{{tab.thread.thread-list.cpu-usage}}:${cpuUsage}%</span> <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span></li>`;
|
||||
if (deadLock) {
|
||||
html += `<li onclick="showThreadInfo('${id}')" class='common-li'>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">{{tab.thread.thread-list.cpu-usage}}:${cpuUsage}%</span> <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span> <span style='font-size: 10px;background-color: #ec2147;' class="uk-label">DEADLOCK</span></li>`;
|
||||
}else {
|
||||
html += `<li onclick="showThreadInfo('${id}')" class='common-li'>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">{{tab.thread.thread-list.cpu-usage}}:${cpuUsage}%</span> <span style='font-size: 10px;background-color: ${colors[state]};' class="uk-label uk-label-success">${state}</span></li>`;
|
||||
}
|
||||
}
|
||||
element.innerHTML = html;
|
||||
});
|
||||
@ -638,7 +915,16 @@
|
||||
let searchText = searchDom.value;
|
||||
let apiSortName = getDom('apiSortName')
|
||||
let apiSortType = getDom('apiSortType')
|
||||
let url = concatToken(`contextPath/koTime/exportApis?question=${searchText}&orderBy=${apiSortName.value}&sort=${apiSortType.value}`);
|
||||
let url = concatToken(`contextPath/koTime/interfaces/export?question=${searchText}&orderBy=${apiSortName.value}&sort=${apiSortType.value}`);
|
||||
let a = document.createElement("a");
|
||||
a.style.display='none';
|
||||
a.href = url;
|
||||
a.click();
|
||||
setTimeout(()=>{a.remove();},3000);
|
||||
}
|
||||
|
||||
function dumpHeap() {
|
||||
let url = concatToken(`contextPath/koTime/memories/heap/export`);
|
||||
let a = document.createElement("a");
|
||||
a.style.display='none';
|
||||
a.href = url;
|
||||
@ -682,116 +968,173 @@
|
||||
</ul>
|
||||
|
||||
<ul class="uk-switcher uk-margin">
|
||||
<li style="margin-left: 30%;margin-right: 30%;margin-top: -10px">
|
||||
<li style="margin-left: 28%;margin-right: 28%;margin-top: -10px">
|
||||
<ul class="uk-flex-left" uk-tab>
|
||||
<li class="uk-active"><a style="text-transform: unset" href="#">{{tab.summary.interface-metric}}</a></li>
|
||||
</ul>
|
||||
<div style="margin-top: 20px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||
<div style="margin-top: 10px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<div id="systemTotalNum-div" style="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">{{tab.summary.interface-metric.total-num}}</span><br>
|
||||
<span style="font-size: 30px;color: #020718;font-weight: bold" id="systemTotalNum">0</span>
|
||||
<div id="systemNum-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.interface-metric.total-num}}:</span><span class="metric-card-summary-v" id="systemTotalNum">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.interface-metric.delay-num}}:</span><span class="metric-card-item-v" id="systemDelayNum">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.interface-metric.normal-num}}:</span><span class="metric-card-item-v" id="systemNormalNum">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="systemDelayNum-div" style="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">{{tab.summary.interface-metric.delay-num}}</span>
|
||||
<br>
|
||||
<span style="font-size: 30px;color: #cc0c0c;font-weight: bold" id="systemDelayNum">0</span>
|
||||
<div id="systemRunTime-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.response-metric.avg-num}}:</span><span class="metric-card-summary-v" id="systemAvgRunTime">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.response-metric.max-num}}:</span><span class="metric-card-item-v" id="systemMaxRunTime">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.response-metric.min-num}}:</span><span class="metric-card-item-v" id="systemMinRunTime">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="systemNormalNum-div" style="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">{{tab.summary.interface-metric.normal-num}}</span>
|
||||
<br>
|
||||
<span style="font-size: 30px;color: #29da93;font-weight: bold" id="systemNormalNum">0</span></div>
|
||||
<div id="systemCallNum-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.interface-metric.avg-call-num}}:</span><span class="metric-card-summary-v" id="systemAvgCallNum">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.interface-metric.max-call-num}}:</span><span class="metric-card-item-v" id="systemMaxCallNum">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.interface-metric.min-call-num}}:</span><span class="metric-card-item-v" id="systemMinCallNum">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul style="margin-top: 10px;" class="uk-flex-left" uk-tab>
|
||||
<li class="uk-active"><a style="text-transform: unset" href="#">{{tab.summary.response-metric}}</a></li>
|
||||
<li class="uk-active"><a style="text-transform: unset" href="#">{{tab.summary.memory-metric}}</a></li>
|
||||
</ul>
|
||||
<div style="margin-top: 10px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<div id="systemAvgRunTime-div" style="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">{{tab.summary.response-metric.avg-num}}</span>
|
||||
<br>
|
||||
<span style="font-size: 30px;color: #020718;font-weight: bold" id="systemAvgRunTime">0</span></div>
|
||||
<div id="physicalMemory-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.physical-memory}}:</span><span class="metric-card-summary-v" id="physicalUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.physical-memory.total}}:</span><span class="metric-card-item-v" id="physicalAmount">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.physical-memory.used}}:</span><span class="metric-card-item-v" id="physicalUsed">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.physical-memory.current-used}}:</span><span class="metric-card-item-v" id="thisUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="systemMaxRunTime-div" style="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">{{tab.summary.response-metric.max-num}}</span>
|
||||
<br>
|
||||
<span style="font-size: 30px;color: #020718;font-weight: bold" id="systemMaxRunTime">0</span></div>
|
||||
<div id="heapMemory-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span onclick="dumpHeap();" style="text-transform: unset;background-color: #404b67;position: absolute;cursor: pointer" title="dump" class="uk-card-badge">></span>
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.heap-memory}}:</span><span class="metric-card-summary-v" id="heapUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span class="metric-card-item-v" id="heapInit">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.max}}:</span><span class="metric-card-item-v" id="heapMax">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span class="metric-card-item-v" id="heapUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="systemMinRunTime-div" style="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">{{tab.summary.response-metric.min-num}}</span>
|
||||
<br>
|
||||
<span style="font-size: 30px;color: #020718;font-weight: bold" id="systemMinRunTime">0</span></div>
|
||||
<div id="nonHeapMemory-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.non-heap-memory}}:</span><span class="metric-card-summary-v" id="nonHeapUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span class="metric-card-item-v" id="nonHeapInit">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.max}}:</span><span class="metric-card-item-v" id="nonHeapMax">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span class="metric-card-item-v" id="nonHeapUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul style="margin-top: 10px;" class="uk-flex-left" uk-tab>
|
||||
<li class="uk-active"><a style="text-transform: unset" href="#">{{tab.summary.jvm-metric}}</a></li>
|
||||
</ul>
|
||||
<div style="margin-top: 10px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<div id="EdenSpace-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.eden-space}}:</span><span class="metric-card-summary-v" id="edenSpaceUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span class="metric-card-item-v" id="edenSpaceInit">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.max}}: </span><span class="metric-card-item-v" id="edenSpaceMax">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span class="metric-card-item-v" id="edenSpaceUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="SurvivorSpace-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.survivor-space}}:</span><span class="metric-card-summary-v" id="survivorSpaceUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span class="metric-card-item-v" id="survivorSpaceInit">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.max}}: </span><span class="metric-card-item-v" id="survivorSpaceMax">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span class="metric-card-item-v" id="survivorSpaceUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="OldGen-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.old-gen}}:</span><span class="metric-card-summary-v" id="oldGenUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span class="metric-card-item-v" id="oldGenInit">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.max}}: </span><span class="metric-card-item-v" id="oldGenMax">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span class="metric-card-item-v" id="oldGenUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="Metaspace-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.meta-space}}:</span><span class="metric-card-summary-v" id="metaspaceUsedRate">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span class="metric-card-item-v" id="metaspaceInit">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.max}}: </span><span class="metric-card-item-v" id="metaspaceMax">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span class="metric-card-item-v" id="metaspaceUsed">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="uk-flex-left" uk-tab>
|
||||
<li class="uk-active"><a style="text-transform: unset" href="#">{{tab.summary.sysusage-metric}}</a></li>
|
||||
<li class="uk-active"><a style="text-transform: unset" href="#">{{tab.summary.other-metric}}</a></li>
|
||||
</ul>
|
||||
<div style="margin-top: 20px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||
<div style="margin-top: 10px;" class="uk-grid-small uk-child-width-expand@s uk-text-center" uk-grid>
|
||||
<div>
|
||||
<div id="cpuInfo-div" style="border-radius: 10px;background-color: #fefffe;padding: 20px; text-align: left;"
|
||||
class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||
<span style="font-size: 12px;color: #3b3f4f;justify-content: space-around;" id="cpuLogicalAmount">{{tab.summary.sysusage-metric.cpu-usage}}:</span><span
|
||||
style="font-size: 15px;color: #020718;font-weight: bold" id="systemLoad">0</span>
|
||||
<div id="cpuInfo-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span id="cpuLogicalAmount" class="metric-card-summary-n">{{tab.summary.sysusage-metric.cpu-usage}}:</span><span class="metric-card-summary-v" id="systemLoad">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list-bullet" style="text-align: left;margin-top: -13px; margin-left: -40px;list-style-type: none">
|
||||
<li style="margin-top: -2px;"><span
|
||||
style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.cpu-usage.user-usage}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="cpuUserRate">0</span></li>
|
||||
<li style="margin-top: -2px;"><span
|
||||
style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.cpu-usage.sys-usage}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="cpuSysRate">0</span></li>
|
||||
<li style="margin-top: -2px;"><span style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.cpu-usage.io-waiting}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="cpuWaitRate">0</span></li>
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.cpu-usage.user-usage}}:</span><span class="metric-card-item-v" id="cpuUserRate">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.cpu-usage.sys-usage}}:</span><span class="metric-card-item-v" id="cpuSysRate">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="heapMemory-div" style="border-radius: 10px;background-color: #fefffe;padding: 20px; text-align: left;"
|
||||
class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||
<span style="font-size: 12px;color: #3b3f4f;justify-content: space-around;">{{tab.summary.sysusage-metric.heap-memory}}:</span><span
|
||||
style="font-size: 15px;color: #020718;font-weight: bold" id="heapUsedRate">0</span>
|
||||
<div id="gc-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.gc-num}}:</span><span class="metric-card-summary-v" id="gcTotalNum">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list-bullet" style="text-align: left;margin-top: -13px; margin-left: -40px;list-style-type: none">
|
||||
<li style="margin-top: -2px;"><span style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.heap-memory.init}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="heapInit">0</span></li>
|
||||
<li style="margin-top: -2px;"><span style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.heap-memory.max}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="heapMax">0</span></li>
|
||||
<li style="margin-top: -2px;"><span style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.heap-memory.used}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="heapUsed">0</span></li>
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.gc-num.minor}}:</span><span class="metric-card-item-v" id="gcMinorNum">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.gc-num.full}}:</span><span class="metric-card-item-v" id="gcFullNum">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="physicalMemory-div" style="border-radius: 10px;background-color: #fefffe;padding: 20px; text-align: left;"
|
||||
class="uk-card uk-card-default uk-card-body uk-label-success">
|
||||
<span style="font-size: 12px;color: #3b3f4f;justify-content: space-around;">{{tab.summary.sysusage-metric.physical-memory}}:</span><span
|
||||
style="font-size: 15px;color: #020718;font-weight: bold" id="physicalUsedRate">0</span>
|
||||
<div id="thread-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.thread-num}}:</span><span class="metric-card-summary-v" id="threadTotalNum">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list-bullet" style="text-align: left;margin-top: -13px; margin-left: -40px;list-style-type: none">
|
||||
<li style="margin-top: -2px;"><span
|
||||
style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.physical-memory.total}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="physicalAmount">0</span>
|
||||
</li>
|
||||
<li style="margin-top: -2px;"><span
|
||||
style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.physical-memory.used}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="physicalUsed">0</span></li>
|
||||
<li style="margin-top: -2px;"><span
|
||||
style="font-size: 8px;color: #3b3f4f;">{{tab.summary.sysusage-metric.physical-memory.current-used}}:</span><span
|
||||
style="font-size: 12px;color: #020718;font-weight: bold" id="thisUsed">0</span></li>
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.thread-num.runnable}}:</span><span class="metric-card-item-v" id="threadRunnableNum">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.thread-num.deadlock}}:</span><span class="metric-card-item-v" id="threadLockNum">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div id="class-div" class="uk-card uk-card-default uk-card-body uk-label-success metric-card">
|
||||
<span class="metric-card-summary-n">{{tab.summary.sysusage-metric.loaded-class-num}}:</span><span class="metric-card-summary-v" id="classTotalNum">0</span>
|
||||
<hr style="margin-top: 7px">
|
||||
<ul class="uk-list metric-card-item">
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.loaded-class-num.current}}:</span><span class="metric-card-item-v" id="classCurrentNum">0</span></li>
|
||||
<li><div class="metric-card-item-point"></div><span class="metric-card-item-n">{{tab.summary.sysusage-metric.loaded-class-num.unloaded}}:</span><span class="metric-card-item-v" id="classDeleteNum">0</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user