聊聊skywalking的async-annotation-plugin

  • 2020 年 3 月 13 日
  • 笔记

本文主要研究一下skywalking的async-annotation-plugin

AsyncExecutionInterceptorInstrumentation

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/async/define/AsyncExecutionInterceptorInstrumentation.java

public class AsyncExecutionInterceptorInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {        @Override      public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {          return new ConstructorInterceptPoint[0];      }        @Override      public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {          return new InstanceMethodsInterceptPoint[]{              new InstanceMethodsInterceptPoint() {                  @Override                  public ElementMatcher<MethodDescription> getMethodsMatcher() {                      return named("doSubmit").and(takesArgumentWithType(0, "java.util.concurrent.Callable"));                  }                    @Override                  public String getMethodsInterceptor() {                      return "org.apache.skywalking.apm.plugin.spring.async.DoSubmitMethodInterceptor";                  }                    @Override                  public boolean isOverrideArgs() {                      return true;                  }              }          };      }        @Override      public ClassMatch enhanceClass() {          return byName("org.springframework.aop.interceptor.AsyncExecutionAspectSupport");      }  }
  • AsyncExecutionInterceptorInstrumentation继承了ClassInstanceMethodsEnhancePluginDefine,它使用org.apache.skywalking.apm.plugin.spring.async.DoSubmitMethodInterceptor拦截org.springframework.aop.interceptor.AsyncExecutionAspectSupport的第一个参数类型为java.util.concurrent.Callable的doSubmit方法

DoSubmitMethodInterceptor

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/async/DoSubmitMethodInterceptor.java

public class DoSubmitMethodInterceptor implements InstanceMethodsAroundInterceptor {        @Override      public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,                               MethodInterceptResult result) throws Throwable {          if (ContextManager.isActive()) {              allArguments[0] = new SWCallable((Callable) allArguments[0], ContextManager.capture());          }      }        @Override      public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,                                Class<?>[] argumentsTypes, Object ret) throws Throwable {          return ret;      }          @Override      public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,                                        Class<?>[] argumentsTypes, Throwable t) {      }  }
  • DoSubmitMethodInterceptor实现了InstanceMethodsAroundInterceptor接口,其beforeMethod方法将allArguments[0]包装为SWCallable

SWCallable

skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/spring-plugins/async-annotation-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/async/SWCallable.java

public class SWCallable<V> implements Callable<V> {        private static final String OPERATION_NAME = "SpringAsync";        private Callable<V> callable;        private ContextSnapshot snapshot;        SWCallable(Callable<V> callable, ContextSnapshot snapshot) {          this.callable = callable;          this.snapshot = snapshot;      }        @Override      public V call() throws Exception {          AbstractSpan span = ContextManager.createLocalSpan(SWCallable.OPERATION_NAME);          span.setComponent(ComponentsDefine.SPRING_ASYNC);          try {              ContextManager.continued(snapshot);              return callable.call();          } catch (Exception e) {              ContextManager.activeSpan().errorOccurred().log(e);              throw e;          } finally {              ContextManager.stopSpan();          }      }  }
  • SWCallable实现了Callable接口,其call方法在执行callable.call()之前先ContextManager.createLocalSpan,然后执行ContextManager.continued(snapshot),之后在catch异常里头执行ContextManager.activeSpan().errorOccurred().log(e),最后在finally里头执行ContextManager.stopSpan()

小结

AsyncExecutionInterceptorInstrumentation继承了ClassInstanceMethodsEnhancePluginDefine,它使用org.apache.skywalking.apm.plugin.spring.async.DoSubmitMethodInterceptor拦截org.springframework.aop.interceptor.AsyncExecutionAspectSupport的第一个参数类型为java.util.concurrent.Callable的doSubmit方法

doc

  • AsyncExecutionInterceptorInstrumentation