Skywalking git:
GitHub - apache/skywalking: APM, Application Performance Monitoring System
集成入门:
10分钟3个步骤集成使用SkyWalking - 知乎
企业级监控项目Skywalking详细介绍,来看看呀-CSDN博客
下面自己学习了一下ByteBuddy的用法,实战了一下:
入门教程:
ByteBuddy入门教程 - 知乎
这篇也不错:
一、基于Byte Buddy语法创建的第一个HelloWorld | 小傅哥 bugstack 虫洞栈
下面直接上代码
Monitor项目是服务记录时间的一个非侵入性的jar
pom
net.bytebuddy
byte-buddy
1.9.2
net.bytebuddy
byte-buddy-agent
1.9.2
maven-assembly-plugin
false
jar-with-dependencies
org.monitor.MonitorAgent
org.monitor.MonitorAgent
true
true
make-assembly
package
single
org.apache.maven.plugins
maven-compiler-plugin
6
两个主要的类一个是代理类一个是方法的拦截器
agentParam这个参数可以传你想要监控的包名+方法名,本例使用:号分割
package org.monitor;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;
import java.lang.instrument.Instrumentation;
public class MonitorAgent {
public static void premain(String agentParam, Instrumentation inst) {
//命令行为-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor:* 或-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor:call
System.out.println("premain监控开始--------->包路径:" + agentParam);
final String[] args= agentParam.split(":");
//:号之后是方法名,如果不为*标识全部
AgentBuilder.Transformer transformer;
// method指定哪些方法需要被拦截,ElementMathers.any指定了所有的方法,声明intercept拦截器
if(args[1].equals("*")){
transformer = new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder> transform(DynamicType.Builder> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule) {
return builder.method(ElementMatchers.any())
.intercept(MethodDelegation.to(MonitorIntercept.class));
}
};
}else{
transformer = new AgentBuilder.Transformer() {
@Override
public DynamicType.Builder> transform(DynamicType.Builder> builder,
TypeDescription typeDescription,
ClassLoader classLoader,
JavaModule javaModule) {
return builder.method(ElementMatchers.nameStartsWith(args[1]))
.intercept(MethodDelegation.to(MonitorIntercept.class));
}
};
}
/**
* 1.type指定了agent拦截的包名,以[com.monitor]作为前缀
* 2.指定了转换器transformer
* 3.将配置安装到Instrumentation
*/
new AgentBuilder.Default()
.type(ElementMatchers.nameStartsWith(args[0]))
.transform(transformer)
.installOn(inst);
}
}
package org.monitor;
import net.bytebuddy.implementation.bind.annotation.Origin;
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
import net.bytebuddy.implementation.bind.annotation.SuperCall;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class MonitorIntercept {
@RuntimeType
public static Object intercept(@Origin Method method,
@SuperCall Callable> callable) throws Exception {
long start = System.currentTimeMillis();
try {
return callable.call();
} finally {
System.out.println(method + ":" + (System.currentTimeMillis() - start) + "ms");
}
}
}
install 项目得到monitor-1.0-SNAPSHOT.jar
另一个用于被监控的项目monitorDemo,直接写一个main方法的项目就可以
new AgentBuilder.Default()
.type(ElementMatchers.nameStartsWith(agentParam))
.transform(transformer)
.installOn(inst);
package org.monitor;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
call();
}
public static void call(){
System.out.println("call-------------------");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
在运行monitorDemo的main的时候需要前面设置参数:
E:/monitor/target/monitor-1.0-SNAPSHOT.jar 就是Monitor项目install后的jar路径,=号后面是你想要监控的monitorDemo项目的包名路径:号后是方法名,如果是全部方法则是*
-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor:* 或-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor:call
-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor:*
运行后会打印出:
Connected to the target VM, address: '127.0.0.1:62854', transport: 'socket'
premain监控开始--------->包路径:org.monitor:*
Hello World!
call-------------------
public static void org.monitor.App.call():1001ms
public static void org.monitor.App.main(java.lang.String[]):2001ms
Disconnected from the target VM, address: '127.0.0.1:62854', transport: 'socket'
Process finished with exit code 0
-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor:call
运行后:
premain监控开始--------->包路径:org.monitor:call
Hello World!
call-------------------
public static void org.monitor.App.call():1001ms
Process finished with exit code 0
只监控了call方法
完成