byte-buddy打印执行时间以及方法链路追踪

文章目录

  • 前言
  • 一、byte-buddy是什么?
  • 二、使用步骤
    • 1.编译成jar包
    • 2.配置Java探针
    • 3.效果演示
  • 三、遭遇问题
    • 1.打桩
    • 2.mybatis报错


前言

很多的小伙伴开发过程中可能都遭遇过打印执行时间的问题。常规的操作就是在需要监控的方法编写几行代码来打印执行时间,勤劳点的小伙伴就会编写aop来打印执行时间,但是绝大部分时候,我们是不需要将这段代码带进生产环境的,所以在上线都要找到相关的代码进行删除。本文提供了一套Java探针程序,可以在开发或者测试(压测)阶段协助调试代码。同时提供生成traceId,方便追踪方法链路。
先提供源码地址:

https://github.com/Jamsw/bytebuddy-agent.git

提示:以下是本篇文章正文内容,下面案例可供参考

一、byte-buddy是什么?

Byte Buddy是一个JVM的运行时代码生成器,提供了简单的API,便于手工、通过Java Agent,或者在构建期间修改字节码。

二、使用步骤

1.编译成jar包

命令如下:

mvn clean package

执行完成后,会在target目录中生成jar包以及config目录。jar包和config需要在相同目录下。如下图所示:
byte-buddy打印执行时间以及方法链路追踪_第1张图片
config目录下包含agent.config配置文件,其中包含两个参数:

agent.packname = com.smart.tcp.gateway
agent.ignore = com.smart.tcp.gateway.client.test.UserModel,com.smart.tcp.gateway.client.test.UserModel

agent.packname:需要打印日志的包路径。
agent.ignore:需要忽略的类。

2.配置Java探针

拿idea开发工具举例,需要在VM options配置如下参数:

-javaagent:path(填写本机或者服务器目录地址)/log-agent-1.0-SNAPSHOT.jar

3.效果演示

tid:71b8195c-eadc-4385-8db1-a8fb414743e8:INFO>方法级别【类名:com.smart.tcp.gateway.client.test.UserMapper  方法名:<init> 执行时间为:0ms】
tid:71b8195c-eadc-4385-8db1-a8fb414743e8:INFO>方法级别【类名:com.smart.tcp.gateway.client.test.UserMapper  方法名:selectUserInfo 执行时间为:0ms】
tid:71b8195c-eadc-4385-8db1-a8fb414743e8:INFO>方法级别【类名:com.smart.tcp.gateway.client.test.UserServiceImpl  方法名:getUserInfo 执行时间为:10ms】
tid:71b8195c-eadc-4385-8db1-a8fb414743e8:INFO>接口级别【url path:/user/getInfo 入参:key=userId value=123456,出参:{"userName":"smart","userId":null} 接口整体耗时:109ms】

三、遭遇问题

1.打桩

由于要打印接口返回值,所以需要将HttpServletResponse进行二次封装,agent程序需要将二次封装的reponse传给拦截的方法,所以需要使用打桩。
首先重写superCall方法,如下:

public interface OverrideCallable {
    Object call(Object[] args);
}

然后在ProcessRequestInterceptor方法入参加入OverrideCallable,如下:

public static Object intercept(@AllArguments Object[] allArguments, @Morph OverrideCallable zuper)

在premain加入打桩配置.withDefaultConfiguration().withBinders(Morph.Binder.install(OverrideCallable.class)),如下所示:

agentBuilder.ignore(ElementMatchers.named("javax.servlet.http"))
                .type(ElementMatchers.named("org.springframework.web.servlet.FrameworkServlet"))
                .transform((builder, type, classLoader, module) ->
                        builder.method(ElementMatchers.named("processRequest"))
                                .intercept(MethodDelegation.withDefaultConfiguration().withBinders(Morph.Binder.install(OverrideCallable.class)).to(ProcessRequestInterceptor.class)))
                .installOn(inst);

2.mybatis报错

由于byte-buddy在注入代码的时候会修改原始类名,所以mybatis通过类名查询方法的时候会报java.lang.NoSuchMethodError报错,解决方式为配置不修改类名.disableClassFormatChanges(), 具体代码如下:

agentBuilder.disableClassFormatChanges().ignore(e)
                .type(ElementMatchers.nameStartsWith(Config.Agent.packname))
                .transform(transformer).installOn(inst);

你可能感兴趣的:(java-agent,byte-buddy,java)