前阵子看了公司网站的一个cache 命中率统计的btrace监控脚本,感觉这个玩意功能挺强大,对应用监控有很大实践意义。也顺便把btrace简单学习了一下,未涉及原理方面的内容,只是使用层面的东西,简单笔记总结一下。
安装
Linux下:
在http://kenai.com/projects/btrace下载btrace-bin.tar.gz,并解压,设置环境变量:
export BTRACE_HOME=/home/yblin/workspace/btrace/btrace-bin
export PATH=$BTRACE_HOME/bin:$PATH
敲入btrace命令看到提示,说明安装正常。
简介
是一个安全动态的监控工具。通过动态的修改运行时的java字节码,可以在运行时代码中插入监控行为。
几个概念
探测点 (probe point):用于表示需要被探测监控的位置或者事件。
探测行为 (action):探测点触发时进行的探测行为。如计时等等。
探测方法 (method):当探测点触发的时候,需要触发的探测行为所定义在的那个方法。
代码结构和例子
Btrace代码结构(1.2之后static可以去掉 )
//annotation defined here
public static void trace(){
//actions defined here
}
注:以上是一个探测方法,方法的注解annotation用来指示探测点,即要探测的位置;方法体的内容,是探测点触发之后的探测行为。
以下是一个例子:
待测试代码:
package btrace.test;
public class MyBtraceTest {
public void execute() {
int i = (int) (Math.random() * 1000);
System.out.println(i);
try {
Thread.sleep(Math.abs(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void loopExcute() {
while (true) {
execute();
}
}
public static void main(String[] args) {
MyBtraceTest m = new MyBtraceTest();
m.loopExcute();
}
}
要测试待测代码里excute方法的执行时间,并每次打出方法栈,监控代码如下:
package btrace.test;
import static com.sun.btrace.BTraceUtils.jstack;
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.str;
import static com.sun.btrace.BTraceUtils.strcat;
import static com.sun.btrace.BTraceUtils.timeMillis;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.TLS;
@BTrace
public class TraceMethodTime {
@TLS
static long beginTime;
@OnMethod(clazz = "btrace.test.MyBtraceTest", method = "execute")
public static void traceExecuteBegin() {// 在方法btrace.test.MyBtraceTest.execute()执行之前进行监控。
println("method start!");
beginTime = timeMillis();
// 监控行为是记录一个开始时间。
}
// OnMethod代表运行一个方法的时候进行监控,location @Location(Kind.RETURN)代表在方法返回的时候触发监控行为。
@OnMethod(clazz = "btrace.test.MyBtraceTest", method = "execute", location = @Location(Kind.RETURN))
public static void traceExcute() {
// 监控行为是根据开始时间计算出方法运行时间。
println(strcat(strcat("btrace.test.MyBtraceTest.execute time is:", str(timeMillis() - beginTime)), "ms"));
println("method end!");
jstack();//打印方法栈
}
}
先运行 MyBtraceTest,通过jps拿到进程id,再通过
btrace 11059 btrace/test/TraceMethodTime.java
命令进行监控。可以得到结果:
参考
Btrace的注解方式有很多,意义各不同,同时也有很多现成例子,能帮助实现各种监控场景。
参考官网:http://kenai.com/projects/btrace/pages/UserGuide