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

完成

相关推荐
小雨笙笙2 分钟前
机器学习:线性回归学习
学习·机器学习·线性回归
HugoStudio_SWAN5 分钟前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
是隼人38 分钟前
buuctf-pwn [HarekazeCTF2019]baby_rop2(64位ret2libc)题解(学习过程持续更新)
c语言·学习·安全·pwn入门·ctf入门
aprilaaaaa2 小时前
(TC397 学习笔记)二、ICU和TIM的时钟计算
笔记·学习·fpga开发
xian_wwq3 小时前
【学习笔记】-深度认知系列-第8讲主流AI模型横向评测——GPT、Claude、Gemini、盘古、文心、通义
人工智能·笔记·学习
大牧师3 小时前
TypeORM 学习教程
数据库·sql·学习·node.js·orm·nest.js·typeorm
晨欣4 小时前
NVIDIA GPU 架构演进学习笔记(GPT-5.6 Terra 生成)
笔记·学习·gpu·显卡·nvidia·英伟达
小雪崩4 小时前
嵌入式学习 day40:数据库
数据库·学习
一条破秋裤4 小时前
17_ADC原理与转换模式
笔记·stm32·学习
传奇开心果编程5 小时前
【Rust入门知识点学与练】第5课:函数
开发语言·学习·rust