add the additional outputs for the methods invoked

This commit is contained in:
huoyo 2022-05-23 23:01:53 +08:00
parent 6534fa07e6
commit 6c7899ef9d
8 changed files with 131 additions and 35 deletions

View File

@ -6,7 +6,7 @@
<groupId>cn.langpy</groupId>
<artifactId>ko-time</artifactId>
<version>2.1.1</version>
<version>2.2.0.BETA</version>
<name>koTime</name>
<description>koTime</description>
<licenses>

View File

@ -0,0 +1,12 @@
package cn.langpy.kotime.annotation;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface KoListener {
String value() default "";
}

View File

@ -18,7 +18,6 @@ public class DefaultConfig {
private Boolean exceptionEnable;
private Boolean paramAnalyse;
private String saveSaver;
private Boolean saveAsync;
private Integer threadNum;
private String contextPath;
private Boolean authEnable;
@ -81,13 +80,7 @@ public class DefaultConfig {
this.saveSaver = saveSaver;
}
public Boolean getSaveAsync() {
return saveAsync;
}
public void setSaveAsync(Boolean saveAsync) {
this.saveAsync = saveAsync;
}
public Integer getThreadNum() {
return threadNum;

View File

@ -1,8 +1,12 @@
package cn.langpy.kotime.config;
import cn.langpy.kotime.annotation.KoListener;
import cn.langpy.kotime.handler.RunTimeHandler;
import cn.langpy.kotime.service.InvokedHandler;
import cn.langpy.kotime.util.Context;
import org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ -11,6 +15,7 @@ import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.logging.Logger;
/**
* zhangchang
*/
@ -33,9 +38,7 @@ public class LoadConfig {
private Boolean exceptionEnable;
@Value("${koTime.save.saver:memory}")
private String saveSaver;
@Value("${koTime.save.async:false}")
private Boolean saveAsync;
@Value("${koTime.save.thread-num:4}")
@Value("${koTime.save.thread-num:10}")
private Integer threadNum;
@Value("${server.port:8080}")
private Integer serverPort;
@ -44,28 +47,50 @@ public class LoadConfig {
@Resource
private DefaultConfig defaultConfig;
@Resource
private ApplicationContext applicationContext;
@PostConstruct
public void function() {
public void initConfig() {
DefaultConfig config = new DefaultConfig();
config.setLogEnable(defaultConfig.getLogEnable()==null?logEnable:defaultConfig.getLogEnable());
config.setPointcut(defaultConfig.getPointcut()==null?pointcut:defaultConfig.getPointcut());
config.setLogLanguage(defaultConfig.getLogLanguage()==null?logLanguage:defaultConfig.getLogLanguage());
config.setThreshold(defaultConfig.getThreshold()==null?timeThreshold:defaultConfig.getThreshold());
config.setExceptionEnable(defaultConfig.getExceptionEnable()==null?exceptionEnable:defaultConfig.getExceptionEnable());
config.setSaveSaver(defaultConfig.getSaveSaver()==null?saveSaver:defaultConfig.getSaveSaver());
config.setEnable(defaultConfig.getEnable()==null?kotimeEnable:defaultConfig.getEnable());
config.setLogEnable(defaultConfig.getLogEnable() == null ? logEnable : defaultConfig.getLogEnable());
config.setPointcut(defaultConfig.getPointcut() == null ? pointcut : defaultConfig.getPointcut());
config.setLogLanguage(defaultConfig.getLogLanguage() == null ? logLanguage : defaultConfig.getLogLanguage());
config.setThreshold(defaultConfig.getThreshold() == null ? timeThreshold : defaultConfig.getThreshold());
config.setExceptionEnable(defaultConfig.getExceptionEnable() == null ? exceptionEnable : defaultConfig.getExceptionEnable());
config.setSaveSaver(defaultConfig.getSaveSaver() == null ? saveSaver : defaultConfig.getSaveSaver());
config.setEnable(defaultConfig.getEnable() == null ? kotimeEnable : defaultConfig.getEnable());
config.setContextPath(defaultConfig.getContextPath());
config.setAuthEnable(defaultConfig.getAuthEnable()==null?false:defaultConfig.getAuthEnable());
config.setParamAnalyse(defaultConfig.getParamAnalyse()==null?true:defaultConfig.getParamAnalyse());
config.setThreadNum(defaultConfig.getThreadNum() == null ? 10 : defaultConfig.getThreadNum());
config.setAuthEnable(defaultConfig.getAuthEnable() == null ? false : defaultConfig.getAuthEnable());
config.setParamAnalyse(defaultConfig.getParamAnalyse() == null ? true : defaultConfig.getParamAnalyse());
if (null!=config) {
config.setPointcut("("+config.getPointcut()+" ) && !@annotation(javax.websocket.server.ServerEndpoint) && !@annotation(cn.langpy.kotime.annotation.KoListener)");
}
Context.setConfig(config);
log.info("kotime=>loading config");
if (StringUtils.hasText(config.getContextPath())) {
log.info("kotime=>view:"+Context.getConfig().getContextPath()+"/koTime");
}else {
log.info("kotime=>view:http://localhost:" + serverPort+serverContext+"/koTime");
log.info("kotime=>view:" + Context.getConfig().getContextPath() + "/koTime");
} else {
log.info("kotime=>view:http://localhost:" + serverPort + serverContext + "/koTime");
}
}
@PostConstruct
public void initMethodHandlers() {
String[] names = applicationContext.getBeanNamesForType(InvokedHandler.class);
for (String name : names) {
InvokedHandler bean = (InvokedHandler) applicationContext.getBean(name);
if (null != bean) {
KoListener annotation = bean.getClass().getAnnotation(KoListener.class);
if (null==annotation) {
continue;
}
log.info("kotime=>loading InvokedHandler:" + bean.getClass().getSimpleName());
Context.addInvokedHandler(bean);
}
}
}
@ -73,7 +98,7 @@ public class LoadConfig {
public AspectJExpressionPointcutAdvisor configurabledvisor() {
log.info("kotime=>loading method listener");
AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
advisor.setExpression(defaultConfig.getPointcut()==null?pointcut:defaultConfig.getPointcut());
advisor.setExpression(defaultConfig.getPointcut() == null ? pointcut : defaultConfig.getPointcut());
advisor.setAdvice(new RunTimeHandler());
return advisor;
}

View File

@ -4,11 +4,15 @@ import cn.langpy.kotime.model.ExceptionNode;
import cn.langpy.kotime.service.GraphService;
import cn.langpy.kotime.model.MethodNode;
import cn.langpy.kotime.service.InvokeService;
import cn.langpy.kotime.service.InvokedHandler;
import cn.langpy.kotime.util.Context;
import cn.langpy.kotime.util.MethodStack;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Parameter;
import java.util.concurrent.ThreadPoolExecutor;
/**
* zhangchang
*/
@ -21,6 +25,8 @@ public class RunTimeHandler implements MethodInterceptor {
return invocation.proceed();
}
boolean exceptionEnable = Context.getConfig().getExceptionEnable();
Parameter[] parameters = invocation.getMethod().getParameters();
ThreadPoolExecutor pool = Context.getThreadPoolExecutor();
long begin = System.nanoTime();
Object obj = null;
MethodNode parent = InvokeService.getParentMethodNode();
@ -37,10 +43,9 @@ public class RunTimeHandler implements MethodInterceptor {
exception.setId(exception.getClassName() + exception.getName() + exception.getMessage());
MethodNode current = InvokeService.getCurrentMethodNode(invocation, 0.0);
if (current.getClassName().equals(e.getStackTrace()[0].getClassName())) {
GraphService graphService = GraphService.getInstance();
graphService.addMethodNode(current);
graphService.addExceptionNode(exception);
graphService.addExceptionRelation(current, exception);
for (InvokedHandler invokedHandler : Context.getInvokedHandlers()) {
pool.execute(()->invokedHandler.onInvoked(current,parent,parameters, invocation.getArguments()));
}
}
MethodStack.clear();
throw e;
@ -50,12 +55,9 @@ public class RunTimeHandler implements MethodInterceptor {
}
long end = System.nanoTime();
MethodNode current = InvokeService.getCurrentMethodNode(invocation, ((end - begin) / 1000000.0));
GraphService graphService = GraphService.getInstance();
graphService.addMethodNode(parent);
graphService.addMethodNode(current);
graphService.addMethodRelation(parent, current);
if (Context.getConfig().getParamAnalyse()) {
graphService.addParamAnalyse(current.getId(),invocation.getMethod().getParameters(), invocation.getArguments(),((end - begin) / 1000000.0));
for (InvokedHandler invokedHandler : Context.getInvokedHandlers()) {
pool.execute(()->invokedHandler.onInvoked(current,parent,parameters, invocation.getArguments()));
}
MethodStack.clear();
return obj;

View File

@ -0,0 +1,16 @@
package cn.langpy.kotime.service;
import cn.langpy.kotime.annotation.KoListener;
import cn.langpy.kotime.model.MethodNode;
import java.lang.reflect.Parameter;
/**
* zhangchang
*/
public interface InvokedHandler {
/**
* return the results of invoking a method.
*/
void onInvoked(MethodNode current, MethodNode parent, Parameter[] names, Object[] values);
}

View File

@ -0,0 +1,22 @@
package cn.langpy.kotime.service;
import cn.langpy.kotime.annotation.KoListener;
import cn.langpy.kotime.model.MethodNode;
import cn.langpy.kotime.util.Context;
import org.springframework.stereotype.Component;
import java.lang.reflect.Parameter;
@KoListener
public final class KoInvokedHandler implements InvokedHandler{
@Override
public void onInvoked(MethodNode current, MethodNode parent, Parameter[] names, Object[] values) {
GraphService graphService = GraphService.getInstance();
graphService.addMethodNode(parent);
graphService.addMethodNode(current);
graphService.addMethodRelation(parent, current);
if (Context.getConfig().getParamAnalyse()) {
graphService.addParamAnalyse(current.getId(),names, values,current.getValue());
}
}
}

View File

@ -1,6 +1,13 @@
package cn.langpy.kotime.util;
import cn.langpy.kotime.config.DefaultConfig;
import cn.langpy.kotime.service.InvokedHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* zhangchang
@ -8,12 +15,16 @@ import cn.langpy.kotime.config.DefaultConfig;
public class Context {
private static DefaultConfig config;
private static List<InvokedHandler> invokedHandlers;
private static ThreadPoolExecutor threadPoolExecutor;
static {
config = new DefaultConfig();
config.setLogEnable(false);
config.setEnable(true);
config.setLogLanguage("chinese");
invokedHandlers = new ArrayList<>();
threadPoolExecutor = new ThreadPoolExecutor(10, 1000,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
public static void setConfig(DefaultConfig koTimeConfig) {
@ -24,4 +35,19 @@ public class Context {
return config;
}
public static void addInvokedHandler(InvokedHandler invokedHandler) {
invokedHandlers.add(invokedHandler);
}
public static List<InvokedHandler> getInvokedHandlers() {
return invokedHandlers;
}
public static ThreadPoolExecutor getThreadPoolExecutor() {
return threadPoolExecutor;
}
public static void setThreadPoolExecutor(ThreadPoolExecutor threadPoolExecutor) {
Context.threadPoolExecutor = threadPoolExecutor;
}
}