Performance Tuning -- 09 -- Btrace应用示例
相关文章:
这里主要展示些 Btrace 相关的应用示例
一、拦截简单参数
-
监控方法
@RestController public class HelloController { /** * 拦截简单参数 */ @GetMapping(value = "/arg/simple/{name}") public String argSimple(@PathVariable("name") String name) { return "Hello " + name + "!"; } }
-
Btrace 脚本
@BTrace public class PrintArgSimple { @OnMethod(clazz = "com.xj.controller.HelloController", method = "argSimple") public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) { BTraceUtils.printArray(args); BTraceUtils.println(pcn + " , " + pmn); BTraceUtils.println(); } }
-
@ProbeClassName
- 标记一个参数,用于保存目标类的类名
-
@ProbeMethodName
- 标记一个参数,用于保存目标方法的方法名
-
AnyType
- 表示任何类型的参数
-
-
调用接口
http://localhost:9998/arg/simple/World
-
监控输出
[World, ] com.xj.controller.HelloController , argSimple
二、拦截返回值
-
监控方法
@RestController public class HelloController { /** * 拦截返回值 */ @GetMapping(value = "/arg/simple/{name}") public String argSimple(@PathVariable("name") String name) { return "Hello " + name + "!"; } }
-
Btrace 脚本
@BTrace public class PrintReturn { @OnMethod(clazz = "com.xj.controller.HelloController", method = "argSimple", location = @Location(Kind.RETURN)) public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType result) { BTraceUtils.println(pcn + " , " + pmn + " , " + result); BTraceUtils.println(); } }
-
@Return
- 标记一个参数,用于保存返回值
-
-
调用接口
http://localhost:9998/arg/simple/World
-
监控输出
com.xj.controller.HelloController , argSimple , Hello World!
三、拦截构造函数
-
监控方法
@Data public class User { private int id; private String name; public User(int id, String name) { this.id = id; this.name = name; } }
@RestController public class HelloController { /** * 拦截构造函数 */ @GetMapping(value = "/constructor") public User constructor(User user) { return user; } }
-
Btrace 脚本
@BTrace public class PrintConstructor { @OnMethod(clazz = "com.xj.entity.User", method = "<init>") public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) { BTraceUtils.printArray(args); BTraceUtils.println(pcn + " , " + pmn); BTraceUtils.println(); } }
- 目标类为 User 类,目标方法为 <init> 方法 (构造方法在字节码层面显示为 <init>)
-
调用接口
http://localhost:9998/constructor?id=1&name=小明
-
监控输出
[1, 小明, ] com.xj.entity.User , <init>
四、拦截同名函数
-
监控方法
@RestController public class HelloController { /** * 拦截同名函数 */ @GetMapping(value = "/same1/{name}") public String same(@PathVariable("name") String name) { return "Hello " + name + "!"; } /** * 拦截同名函数 */ @GetMapping(value = "/same2/{name}/{id}") public String same(@PathVariable("name") String name, @PathVariable(name = "id") int id) { return "Hello " + name + " " + id + "!"; } }
-
Btrace 脚本
@BTrace public class PrintSame1 { @OnMethod(clazz = "com.xj.controller.HelloController", method = "same") public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name) { BTraceUtils.println(pcn + " , " + pmn + " , " + name); BTraceUtils.println(); } }
@BTrace public class PrintSame2 { @OnMethod(clazz = "com.xj.controller.HelloController", method = "same") public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, String name, int id) { BTraceUtils.println(pcn + " , " + pmn + " , " + name + " , " + id); BTraceUtils.println(); } }
- 同名方法可以用真实参数进行区分
-
调用接口
http://localhost:9998/same1/World
http://localhost:9998/same2/World/1
-
监控输出
com.xj.controller.HelloController , same , World
com.xj.controller.HelloController , same , World , 1
五、拦截异常
-
监控方法
@RestController public class HelloController { /** * 拦截异常 */ @GetMapping(value = "/exception") public String exception() { try { System.out.println("method start"); System.out.println(1 / 0); System.out.println("method end"); } catch (Exception e) { // 把异常吞了 } return "success"; } }
-
Btrace 脚本
@BTrace public class PrintOnThrow { // store current exception in a thread local // variable (@TLS annotation). Note that we can't // store it in a global variable! @TLS static Throwable currentException; // introduce probe into every constructor of java.lang.Throwable // class and store "this" in the thread local variable. @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow(@Self Throwable self) {//new Throwable() currentException = self; } @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow1(@Self Throwable self, String s) {//new Throwable(String msg) currentException = self; } @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow1(@Self Throwable self, String s, Throwable cause) {//new Throwable(String msg, Throwable cause) currentException = self; } @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow2(@Self Throwable self, Throwable cause) {//new Throwable(Throwable cause) currentException = self; } // when any constructor of java.lang.Throwable returns // print the currentException's stack trace. @OnMethod( clazz="java.lang.Throwable", method="<init>", location=@Location(Kind.RETURN) ) public static void onthrowreturn() { if (currentException != null) { BTraceUtils.Threads.jstack(currentException); currentException = null; } } }
- 当方法内部抛出的异常被吞掉时,我们可以用该 Btrace 脚本来检测被吞掉的异常
-
调用接口
http://localhost:9998/exception
-
监控输出
java.lang.ArithmeticException: / by zero com.xj.controller.HelloController.exception(HelloController.java:57) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897) javax.servlet.http.HttpServlet.service(HttpServlet.java:634) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) javax.servlet.http.HttpServlet.service(HttpServlet.java:741) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:853) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.lang.Thread.run(Thread.java:748)
六、拦截行号
-
监控方法
@RestController public class HelloController { /** * 拦截行号 */ @GetMapping(value = "/line") public String line() { System.out.println("line"); return "success"; } }
-
Btrace 脚本
@BTrace public class PrintLine { @OnMethod(clazz = "com.xj.controller.HelloController", location = @Location(value = Kind.LINE, line = 70)) public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line) { BTraceUtils.println(pcn + " , " + pmn + " , " + line); BTraceUtils.println(); } }
-
Kind.LINE
- 在某一行进行拦截
-
-
调用接口
http://localhost:9998/line
-
监控输出
com.xj.controller.HelloController , line , 70
七、拦截复杂参数
-
监控方法
@RestController public class HelloController { /** * 拦截复杂参数 */ @GetMapping(value = "/arg/complex") public User argComplex(User user) { return user; } }
-
Btrace 脚本
@BTrace public class PrintArgComplex { @OnMethod(clazz = "com.xj.controller.HelloController", method = "argComplex") public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn, User user) { // print all fields BTraceUtils.printFields(user); // print one field Field field = BTraceUtils.field("com.xj.entity.User", "name"); BTraceUtils.println(BTraceUtils.get(field, user)); BTraceUtils.println(pcn + " , " + pmn); BTraceUtils.println(); } }
-
由于此处我们引用了 User 类,则需要将目标程序中的 User 类加入到 classpath 中
-
使用 Class
btrace -cp D:\Workspace\Idea\idea-exercise-maven\jvm-tuning\target\classes 8664 PrintArgComplex.java
-
使用 jar 包 (注意:此处 jar 包须为普通 jar 包,而不是可执行 jar 包)
btrace -cp D:\Workspace\Idea\idea-exercise-maven\jvm-tuning\target\jvm-tuning-0.0.1-SNAPSHOT.jar 8664 PrintArgComplex.java
-
-
-
调用接口
http://localhost:9998/arg/complex?id=1&name=小明
-
监控输出
{id=1, name=小明, } 小明 com.xj.controller.HelloController , argComplex
八、打印参数
-
Btrace 脚本
@BTrace public class PrintJInfo { static { BTraceUtils.println("System Properties:"); BTraceUtils.printProperties(); BTraceUtils.println("VM Flags"); BTraceUtils.printVmArguments(); BTraceUtils.println("OS Environment"); BTraceUtils.printEnv(); BTraceUtils.exit(0); } }
- 可以在静态代码块中打印出系统参数、JVM 参数以及环境变量,类似于 jinfo
-
监控输出
System Properties: sun.desktop = windows awt.toolkit = sun.awt.windows.WToolkit file.encoding.pkg = sun.io java.specification.version = 1.8 sun.cpu.isalist = amd64 sun.jnu.encoding = GBK com.sun.management.jmxremote.authenticate = false // ...
九、正则表达式匹配
-
监控方法
@RestController public class HelloController { /** * 拦截简单参数 */ @GetMapping(value = "/arg/simple/{name}") public String argSimple(@PathVariable("name") String name) { return "Hello " + name + "!"; } }
-
Btrace 脚本
@BTrace public class PrintRegex { @OnMethod(clazz = "com.xj.controller.HelloController", method = "/.*/") public static void test(@ProbeClassName String pcn, @ProbeMethodName String pmn) { BTraceUtils.println(pcn + " , " + pmn); BTraceUtils.println(); } }
- 在 method 参数中,我们可以通过正则表达式来匹配相应的方法名 (此处
.*
代表匹配所有方法)
- 在 method 参数中,我们可以通过正则表达式来匹配相应的方法名 (此处
-
调用接口
http://localhost:9998/arg/simple/World
-
监控输出
[World, ] com.xj.controller.HelloController , argSimple