skywalking~定制agent

本文详细介绍了如何定制SkyWalking的Agent,包括使用ByteBuddy忽视特定类,将关键插件注入Bootstrap ClassLoader,以及根据配置保存增强类。还探讨了RETRANSFORMATION和REDEFINITION两种方法的区别,并总结了自定义Agent的步骤和细节,如拦截类的选择、增强模式的设定等。
摘要由CSDN通过智能技术生成

定制agent实际是在定制ByteBuddy字节码增强规则。
ps:其中参数Config.Agent.IS_OPEN_DEBUGGING_CLASS配置如果为true,会将所有测试类文件保存到/debugging目录下

final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));

创建一个AgentBuilder定制bytebuddy的行为
首先指定了一些忽略的类,例如以net.bytebuddy.、org.slf4j开头的。忽略所有skywalking的工具类,isSynthetic忽略编译器生成的类

  AgentBuilder agentBuilder = new AgentBuilder.Default(byteBuddy).ignore(
                nameStartsWith("net.bytebuddy.")
                        .or(nameStartsWith("org.slf4j."))
                        .or(nameStartsWith("org.groovy."))
                        .or(nameContains("javassist"))
                        .or(nameContains(".asm."))
                        .or(nameContains(".reflectasm."))
                        .or(nameStartsWith("sun.reflect"))
                        .or(allSkyWalkingAgentExcludeToolkit())
                        .or(ElementMatchers.isSynthetic()));

将一些重要的插件及其他类注入到Bootstrap classloader中。其中遵循双亲委派原则,顶层父类无法找到子加载器中加载的类,将这些插件注入到Bootstrap classloader中,方便后续使用。

BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);

public static AgentBuilder inject(PluginFinder pluginFinder, Instrumentation instrumentation,
        AgentBuilder agentBuilder, JDK9ModuleExporter.EdgeClasses edgeClasses) throws PluginException {
        Map<String, byte[]> classesTypeMap = new HashMap<>();

        if (!prepareJREInstrumentation(pluginFinder, classesTypeMap)) {
            return agentBuilder;
        }

        if (!prepareJREInstrumentationV2(pluginFinder, classesTypeMap)) {
            return agentBuilder;
        }

        for (String highPriorityClass : HIGH_PRIORITY_CLASSES) {
            loadHighPriorityClass(classesTypeMap, highPriorityClass);
        }
        for (String highPriorityClass : ByteBuddyCoreClasses.CLASSES) {
            loadHighPriorityClass(classesTypeMap, highPriorityClass);
        }

        /**
         * Prepare to open edge of necessary classes.
         */
        for (String generatedClass : classesTypeMap.keySet()) {
            edgeClasses.add(generatedClass);
        }

        ClassInjector.UsingUnsafe.Factory factory = ClassInjector.UsingUnsafe.Factory.resolve(instrumentation);
        factory.make(null, null).injectRaw(classesTypeMap);
        agentBuilder = agentBuilder.with(new AgentBuilder.InjectionStrategy.UsingUnsafe.OfFactory(factory));

        return agentBuilder;
    }

根据配置,判断是否允许将skywalking增强类进行保存,允许其他agent进行增强

 if (Config.Agent.IS_CACHE_ENHANCED_CLASS) {
            try {
                agentBuilder = agentBuilder.with(new CacheableTransformerDecorator(Config.Agent.CLASS_CACHE_MODE));
                LOGGER.info("SkyWalking agent class cache [{}] activated.", Config.Agent.CLASS_CACHE_MODE);
            } catch (Exception e) {
                LOGGER.error(e, "SkyWalking agent can't active class cache.");
            }
        }
agentBuilder.type(pluginFinder.buildMatch()) //指定需要拦截的类
                    .transform(new Transformer(pluginFinder))   //指定拦截操作类,具体实际操作的类中transform方法
                    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)  //RETRANSFORMATION和REDEFINITION是否保留修改前的方法
                    .with(new RedefinitionListener())
                    .with(new Listener()) //注册监听器
                    .installOn(instrumentation); //将agent安装到instrumentation

RETRANSFORMATION在修改方法后,保留原方法,例如
class Person{
void say(){
sout(“hello”);
}
}
经过bytebuddy增强,对方法进行了重定义,复制了一个原方法,进行了重写。同时保留了原方法。
class Person{
void say(){
sout(“hi”);
}
void say$001(){
sout(“hi”);
}
}。
而REDEFINITION直接就是替换原方法。

总结:
  1. 创建bytebuddy实例
  2. 指定bytebuddy要忽略的类
  3. 将必要的类注入到BootstrapClassLoader中
  4. 解决JDK模块系统的跨模块访问
  5. 根绝配置决定是否将字节码保存到磁盘、内存中
  6. 细节定制:
    1.指定Bytebuddy要拦截的类
    2.指定字节码增强的类
    3.指定字节增强的模式
    4.注册监听器
    5.将agent安装到instrumentation
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值