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

完成

相关推荐
2501_9011478323 分钟前
学习笔记:单调递增数字求解的迭代优化与工程实践
linux·服务器·笔记·学习·算法
苦逼IT运维1 小时前
从 0 到 1 理解 Kubernetes:一次“破坏式”学习实践(一)
linux·学习·docker·容器·kubernetes
野犬寒鸦2 小时前
从零起步学习并发编程 || 第五章:悲观锁与乐观锁的思想与实现及实战应用与问题
java·服务器·数据库·学习·语言模型
阿蒙Amon2 小时前
TypeScript学习-第13章:实战与最佳实践
javascript·学习·typescript
云小逸2 小时前
【nmap源码学习】 Nmap 源码深度解析:nmap_main 函数详解与 NSE 脚本引擎原理
网络协议·学习·安全
hssfscv3 小时前
Javaweb学习笔记——后端实战8 springboot原理
笔记·后端·学习
苍煜3 小时前
超简单 poi-tl 学习博客:从0到1掌握Word生成(无需模板+模板填充)
学习·word
sensen_kiss3 小时前
Jupter Notebook 使用教程
大数据·人工智能·python·学习·数据分析
狂奔蜗牛飙车3 小时前
Python学习之路-Python3 迭代器与生成器学习详解
开发语言·python·学习·#python学习笔记·python迭代器生成器
云小逸3 小时前
【Nmap 源码学习】深度解析:main.cc 入口函数详解
网络·windows·学习·nmap