Skywalking 学习之ByteBuddy 方法执行时间监控

Skywalking git:

GitHub - apache/skywalking: APM, Application Performance Monitoring System

集成入门:

10分钟3个步骤集成使用SkyWalking - 知乎

下面自己学习了一下ByteBuddy的用法,实战了一下:

入门教程:

ByteBuddy入门教程 - 知乎

这篇也不错:

一、基于Byte Buddy语法创建的第一个HelloWorld | 小傅哥 bugstack 虫洞栈

下面直接上代码

Monitor项目是服务记录时间的一个非侵入性的jar

pom

复制代码
<dependencies>
    <!--解决字节码操作和Instrumentation API的复杂性-->
    <dependency>
      <groupId>net.bytebuddy</groupId>
      <artifactId>byte-buddy</artifactId>
      <version>1.9.2</version>
    </dependency>
    <dependency>
      <groupId>net.bytebuddy</groupId>
      <artifactId>byte-buddy-agent</artifactId>
      <version>1.9.2</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <configuration>
          <appendAssemblyId>false</appendAssemblyId>
          <descriptorRefs>
            <!--打包时加入依赖-->
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <!--自动生成/META-INF/MANIFEST.MF-->
            <manifestEntries>
              <Premain-Class>org.monitor.MonitorAgent</Premain-Class>
              <Agent-Class>org.monitor.MonitorAgent</Agent-Class>
              <Can-Redefine-Classes>true</Can-Redefine-Classes>
              <Can-Retransform-Classes>true</Can-Retransform-Classes>
            </manifestEntries>
          </archive>
        </configuration>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>6</source>
          <target>6</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

两个主要的类一个是代理类一个是方法的拦截器

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) {
        System.out.println("premain开始--------->" + agentParam);
        // method指定哪些方法需要被拦截,ElementMathers.any指定了所有的方法,声明intercept拦截器
        AgentBuilder.Transformer transformer = new AgentBuilder.Transformer() {
            @Override
            public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder,
                                                    TypeDescription typeDescription,
                                                    ClassLoader classLoader,
                                                    JavaModule javaModule) {
                return builder.method(ElementMatchers.<MethodDescription>any())
                        .intercept(MethodDelegation.to(MonitorIntercept.class));
            }
        };
        /**
         * 1.type指定了agent拦截的包名,以[com.monitor]作为前缀
         * 2.指定了转换器transformer
         * 3.将配置安装到Instrumentation
         */
        new AgentBuilder.Default()
                .type(ElementMatchers.<TypeDescription>nameStartsWith(agentParam))
                .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方法的项目就可以

java 复制代码
new AgentBuilder.Default()
                .type(ElementMatchers.<TypeDescription>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(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

在运行monitorDemo的main的时候需要前面设置参数:

E:/monitor/target/monitor-1.0-SNAPSHOT.jar 就是Monitor项目install后的jar路径,=号后面是你想要监控的monitorDemo项目的包名路径

java 复制代码
-javaagent:E:/monitor/target/monitor-1.0-SNAPSHOT.jar=org.monitor

运行后会打印出:

java 复制代码
premain监控开始--------->包路径:org.monitor
Hello World!
public static void org.monitor.App.main(java.lang.String[]):10001ms

Process finished with exit code 0

完成

相关推荐
浩瀚地学7 小时前
【Java】JDK8的一些新特性
java·开发语言·经验分享·笔记·学习
JeffDingAI7 小时前
【Datawhale学习笔记】深入大模型架构
笔记·学习
暖阳之下8 小时前
学习周报三十一
学习
Master_oid9 小时前
机器学习29:增强式学习(Deep Reinforcement Learning)④
人工智能·学习·机器学习
楼田莉子10 小时前
Linux学习之磁盘与Ext系列文件
linux·运维·服务器·c语言·学习
一条闲鱼_mytube10 小时前
智能体设计模式(三)多智能体协作-记忆管理-学习与适应
人工智能·学习·设计模式
丝斯201111 小时前
AI学习笔记整理(50)——大模型中的Graph RAG
人工智能·笔记·学习
一允11 小时前
Git学习记录
git·学习
崇山峻岭之间12 小时前
Matlab学习记录37
android·学习·matlab
开开心心_Every12 小时前
免费窗口置顶小工具:支持多窗口置顶操作
服务器·前端·学习·macos·edge·powerpoint·phpstorm