美文网首页
skywalking-agent初始化流程(二)-基于byteb

skywalking-agent初始化流程(二)-基于byteb

作者: 李亚林1990 | 来源:发表于2020-08-10 20:28 被阅读0次

    接上篇:
    对于所有的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<String, LinkedList<AbstractClassEnhancePluginDefine>> nameMatchDefine = new HashMap<String, LinkedList<AbstractClassEnhancePluginDefine>>();
    //非名称匹配:方法注解匹配、类注解匹配等
    private final List<AbstractClassEnhancePluginDefine> signatureMatchDefine = new ArrayList<AbstractClassEnhancePluginDefine>();
    //返回bytebuddy元素匹配器,用户判断是否匹配
    public ElementMatcher<? super TypeDescription> buildMatch() {
            ElementMatcher.Junction judge = new AbstractJunction<NamedElement>() {
                @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图如下:


    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<AbstractClassEnhancePluginDefine> 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图:


    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初始化流程(二)-基于byteb

          本文链接:https://www.haomeiwen.com/subject/misqdktx.html