SkyWalking源码-- Agent 定制化行为

372 阅读2分钟

本文基于 SkyWalking-Java-agent 8.15.0 版本

image.png

SkyWalking 采用 ByteBuddy 进行字节码的修改

// 3.定制化Agent行为  
// 创建 ByteBuddy 实例  
final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));  
// 指定 ByteBuddy 要忽略的类  
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()));  
// 1)将必要的类注入到Bootstrap ClassLoader  
JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses();  
try {  
    agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);  
} catch (Exception e) {  
    LOGGER.error(e, "SkyWalking agent inject bootstrap instrumentation failure. Shutting down.");  
return;  
}  
// 解决JDK模块系统的跨模块类访问  
try {  
    agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses);  
} catch (Exception e) {  
    LOGGER.error(e, "SkyWalking agent open read edge in JDK 9+ failure. Shutting down.");  
    return;  
}  
// 将修改后的字节码保存到磁盘/内存上  
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()) // 指定ByteBuddy要拦截的类  
.transform(new Transformer(pluginFinder))  
.with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) // redefine和retransform的区别在于是否保留修改前的内容  
.with(new RedefinitionListener())  
.with(new Listener())  
.installOn(instrumentation);

1. 创建 ByteBuddy 实例

// 创建 ByteBuddy 实例  
final ByteBuddy byteBuddy = new ByteBuddy().with(TypeValidation.of(Config.Agent.IS_OPEN_DEBUGGING_CLASS));

2. 指定 ByteBuddy 要忽略的类

// 指定 ByteBuddy 要忽略的类  
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()));

3. 将必要的类注入到 BootstrapClassLoader 中

// 1)将必要的类注入到Bootstrap ClassLoader  
JDK9ModuleExporter.EdgeClasses edgeClasses = new JDK9ModuleExporter.EdgeClasses();  
try {  
    agentBuilder = BootstrapInstrumentBoost.inject(pluginFinder, instrumentation, agentBuilder, edgeClasses);  
} catch (Exception e) {  
    LOGGER.error(e, "SkyWalking agent inject bootstrap instrumentation failure. Shutting down.");  
    return;  
}

4. 解决 JDK 模块系统的跨模块类访问

// 解决JDK模块系统的跨模块类访问  
try {  
    agentBuilder = JDK9ModuleExporter.openReadEdge(instrumentation, agentBuilder, edgeClasses);  
} catch (Exception e) {  
    LOGGER.error(e, "SkyWalking agent open read edge in JDK 9+ failure. Shutting down.");  
    return;  
}

5. 根据配置决定是否将修改后的字节码保存到磁盘/内存上

// 将修改后的字节码保存到磁盘/内存上  
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.");  
    }  
}

6. 细节定制

agentBuilder.type(pluginFinder.buildMatch()) // 指定ByteBuddy要拦截的类  
    .transform(new Transformer(pluginFinder))  
    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION) // redefine和retransform的区别在于是否保留修改前的内容  
    .with(new RedefinitionListener())  // 注册监听器
    .with(new Listener())  // 注册监听器
    .installOn(instrumentation); // 将 Agent 安装到 Instrumentation