diff --git a/README.md b/README.md index 8283057..acacaae 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ http://huoyo.gitee.io/ko-time/ 缺点: -> * 对项目中每个方法进行监控,在性能层面会有一定的影响,建议在开发阶段使用 +> * 由于对项目中每个方法进行监控,在性能层面会有一点影响,建议在开发阶段使用 #### 使用教程 @@ -26,7 +26,7 @@ http://huoyo.gitee.io/ko-time/ cn.langpy ko-time - 1.7 + 1.8 ``` @@ -45,10 +45,9 @@ koTime.log.enable=false # 是否开启控制输出,非必填,默认false koTime.log.language=chinese # 控制台输出语言(english/chinese)非必填,默认chinese koTime.time.threshold=800.0 # 时间阈值,用于前端展示,大于阈值显示红色,小于阈值显示绿色,非必填,默认800 koTime.pointcut=execution(* com.huoyo.demo.controller.*(..)) || execution(* com.huoyo.demo.service.*(..)) 需要监测的切面范围(比如监测controller层和service层),参考aop的@pointcut v1.4开始加入的功能,用来替代下面的步骤3 -koTime.ui.template=thymeleaf 前端页面模板,默认为freemarker,可选thymeleaf 与引入的pom依赖对应 +koTime.ui.template=thymeleaf 前端页面模板,非必填,默认为freemarker,可选thymeleaf 与引入的pom依赖对应 ``` -`注意:暂不支持mybatis的mapper监测` 3. 新建一个类,实现ComputeTimeHandlerInterface,并在 @Pointcut 写入 需要监测的范围 @@ -122,6 +121,8 @@ public class RunTimeHandler implements ComputeTimeHandlerInterface { > V1.7:修复未调用接口时No value present异常 +> V1.8:支持Mybatis的Mapper监测、新增最大/最小运行时间、修复小数位数过长页面边界溢出的bug + #### 特别说明 1.本项目使用java8开发,其他版本未曾试验,如有什么bug还请告知! diff --git a/pom.xml b/pom.xml index 87b8dea..55471c9 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ cn.langpy ko-time - 1.7 + 1.8 koTime koTime diff --git a/src/main/java/cn/langpy/kotime/handler/RunTimeHandler.java b/src/main/java/cn/langpy/kotime/handler/RunTimeHandler.java index 14d6258..26f2e91 100644 --- a/src/main/java/cn/langpy/kotime/handler/RunTimeHandler.java +++ b/src/main/java/cn/langpy/kotime/handler/RunTimeHandler.java @@ -12,7 +12,8 @@ public class RunTimeHandler implements MethodInterceptor { long begin = System.nanoTime(); Object obj=invocation.proceed(); long end =System.nanoTime(); - String packName = invocation.getThis().getClass().getPackage().getName(); +// String packName = invocation.getThis().getClass().getPackage().getName(); + String packName = invocation.getMethod().getDeclaringClass().getPackage().getName(); RunTimeNode parent = InvokeService.getParentRunTimeNode(packName); RunTimeNode current = InvokeService.getCurrentRunTimeNode(invocation,((end-begin)/1000000.0)); InvokeService.createGraph(parent,current); diff --git a/src/main/java/cn/langpy/kotime/model/RunTimeNode.java b/src/main/java/cn/langpy/kotime/model/RunTimeNode.java index 56eca35..e32e4c8 100644 --- a/src/main/java/cn/langpy/kotime/model/RunTimeNode.java +++ b/src/main/java/cn/langpy/kotime/model/RunTimeNode.java @@ -11,6 +11,8 @@ public class RunTimeNode implements Comparable { private String className; private String methodName; private Double avgRunTime = 0.0; + private Double maxRunTime = 0.0; + private Double minRunTime = 10000.0; private Double value = 0.0; private String avgRunTimeUnit = "ms"; private MethodType methodType; @@ -79,6 +81,21 @@ public class RunTimeNode implements Comparable { this.avgRunTime = avgRunTime; } + public Double getMaxRunTime() { + return maxRunTime; + } + + public void setMaxRunTime(Double maxRunTime) { + this.maxRunTime = maxRunTime; + } + + public Double getMinRunTime() { + return minRunTime; + } + + public void setMinRunTime(Double minRunTime) { + this.minRunTime = minRunTime; + } public List getChildren() { return children; @@ -112,6 +129,8 @@ public class RunTimeNode implements Comparable { "className='" + className + '\'' + ", methodName='" + methodName + '\'' + ", avgRunTime=" + avgRunTime + + ", maxRunTime=" + maxRunTime + + ", minRunTime=" + minRunTime + ", avgRunTimeUnit='" + avgRunTimeUnit + '\'' + ", methodType=" + methodType + ", children=" + children + diff --git a/src/main/java/cn/langpy/kotime/service/InvokeService.java b/src/main/java/cn/langpy/kotime/service/InvokeService.java index e640eb8..d5638e8 100644 --- a/src/main/java/cn/langpy/kotime/service/InvokeService.java +++ b/src/main/java/cn/langpy/kotime/service/InvokeService.java @@ -6,6 +6,7 @@ import cn.langpy.kotime.util.Common; import org.aopalliance.intercept.MethodInvocation; import org.aspectj.lang.ProceedingJoinPoint; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; @@ -33,13 +34,18 @@ public class InvokeService { } public static RunTimeNode getCurrentRunTimeNode(MethodInvocation pjp, Double runTime) { - String className = pjp.getThis().getClass().getName(); +// String className = pjp.getThis().getClass().getName(); + String className = pjp.getMethod().getDeclaringClass().getName(); String methodName = pjp.getMethod().getName(); RunTimeNode current = new RunTimeNode(); current.setName(className.substring(className.lastIndexOf(".")+1)+"."+methodName); current.setClassName(className); current.setMethodName(methodName); + BigDecimal bg = new BigDecimal(runTime); + runTime = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); current.setAvgRunTime(runTime); + current.setMaxRunTime(runTime); + current.setMinRunTime(runTime); current.setChildren(new ArrayList<>()); current.setMethodType(Common.getMethodType(pjp)); return current; diff --git a/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java b/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java index 963f8b7..45626be 100644 --- a/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java +++ b/src/main/java/cn/langpy/kotime/service/RunTimeNodeService.java @@ -5,6 +5,7 @@ import cn.langpy.kotime.util.Context; import cn.langpy.kotime.util.GraphMap; import cn.langpy.kotime.util.MethodType; +import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -13,7 +14,16 @@ public class RunTimeNodeService { public static void addOrUpdate(String key, RunTimeNode runTimeNode) { if (GraphMap.containsKey(key)) { - GraphMap.get(key).setAvgRunTime(runTimeNode.getAvgRunTime()); + RunTimeNode oldNode = GraphMap.get(key); + if (0 == oldNode.getAvgRunTime()) { + GraphMap.get(key).setAvgRunTime((runTimeNode.getAvgRunTime())); + } else { + BigDecimal bg = new BigDecimal((runTimeNode.getAvgRunTime()+oldNode.getAvgRunTime())/2.0); + double avg = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + GraphMap.get(key).setAvgRunTime(avg); + } + GraphMap.get(key).setMaxRunTime(runTimeNode.getMaxRunTime()>oldNode.getMaxRunTime()?runTimeNode.getMaxRunTime():oldNode.getMaxRunTime()); + GraphMap.get(key).setMinRunTime(runTimeNode.getMinRunTime() 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); + RunTimeNode hisRunTimeNodeChild = hisRunTimeNodeChildren.get(i); + if (hisRunTimeNodeChild.equals(child)) { + double avg = (child.getAvgRunTime()+hisRunTimeNodeChild.getAvgRunTime())/2.0; + BigDecimal bg = new BigDecimal(avg); + avg = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); + child.setAvgRunTime(avg); + if (hisRunTimeNodeChild.getMaxRunTime()>child.getMaxRunTime()) { + child.setMaxRunTime(hisRunTimeNodeChild.getMaxRunTime()); + } + if (hisRunTimeNodeChild.getMinRunTime()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)); + BigDecimal bg = new BigDecimal(avg); + avg = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); systemStatistic.setMaxRunTime(max); systemStatistic.setMinRunTime(min); systemStatistic.setAvgRunTime(avg); diff --git a/src/main/java/cn/langpy/kotime/util/Common.java b/src/main/java/cn/langpy/kotime/util/Common.java index 81dca56..f0feeb8 100644 --- a/src/main/java/cn/langpy/kotime/util/Common.java +++ b/src/main/java/cn/langpy/kotime/util/Common.java @@ -36,7 +36,7 @@ public class Common { }else if (targetClass.getAnnotation(Repository.class)!=null) { return MethodType.Dao; } - String className = pjp.getThis().getClass().getName().toLowerCase(); + String className = pjp.getMethod().getDeclaringClass().getName().toLowerCase(); if (className.contains("controller")) { return MethodType.Controller; }else if (className.contains("service")) { diff --git a/src/main/resources/static/config.js b/src/main/resources/static/config.js index 4949076..0a84278 100644 --- a/src/main/resources/static/config.js +++ b/src/main/resources/static/config.js @@ -30,9 +30,13 @@ function getOption(data,threshold){ '{'+bg+'| 指标}', ' {aa|}方法:'+params.name+" ", '{hr|}', - ' {aa|}耗时: '+params.data.avgRunTime+" ms ", + ' {aa|}类型: '+params.data.methodType+" ", '{hr|}', - ' {aa|}类型: '+params.data.methodType+" " + ' {aa|}平均耗时: '+params.data.avgRunTime+" ms ", + '{hr|}', + ' {aa|}最大耗时: '+params.data.maxRunTime+" ms ", + '{hr|}', + ' {aa|}最小耗时: '+params.data.minRunTime+" ms " ].join('\n'); }, backgroundColor: '#ddd', diff --git a/src/main/resources/templates/index-freemarker.html b/src/main/resources/templates/index-freemarker.html index 9dd8380..5693ee4 100644 --- a/src/main/resources/templates/index-freemarker.html +++ b/src/main/resources/templates/index-freemarker.html @@ -75,7 +75,7 @@ <#else>layui-bg-green ">平均响应 ${runtime.avgRunTime} 毫秒 -
+
diff --git a/src/main/resources/templates/index-thymeleaf.html b/src/main/resources/templates/index-thymeleaf.html index 69a7965..53a343d 100644 --- a/src/main/resources/templates/index-thymeleaf.html +++ b/src/main/resources/templates/index-thymeleaf.html @@ -80,7 +80,7 @@ -
+