skywalking-agent初始化流程(二)-基于bytebuddy的增强机制

接上篇:
对于所有的skywalking-plugin.def配置文件中定义的agent插件,将通过如下代码生效匹配规则和拦截逻辑。

agentBuilder
    .type(pluginFinder.buildMatch())//匹配规则:待增强的类
    .transform(new Transformer(pluginFinder))//根据匹配规则和增强逻辑创建Transformer:
    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
    .with(new Listener())//回调接口,用来在debug模式下保存增强后的字节码文件
    .installOn(instrumentation);

1.pluginFinder.buildMatch():匹配规则

//直接根据类名称匹配的插件
private final Map> nameMatchDefine = new HashMap>();
//非名称匹配:方法注解匹配、类注解匹配等
private final List signatureMatchDefine = new ArrayList();
//返回bytebuddy元素匹配器,用户判断是否匹配
public ElementMatcher buildMatch() {
        ElementMatcher.Junction judge = new AbstractJunction() {
            @Override
            public boolean matches(NamedElement target) {
                //直接根据类名称匹配
                return nameMatchDefine.containsKey(target.getActualName());
            }
        };
        judge = judge.and(not(isInterface()));
        for (AbstractClassEnhancePluginDefine define : signatureMatchDefine) {
            ClassMatch match = define.enhanceClass();
            if (match instanceof IndirectMatch) {
                //其他规则匹配
                judge = judge.or(((IndirectMatch)match).buildJunction());
            }
        }
        return new ProtectiveShieldMatcher(judge);
    }

增强类匹配规则需要实现ClassMatch接口,skywalking中预定义了一些常用匹配规则
ER图如下:


skywalking-agent初始化流程(二)-基于bytebuddy的增强机制_第1张图片
image.png

NameMatch:直接根据类名称匹配
ClassAnnotationMatch:类注解匹配
MethodAnnotationMatch:方法注解匹配
HierarchyMatch:父类或父接口匹配
MultiClassNameMatch:直接根据类名称匹配(类名称数组、逻辑关系--或)

2.new Transformer(pluginFinder):根据匹配规则和增强逻辑创建AgentBuilder.Transformer

private static class Transformer implements AgentBuilder.Transformer {
        private PluginFinder pluginFinder;

        Transformer(PluginFinder pluginFinder) {
            this.pluginFinder = pluginFinder;
        }

        @Override
        public DynamicType.Builder transform(DynamicType.Builder builder, TypeDescription typeDescription,
            ClassLoader classLoader, JavaModule module) {
            //当前类typeDescription对应的插件集合
            List pluginDefines = pluginFinder.find(typeDescription);
            if (pluginDefines.size() > 0) {
                DynamicType.Builder newBuilder = builder;
                EnhanceContext context = new EnhanceContext();
                for (AbstractClassEnhancePluginDefine define : pluginDefines) {
                    //插件对应的增强逻辑
                    DynamicType.Builder possibleNewBuilder = define.define(typeDescription, newBuilder, classLoader, context);
                    if (possibleNewBuilder != null) {
                        newBuilder = possibleNewBuilder;
                    }
                }
                if (context.isEnhanced()) {
                    logger.debug("Finish the prepare stage for {}.", typeDescription.getName());
                }

                return newBuilder;
            }
            return builder;
        }
    }

此处需要重点解释的是如何基于skywaling插件定义的增强逻辑构建bytebuddy的DynamicType.Builder(动态类型构造器)
回顾上篇的插件定义ER图:


skywalking-agent初始化流程(二)-基于bytebuddy的增强机制_第2张图片
image.png

依次次通过如下函数链构建DynamicType.Builder
AbstractClassEnhancePluginDefine.define => ClassEnhancePluginDefine.enhance
=>ClassEnhancePluginDefine.enhanceClass=>ClassEnhancePluginDefine.enhanceInstance

@Override
    protected DynamicType.Builder enhance(TypeDescription typeDescription,
        DynamicType.Builder newClassBuilder, ClassLoader classLoader,
        EnhanceContext context) throws PluginException {
        //根据getStaticMethodsInterceptPoints(待增强的静态方法和拦截处理器)
        //在DynamicType.Builder构建中嵌入增强逻辑
        newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader);
        
        //根据getConstructorsInterceptPoints(待增强的构造方法和拦截处理器)
        //根据getInstanceMethodsInterceptPoints(待增强的实例方法和拦截处理器)
        //在DynamicType.Builder构建中嵌入增强逻辑
        newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context);

        return newClassBuilder;
    }

以静态方法增强逻辑嵌入为例子:

StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints();
for (StaticMethodsInterceptPoint staticMethodsInterceptPoint : staticMethodsInterceptPoints) {
            String interceptor = staticMethodsInterceptPoint.getMethodsInterceptor();
            newClassBuilder =         
//指定方法匹配规则  
newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher()))
                        .intercept(
                            MethodDelegation.withDefaultConfiguration()
                                .withBinders(
                                    Morph.Binder.install(OverrideCallable.class)
                                )
                                //拦截处理器
                                .to(new StaticMethodsInterWithOverrideArgs(interceptor))
                        );

3.new Listener() 回调接口,用来在debug模式下保存增强后的字节码文件
实现bytebuddy的AgentBuilder.Listener接口,基于事件回调

private static class Listener implements AgentBuilder.Listener {
        @Override
        public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {

        }

        @Override
        public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module,
            boolean loaded, DynamicType dynamicType) {
            if (logger.isDebugEnable()) {
                logger.debug("On Transformation class {}.", typeDescription.getName());
            }
            //在debug模式下保存增强后的字节码文件
            InstrumentDebuggingClass.INSTANCE.log(dynamicType);
        }

        @Override
        public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module,
            boolean loaded) {

        }

        @Override
        public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded,
            Throwable throwable) {
            logger.error("Enhance class " + typeName + " error.", throwable);
        }

        @Override
        public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {
        }
    }

你可能感兴趣的:(skywalking-agent初始化流程(二)-基于bytebuddy的增强机制)