From b159bf22881fa7c5cb798dad45efec7ffe2e843c Mon Sep 17 00:00:00 2001 From: huoyo <1729913829@qq.com> Date: Fri, 11 Dec 2020 19:09:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=85=8D=E7=BD=AE=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../langpy/kotime/config/DefaultConfig.java | 52 ++++++++ .../kotime/controller/KoTimeController.java | 9 +- .../kotime/handler/ComputeTimeHandler.java | 1 + .../handler/ComputeTimeHandlerInterface.java | 10 +- .../cn/langpy/kotime/model/KoTimeConfig.java | 41 ++++++ .../langpy/kotime/model/SystemStatistic.java | 13 ++ .../langpy/kotime/service/InvokeService.java | 65 ++++++++++ .../kotime/service/RunTimeNodeService.java | 91 ++++++++++++++ .../java/cn/langpy/kotime/util/Common.java | 48 +++---- .../java/cn/langpy/kotime/util/Context.java | 110 ++-------------- .../java/cn/langpy/kotime/util/GraphMap.java | 57 +++++++++ src/main/resources/static/config.js | 98 +++++++++++++++ src/main/resources/templates/index.html | 118 ++---------------- 14 files changed, 461 insertions(+), 254 deletions(-) create mode 100644 src/main/java/cn/langpy/kotime/config/DefaultConfig.java create mode 100644 src/main/java/cn/langpy/kotime/model/KoTimeConfig.java create mode 100644 src/main/java/cn/langpy/kotime/service/InvokeService.java create mode 100644 src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java create mode 100644 src/main/java/cn/langpy/kotime/util/GraphMap.java create mode 100644 src/main/resources/static/config.js diff --git a/pom.xml b/pom.xml index 8d20330..c5af2dc 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.langpy ko-time - 1.0 + 1.1 koTime koTime diff --git a/src/main/java/cn/langpy/kotime/config/DefaultConfig.java b/src/main/java/cn/langpy/kotime/config/DefaultConfig.java new file mode 100644 index 0000000..0a2528c --- /dev/null +++ b/src/main/java/cn/langpy/kotime/config/DefaultConfig.java @@ -0,0 +1,52 @@ +package cn.langpy.kotime.config; + + +import cn.langpy.kotime.model.KoTimeConfig; +import cn.langpy.kotime.util.Context; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +public class DefaultConfig { + @Value("${koTime.log.language:chinese}") + private String logLanguage; + @Value("${koTime.log.enable:false}") + private Boolean logEnable; + @Value("${koTime.time.threshold:800.0}") + private Double timeThreshold; + + @PostConstruct + public void function() { + KoTimeConfig config = new KoTimeConfig(); + config.setLogEnable(logEnable); + config.setLogLanguage(logLanguage); + config.setTimeThreshold(timeThreshold); + Context.setConfig(config); + } + + public Double getTimeThreshold() { + return timeThreshold; + } + + public void setTimeThreshold(Double timeThreshold) { + this.timeThreshold = timeThreshold; + } + + public String getLogLanguage() { + return logLanguage; + } + + public void setLogLanguage(String logLanguage) { + this.logLanguage = logLanguage; + } + + public Boolean getLogEnable() { + return logEnable; + } + + public void setLogEnable(Boolean logEnable) { + this.logEnable = logEnable; + } +} diff --git a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java index 18474d3..b86962d 100644 --- a/src/main/java/cn/langpy/kotime/controller/KoTimeController.java +++ b/src/main/java/cn/langpy/kotime/controller/KoTimeController.java @@ -2,8 +2,8 @@ package cn.langpy.kotime.controller; import cn.langpy.kotime.model.RunTimeNode; import cn.langpy.kotime.model.SystemStatistic; +import cn.langpy.kotime.service.RunTimeNodeService; import cn.langpy.kotime.util.Context; -import cn.langpy.kotime.util.MethodType; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -20,16 +20,17 @@ import java.util.List; public class KoTimeController { @GetMapping public String index(Model model, HttpServletRequest request) { - List list = Context.get(MethodType.Controller); + List list = RunTimeNodeService.getControllers(); model.addAttribute("list",list); - SystemStatistic system = Context.getStatistic(); + SystemStatistic system = RunTimeNodeService.getRunStatistic(); model.addAttribute("system",system); + model.addAttribute("config",Context.getConfig()); return "index"; } @GetMapping("/getTree") @ResponseBody public RunTimeNode getTree(String methodName,Model model, HttpServletRequest request) { - return Context.getTree(methodName); + return RunTimeNodeService.getGraph(methodName); } } diff --git a/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandler.java b/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandler.java index e1c3abe..a43a8f2 100644 --- a/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandler.java +++ b/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandler.java @@ -27,6 +27,7 @@ public class ComputeTimeHandler { long begin = System.nanoTime(); Object obj=pjp.proceed(); long end =System.nanoTime(); + StackTraceElement stacks[] = Thread.currentThread().getStackTrace(); if ("chinese".equals(computeTime.value())) { log.info("调用方法={},耗时={}毫秒",pjp.getTarget().getClass().getName()+"."+pjp.getSignature().getName(),(end-begin)/1000000); }else{ diff --git a/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandlerInterface.java b/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandlerInterface.java index 21273f0..8ac7e5b 100644 --- a/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandlerInterface.java +++ b/src/main/java/cn/langpy/kotime/handler/ComputeTimeHandlerInterface.java @@ -2,8 +2,7 @@ package cn.langpy.kotime.handler; import cn.langpy.kotime.model.RunTimeNode; -import cn.langpy.kotime.util.Common; -import cn.langpy.kotime.util.Context; +import cn.langpy.kotime.service.InvokeService; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -11,7 +10,6 @@ import org.aspectj.lang.annotation.Pointcut; @Aspect public interface ComputeTimeHandlerInterface { - @Pointcut("") void prog(); @@ -21,9 +19,9 @@ public interface ComputeTimeHandlerInterface { Object obj=pjp.proceed(); long end =System.nanoTime(); String packName = this.getClass().getPackage().getName(); - RunTimeNode parent = Common.getParentRunTimeNode(packName); - RunTimeNode current = Common.getCurrentRunTimeNode(pjp,((end-begin)/1000000.0)); - Context.set(parent,current); + RunTimeNode parent = InvokeService.getParentRunTimeNode(packName); + RunTimeNode current = InvokeService.getCurrentRunTimeNode(pjp,((end-begin)/1000000.0)); + InvokeService.createGraph(parent,current); return obj; } diff --git a/src/main/java/cn/langpy/kotime/model/KoTimeConfig.java b/src/main/java/cn/langpy/kotime/model/KoTimeConfig.java new file mode 100644 index 0000000..4e32819 --- /dev/null +++ b/src/main/java/cn/langpy/kotime/model/KoTimeConfig.java @@ -0,0 +1,41 @@ +package cn.langpy.kotime.model; + + +public class KoTimeConfig { + private String logLanguage; + private Boolean logEnable; + private Double timeThreshold; + + public Double getTimeThreshold() { + return timeThreshold; + } + + public void setTimeThreshold(Double timeThreshold) { + this.timeThreshold = timeThreshold; + } + + public String getLogLanguage() { + return logLanguage; + } + + public void setLogLanguage(String logLanguage) { + this.logLanguage = logLanguage; + } + + public Boolean getLogEnable() { + return logEnable; + } + + public void setLogEnable(Boolean logEnable) { + this.logEnable = logEnable; + } + + @Override + public String toString() { + return "KoTimeConfig{" + + "logLanguage='" + logLanguage + '\'' + + "timeThreshold='" + timeThreshold + '\'' + + ", logEnable=" + logEnable + + '}'; + } +} diff --git a/src/main/java/cn/langpy/kotime/model/SystemStatistic.java b/src/main/java/cn/langpy/kotime/model/SystemStatistic.java index 27b688a..7eb95c6 100644 --- a/src/main/java/cn/langpy/kotime/model/SystemStatistic.java +++ b/src/main/java/cn/langpy/kotime/model/SystemStatistic.java @@ -65,4 +65,17 @@ public class SystemStatistic { public void setNormalNum(Integer normalNum) { this.normalNum = normalNum; } + + @Override + public String toString() { + return "SystemStatistic{" + + "name='" + name + '\'' + + ", avgRunTime=" + avgRunTime + + ", maxRunTime=" + maxRunTime + + ", minRunTime=" + minRunTime + + ", totalNum=" + totalNum + + ", delayNum=" + delayNum + + ", normalNum=" + normalNum + + '}'; + } } diff --git a/src/main/java/cn/langpy/kotime/service/InvokeService.java b/src/main/java/cn/langpy/kotime/service/InvokeService.java new file mode 100644 index 0000000..95fd2be --- /dev/null +++ b/src/main/java/cn/langpy/kotime/service/InvokeService.java @@ -0,0 +1,65 @@ +package cn.langpy.kotime.service; + + +import cn.langpy.kotime.model.RunTimeNode; +import cn.langpy.kotime.util.Common; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +public class InvokeService { + + public static RunTimeNode getParentRunTimeNode(String packName) { + String parentClassName = ""; + String parentMothodName = ""; + StackTraceElement[] stacks = Thread.currentThread().getStackTrace(); + StackTraceElement stack = Common.filter(stacks,packName); + if (stack!=null) { + parentClassName = stack.getClassName(); + parentMothodName = stack.getMethodName(); + } + RunTimeNode parent = new RunTimeNode(); + parent.setClassName(parentClassName); + parent.setMethodName(parentMothodName); + parent.setName(parentClassName.substring(parentClassName.lastIndexOf(".")+1)+"."+parentMothodName); + parent.setMethodType(Common.getMethodType(parentClassName)); + parent.setChildren(new ArrayList<>()); + return parent; + } + + public static RunTimeNode getCurrentRunTimeNode(ProceedingJoinPoint pjp, Double runTime) { + String className = pjp.getTarget().getClass().getName(); + String methodName = pjp.getSignature().getName(); + RunTimeNode current = new RunTimeNode(); + current.setName(className.substring(className.lastIndexOf(".")+1)+"."+methodName); + current.setClassName(className); + current.setMethodName(methodName); + current.setAvgRunTime(runTime); + current.setChildren(new ArrayList<>()); + current.setMethodType(Common.getMethodType(pjp)); + return current; + } + + public static void createGraph(RunTimeNode parent, RunTimeNode current) { + if (current.getMethodName().contains("$")) { + return; + } + Common.showLog(current); + String parentKey = parent.getClassName()+"."+parent.getMethodName(); + String currentKey = current.getClassName()+"."+current.getMethodName(); + if (".".equals(parentKey)) { + RunTimeNodeService.addOrUpdate(currentKey,current); + }else if (RunTimeNodeService.containsNode(parent)) { + RunTimeNodeService.addOrUpdateChildren(parent,current); + }else{ + List list = new ArrayList<>(); + list.add(current); + parent.setChildren(list); + RunTimeNodeService.add(parentKey,parent); + } + } + +} diff --git a/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java b/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java new file mode 100644 index 0000000..debaf17 --- /dev/null +++ b/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java @@ -0,0 +1,91 @@ +package cn.langpy.kotime.service; +import cn.langpy.kotime.model.RunTimeNode; +import cn.langpy.kotime.model.SystemStatistic; +import cn.langpy.kotime.util.Context; +import cn.langpy.kotime.util.GraphMap; +import cn.langpy.kotime.util.MethodType; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class RunTimeNodeService { + + public static void addOrUpdate(String key, RunTimeNode runTimeNode) { + if (GraphMap.containsKey(key)) { + GraphMap.get(key).setAvgRunTime(runTimeNode.getAvgRunTime()); + }else{ + GraphMap.put(key,runTimeNode); + } + } + + public static void add(String key, RunTimeNode runTimeNode) { + GraphMap.put(key,runTimeNode); + } + + public static boolean containsKey(String key) { + return GraphMap.containsKey(key); + } + public static boolean containsNode(RunTimeNode node) { + String key = node.getClassName()+"."+node.getMethodName(); + return GraphMap.containsKey(key); + } + + public static RunTimeNode getRunTimeNode(String key) { + return GraphMap.get(key); + } + + public static void addOrUpdateChildren(RunTimeNode parent, RunTimeNode current) { + String parentKey = parent.getClassName()+"."+parent.getMethodName(); + RunTimeNode hisRunTimeNode = RunTimeNodeService.getRunTimeNode(parentKey); + List hisRunTimeNodeChildren = hisRunTimeNode.getChildren(); + if (hisRunTimeNodeChildren!=null) { + if (hisRunTimeNodeChildren.contains(current)) { + updateChildren(current,hisRunTimeNodeChildren); + }else{ + hisRunTimeNodeChildren.add(current); + } + } else { + List list = new ArrayList<>(); + list.add(current); + hisRunTimeNode.setChildren(list); + } + GraphMap.put(parentKey,hisRunTimeNode); + } + + public static void updateChildren(RunTimeNode child, List hisRunTimeNodeChildren) { + int hisLength = hisRunTimeNodeChildren.size(); + for (int i = 0; i < hisLength; i++) { + if (hisRunTimeNodeChildren.get(i)==child) { + child.setAvgRunTime((child.getAvgRunTime()+hisRunTimeNodeChildren.get(i).getAvgRunTime())/2.0); + hisRunTimeNodeChildren.set(i,child) ; + break; + } + } + } + public static SystemStatistic getRunStatistic() { + List controllerApis = GraphMap.get(MethodType.Controller); + SystemStatistic systemStatistic = new SystemStatistic(); + int delayNum = (int)controllerApis.stream().filter(controllerApi -> controllerApi.getAvgRunTime() >= Context.getConfig().getTimeThreshold()).count(); + systemStatistic.setDelayNum(delayNum); + int normalNum = (int)controllerApis.stream().filter(controllerApi -> controllerApi.getAvgRunTime() < Context.getConfig().getTimeThreshold()).count(); + systemStatistic.setNormalNum(normalNum); + int totalNum = (int)controllerApis.stream().count(); + systemStatistic.setTotalNum(totalNum); + Double max = controllerApis.stream().map(api->api.getAvgRunTime()).max(Double::compareTo).get(); + Double min = controllerApis.stream().map(api->api.getAvgRunTime()).min(Double::compareTo).get(); + Double avg = controllerApis.stream().map(api->api.getAvgRunTime()).collect(Collectors.averagingDouble(Double::doubleValue)); + systemStatistic.setMaxRunTime(max); + systemStatistic.setMinRunTime(min); + systemStatistic.setAvgRunTime(avg); + return systemStatistic; + } + + public static List getControllers() { + List list = GraphMap.get(MethodType.Controller); + return list; + } + public static RunTimeNode getGraph(String methodName) { + return GraphMap.getTree(methodName); + } +} diff --git a/src/main/java/cn/langpy/kotime/util/Common.java b/src/main/java/cn/langpy/kotime/util/Common.java index 39bf3ba..e7615e1 100644 --- a/src/main/java/cn/langpy/kotime/util/Common.java +++ b/src/main/java/cn/langpy/kotime/util/Common.java @@ -1,52 +1,30 @@ package cn.langpy.kotime.util; import cn.langpy.kotime.model.RunTimeNode; +import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; import org.springframework.web.bind.annotation.RestController; -import java.util.ArrayList; - +@Slf4j public class Common { - public static RunTimeNode getParentRunTimeNode(String packName) { - String parentClassName = ""; - String parentMothodName = ""; - StackTraceElement[] stacks = Thread.currentThread().getStackTrace(); + public static StackTraceElement filter(StackTraceElement[] stacks,String packName) { String[] packNameSplit = packName.split("\\."); String filter = packNameSplit.length>1 ? packNameSplit[0]+"."+packNameSplit[1] : packNameSplit[0]; int stacksLength = stacks.length; for (int i = 0; i < stacksLength; i++) { StackTraceElement stack = stacks[i]; if (stack.getClassName().startsWith(filter)&& !stack.getClassName().contains("$")) { - parentClassName = stack.getClassName(); - parentMothodName = stack.getMethodName(); - break; + return stack; } } - RunTimeNode parent = new RunTimeNode(); - parent.setClassName(parentClassName); - parent.setMethodName(parentMothodName); - parent.setName(parentClassName.substring(parentClassName.lastIndexOf(".")+1)+"."+parentMothodName); - parent.setMethodType(getMethodType(parentClassName)); - parent.setChildren(new ArrayList<>()); - return parent; + return null; } - public static RunTimeNode getCurrentRunTimeNode(ProceedingJoinPoint pjp,Double runTime) { - String className = pjp.getTarget().getClass().getName(); - String methodName = pjp.getSignature().getName(); - RunTimeNode current = new RunTimeNode(); - current.setName(className.substring(className.lastIndexOf(".")+1)+"."+methodName); - current.setClassName(className); - current.setMethodName(methodName); - current.setAvgRunTime(runTime); - current.setChildren(new ArrayList<>()); - current.setMethodType(getMethodType(pjp)); - return current; - } + public static MethodType getMethodType(ProceedingJoinPoint pjp) { MethodType methodType = null; @@ -64,7 +42,7 @@ public class Common { methodType = MethodType.Controller; }else if (className.contains("service")) { methodType = MethodType.Service; - }else if (className.contains("dao") || className.contains("mapper")) { + }else if (className.contains("dao") || className.contains("mapper")|| className.contains( "com.sun.proxy.$Proxy")) { methodType = MethodType.Dao; }else{ methodType = MethodType.Others; @@ -80,7 +58,7 @@ public class Common { methodType = MethodType.Controller; }else if (className.contains("service")) { methodType = MethodType.Service; - }else if (className.contains("dao") || className.contains("mapper")) { + }else if (className.contains("dao") || className.contains("mapper")|| className.contains( "com.sun.proxy.$Proxy")) { methodType = MethodType.Dao; }else{ methodType = MethodType.Others; @@ -88,4 +66,14 @@ public class Common { return methodType; } + public static void showLog(RunTimeNode current) { + String currentKey = current.getClassName()+"."+current.getMethodName(); + if (Context.getConfig().getLogEnable() && "chinese".equals(Context.getConfig().getLogLanguage())) { + log.info("调用方法="+currentKey+",耗时="+current.getAvgRunTime()+"毫秒"); + }else if (Context.getConfig().getLogEnable() && "english".equals(Context.getConfig().getLogLanguage())) { + log.info("method="+currentKey+",runTime="+current.getAvgRunTime()+"ms"); + } + } + } + diff --git a/src/main/java/cn/langpy/kotime/util/Context.java b/src/main/java/cn/langpy/kotime/util/Context.java index fcafa44..2dbf30e 100644 --- a/src/main/java/cn/langpy/kotime/util/Context.java +++ b/src/main/java/cn/langpy/kotime/util/Context.java @@ -1,112 +1,16 @@ package cn.langpy.kotime.util; - -import cn.langpy.kotime.model.RunTimeNode; -import cn.langpy.kotime.model.SystemStatistic; +import cn.langpy.kotime.model.KoTimeConfig; import lombok.extern.slf4j.Slf4j; -import java.util.*; -import java.util.stream.Collectors; - @Slf4j public class Context { + private static KoTimeConfig config; - private static Map runTimeNodeMap; - static { - runTimeNodeMap = new HashMap<>(); + public static void setConfig(KoTimeConfig koTimeConfig) { + config = koTimeConfig; + } + public static KoTimeConfig getConfig() { + return config ; } - - public static void set(RunTimeNode parent,RunTimeNode current) { - - String parentKey = parent.getClassName()+"."+parent.getMethodName(); - String currentKey = current.getClassName()+"."+current.getMethodName(); - if (!currentKey.contains("$")) { - log.info("调用方法="+currentKey+",耗时="+current.getAvgRunTime()+"毫秒"); - }else { - return; - } - if (".".equals(parentKey)) { - if (runTimeNodeMap.containsKey(currentKey)) { - runTimeNodeMap.get(currentKey).setAvgRunTime(current.getAvgRunTime()); - }else{ - runTimeNodeMap.put(currentKey,current); - } - }else if (runTimeNodeMap.containsKey(parentKey)) { - RunTimeNode hisRunTimeNode = runTimeNodeMap.get(parentKey); - List hisRunTimeNodeChildren = hisRunTimeNode.getChildren(); - if (hisRunTimeNodeChildren!=null) { - if (hisRunTimeNodeChildren.contains(current)) { - int hisLength = hisRunTimeNodeChildren.size(); - for (int i = 0; i < hisLength; i++) { - if (hisRunTimeNodeChildren.get(i)==current) { - current.setAvgRunTime((current.getAvgRunTime()+hisRunTimeNode.getChildren().get(i).getAvgRunTime())/2.0); - hisRunTimeNodeChildren.set(i,current) ; - break; - } - } - }else{ - hisRunTimeNodeChildren.add(current); - } - } else { - List list = new ArrayList<>(); - list.add(current); - hisRunTimeNode.setChildren(list); - } - runTimeNodeMap.put(parentKey,hisRunTimeNode); - }else{ - List list = new ArrayList<>(); - list.add(current); - parent.setChildren(list); - runTimeNodeMap.put(parentKey,parent); - } - - } - - public static RunTimeNode get(String key) { - return runTimeNodeMap.get(key); - } - public static List get(MethodType methodType) { - return runTimeNodeMap.values().stream() - .filter(runTimeNode -> runTimeNode.getMethodType()==methodType) - .sorted(Comparator.reverseOrder()) - .collect(Collectors.toList()); - } - public static RunTimeNode getTree(String key) { - RunTimeNode root = runTimeNodeMap.get(key); - if (root==null) { - return root; - } - root.setValue(root.getAvgRunTime()); - List children = root.getChildren(); - if (children!=null&&children.size()>0) { - children.forEach(child->{ - String childKey = child.getClassName()+"."+child.getMethodName(); - RunTimeNode newChild = getTree(childKey); - if (newChild!=null) { - child.setChildren(newChild.getChildren()); - child.setValue(child.getAvgRunTime()); - } - }); - } - - return root; - } - - public static SystemStatistic getStatistic() { - List controllerApis = get(MethodType.Controller); - SystemStatistic systemStatistic = new SystemStatistic(); - int delayNum = (int)controllerApis.stream().filter(controllerApi -> controllerApi.getAvgRunTime() >= 800).count(); - systemStatistic.setDelayNum(delayNum); - int normalNum = (int)controllerApis.stream().filter(controllerApi -> controllerApi.getAvgRunTime() < 800).count(); - systemStatistic.setNormalNum(normalNum); - int totalNum = (int)controllerApis.stream().count(); - systemStatistic.setTotalNum(totalNum); - Double max = controllerApis.stream().map(api->api.getAvgRunTime()).max(Double::compareTo).get(); - Double min = controllerApis.stream().map(api->api.getAvgRunTime()).min(Double::compareTo).get(); - Double avg = controllerApis.stream().map(api->api.getAvgRunTime()).collect(Collectors.averagingDouble(Double::doubleValue)); - systemStatistic.setMaxRunTime(max); - systemStatistic.setMinRunTime(min); - systemStatistic.setAvgRunTime(avg); - return systemStatistic; - } } diff --git a/src/main/java/cn/langpy/kotime/util/GraphMap.java b/src/main/java/cn/langpy/kotime/util/GraphMap.java new file mode 100644 index 0000000..6868665 --- /dev/null +++ b/src/main/java/cn/langpy/kotime/util/GraphMap.java @@ -0,0 +1,57 @@ +package cn.langpy.kotime.util; + + +import cn.langpy.kotime.model.RunTimeNode; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class GraphMap { + /*只需保证可见性,无需保证线程安全*/ + private volatile static Map runTimeNodeMap; + + static { + runTimeNodeMap = new HashMap<>(); + } + + public static RunTimeNode get(String key) { + return runTimeNodeMap.get(key); + } + + public static RunTimeNode put(String key, RunTimeNode runTimeNode) { + return runTimeNodeMap.put(key,runTimeNode); + } + public static boolean containsKey(String key) { + return GraphMap.runTimeNodeMap.containsKey(key); + } + + public static List get(MethodType methodType) { + return runTimeNodeMap.values().stream() + .filter(runTimeNode -> runTimeNode.getMethodType()==methodType) + .sorted(Comparator.reverseOrder()) + .collect(Collectors.toList()); + } + + public static RunTimeNode getTree(String key) { + RunTimeNode root = runTimeNodeMap.get(key); + if (root==null) { + return root; + } + root.setValue(root.getAvgRunTime()); + List children = root.getChildren(); + if (children!=null&&children.size()>0) { + children.forEach(child->{ + String childKey = child.getClassName()+"."+child.getMethodName(); + RunTimeNode newChild = getTree(childKey); + if (newChild!=null) { + child.setChildren(newChild.getChildren()); + child.setValue(child.getAvgRunTime()); + } + }); + } + return root; + } +} diff --git a/src/main/resources/static/config.js b/src/main/resources/static/config.js new file mode 100644 index 0000000..fe7e610 --- /dev/null +++ b/src/main/resources/static/config.js @@ -0,0 +1,98 @@ +function getOption(data){ + return { + tooltip: { + trigger: 'item', + triggerOn: 'mousemove' + }, + series: [ + { + type: 'tree', + // initialTreeDepth: 3, + data: [data], + top: '1%', + left: '15%', + bottom: '1%', + right: '10%', + roam: true, + symbolSize: 20, + itemStyle: { + borderColor: 'green' + }, + + label: { + position: 'right', + formatter: function(params){ + var bg = "titleBgGreen" + if (params.value>800) { + bg = "titleBgRed" + } + return [ + '{'+bg+'| 指标}', + ' {aa|}方法:'+params.name+" ", + '{hr|}', + ' {aa|}耗时: '+params.data.avgRunTime+" ms ", + '{hr|}', + ' {aa|}类型: '+params.data.methodType+" " + ].join('\n'); + }, + backgroundColor: '#ddd', + borderColor: '#88e781', + borderWidth: 1, + borderRadius: 5, + color: '#000', + fontSize: 12, + rich: { + titleBgGreen: { + align: 'left', + backgroundColor: '#59977e', + height: 20, + borderRadius: [5, 5, 0, 0], + padding: [0, 0, 0, 0], + width: '100%', + color: '#eee' + }, + titleBgRed: { + align: 'left', + backgroundColor: '#dc1d16', + height: 20, + borderRadius: [5, 5, 0, 0], + padding: [0, 0, 0, 0], + width: '100%', + color: '#eee' + }, + hr: { + borderColor: '#777', + width: '100%', + borderWidth: 0.5, + height: 0 + }, + aa: { + lineHeight: 20, + borderColor: '#111111', + height: 20, + borderRadius: [5, 5, 0, 0], + padding: [0, 0, 0, 0], + width: '0%' + + }, + t: { + align: 'center' + } + } + }, + + leaves: { + label: { + position: 'right', + verticalAlign: 'middle', + align: 'left' + } + }, + expandAndCollapse: true, + animationDuration: 550, + animationDurationUpdate: 750 + } + ] + } +} + diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html index 0fd8f71..7c80943 100644 --- a/src/main/resources/templates/index.html +++ b/src/main/resources/templates/index.html @@ -48,15 +48,15 @@
  • -
    ${system.avgRunTime}
    +
    ${system.avgRunTime}
    平均响应(ms)
  • -
    ${system.maxRunTime}
    +
    ${system.maxRunTime}
    最大响应(ms)
  • -
    ${system.minRunTime}
    +
    ${system.minRunTime}
    最小响应(ms)
@@ -68,7 +68,7 @@

${runtime.className}#${runtime.methodName}  - layui-bg-red <#else>layui-bg-green ">平均响应 ${runtime.avgRunTime} 毫秒

@@ -100,26 +100,18 @@
- - - - - - - - - + + \ No newline at end of file