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

完成

相关推荐
y = xⁿ16 小时前
Redis八股学习日记:数据结构;跳表的底层;Reids的事务机制
数据结构·redis·学习
炽烈小老头16 小时前
【每天学习一点算法 2026/04/29】最长连续序列
学习·算法
库奇噜啦呼16 小时前
【iOS】源码学习-类与对象底层原理
学习·ios·cocoa
不灭锦鲤17 小时前
网络安全学习第98天
学习·安全
星幻元宇VR17 小时前
VR自行车骑行模拟系统|让交通安全教育“骑”进现实
科技·学习·安全·vr
知识分享小能手17 小时前
R语言入门学习教程,从入门到精通,R语言数值关系数据可视化 - 完整知识点(5)
学习·信息可视化·r语言
嵌入式小企鹅20 小时前
CPU供需趋紧、DeepSeek V4全链适配、小米开源万亿模型
人工智能·学习·开源·嵌入式·小米·算力·昇腾
三品吉他手会点灯1 天前
C语言学习笔记 - 20.C编程预备计算机专业知识 - 变量为什么必须的初始化【重点】
c语言·笔记·学习
sakiko_1 天前
UIKit学习笔记1-创建项目(使用UIKit)、使用组件
笔记·学习
生信碱移1 天前
PACells:这个方法可以鉴定疾病/预后相关的重要细胞亚群,作者提供的代码流程可以学习起来了,甚至兼容转录组与 ATAC 两种数据类型!
人工智能·学习·算法·机器学习·数据挖掘·数据分析·r语言