本文主要研究一下skywalking的AbstractPlatformTransactionManagerInstrumentationjava
skywalking-6.6.0/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/define/AbstractPlatformTransactionManagerInstrumentation.javagit
public class AbstractPlatformTransactionManagerInstrumentation 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("getTransaction"); } @Override public String getMethodsInterceptor() { return "org.apache.skywalking.apm.plugin.spring.transaction.GetTransactionMethodInterceptor"; } @Override public boolean isOverrideArgs() { return false; } }, new InstanceMethodsInterceptPoint() { @Override public ElementMatcher<MethodDescription> getMethodsMatcher() { return named("commit").or(named("rollback")); } @Override public String getMethodsInterceptor() { return "org.apache.skywalking.apm.plugin.spring.transaction.EndTransactionMethodInterceptor"; } @Override public boolean isOverrideArgs() { return false; } } }; } @Override public ClassMatch enhanceClass() { return byName("org.springframework.transaction.support.AbstractPlatformTransactionManager"); } }
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassInstanceMethodsEnhancePluginDefine.javagithub
public abstract class ClassInstanceMethodsEnhancePluginDefine extends ClassEnhancePluginDefine { /** * @return null, means enhance no static methods. */ @Override public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { return null; } }
skywalking-6.6.0/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/plugin/interceptor/enhance/ClassEnhancePluginDefine.javaspring
public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePluginDefine { private static final ILog logger = LogManager.getLogger(ClassEnhancePluginDefine.class); /** * New field name. */ public static final String CONTEXT_ATTR_NAME = "_$EnhancedClassField_ws"; /** * Begin to define how to enhance class. After invoke this method, only means definition is finished. * * @param typeDescription target class description * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. */ @Override protected DynamicType.Builder<?> enhance(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader, EnhanceContext context) throws PluginException { newClassBuilder = this.enhanceClass(typeDescription, newClassBuilder, classLoader); newClassBuilder = this.enhanceInstance(typeDescription, newClassBuilder, classLoader, context); return newClassBuilder; } /** * Enhance a class to intercept constructors and class instance methods. * * @param typeDescription target class description * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. */ private DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader, EnhanceContext context) throws PluginException { ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints(); InstanceMethodsInterceptPoint[] instanceMethodsInterceptPoints = getInstanceMethodsInterceptPoints(); String enhanceOriginClassName = typeDescription.getTypeName(); boolean existedConstructorInterceptPoint = false; if (constructorInterceptPoints != null && constructorInterceptPoints.length > 0) { existedConstructorInterceptPoint = true; } boolean existedMethodsInterceptPoints = false; if (instanceMethodsInterceptPoints != null && instanceMethodsInterceptPoints.length > 0) { existedMethodsInterceptPoints = true; } /** * nothing need to be enhanced in class instance, maybe need enhance static methods. */ if (!existedConstructorInterceptPoint && !existedMethodsInterceptPoints) { return newClassBuilder; } /** * Manipulate class source code.<br/> * * new class need:<br/> * 1.Add field, name {@link #CONTEXT_ATTR_NAME}. * 2.Add a field accessor for this field. * * And make sure the source codes manipulation only occurs once. * */ if (!context.isObjectExtended()) { newClassBuilder = newClassBuilder.defineField(CONTEXT_ATTR_NAME, Object.class, ACC_PRIVATE | ACC_VOLATILE) .implement(EnhancedInstance.class) .intercept(FieldAccessor.ofField(CONTEXT_ATTR_NAME)); context.extendObjectCompleted(); } /** * 2. enhance constructors */ if (existedConstructorInterceptPoint) { for (ConstructorInterceptPoint constructorInterceptPoint : constructorInterceptPoints) { if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()).intercept(SuperMethodCall.INSTANCE .andThen(MethodDelegation.withDefaultConfiguration() .to(BootstrapInstrumentBoost.forInternalDelegateClass(constructorInterceptPoint.getConstructorInterceptor())) ) ); } else { newClassBuilder = newClassBuilder.constructor(constructorInterceptPoint.getConstructorMatcher()).intercept(SuperMethodCall.INSTANCE .andThen(MethodDelegation.withDefaultConfiguration() .to(new ConstructorInter(constructorInterceptPoint.getConstructorInterceptor(), classLoader)) ) ); } } } /** * 3. enhance instance methods */ if (existedMethodsInterceptPoints) { for (InstanceMethodsInterceptPoint instanceMethodsInterceptPoint : instanceMethodsInterceptPoints) { String interceptor = instanceMethodsInterceptPoint.getMethodsInterceptor(); if (StringUtil.isEmpty(interceptor)) { throw new EnhanceException("no InstanceMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName); } ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(instanceMethodsInterceptPoint.getMethodsMatcher()); if (instanceMethodsInterceptPoint instanceof DeclaredInstanceMethodsInterceptPoint) { junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription)); } if (instanceMethodsInterceptPoint.isOverrideArgs()) { if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.method(junction) .intercept( MethodDelegation.withDefaultConfiguration() .withBinders( Morph.Binder.install(OverrideCallable.class) ) .to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)) ); } else { newClassBuilder = newClassBuilder.method(junction) .intercept( MethodDelegation.withDefaultConfiguration() .withBinders( Morph.Binder.install(OverrideCallable.class) ) .to(new InstMethodsInterWithOverrideArgs(interceptor, classLoader)) ); } } else { if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.method(junction) .intercept( MethodDelegation.withDefaultConfiguration() .to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)) ); } else { newClassBuilder = newClassBuilder.method(junction) .intercept( MethodDelegation.withDefaultConfiguration() .to(new InstMethodsInter(interceptor, classLoader)) ); } } } } return newClassBuilder; } /** * Enhance a class to intercept class static methods. * * @param typeDescription target class description * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. */ private DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader) throws PluginException { StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints(); String enhanceOriginClassName = typeDescription.getTypeName(); if (staticMethodsInterceptPoints == null || staticMethodsInterceptPoints.length == 0) { return newClassBuilder; } for (StaticMethodsInterceptPoint staticMethodsInterceptPoint : staticMethodsInterceptPoints) { String interceptor = staticMethodsInterceptPoint.getMethodsInterceptor(); if (StringUtil.isEmpty(interceptor)) { throw new EnhanceException("no StaticMethodsAroundInterceptor define to enhance class " + enhanceOriginClassName); } if (staticMethodsInterceptPoint.isOverrideArgs()) { if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher())) .intercept( MethodDelegation.withDefaultConfiguration() .withBinders( Morph.Binder.install(OverrideCallable.class) ) .to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)) ); } else { newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher())) .intercept( MethodDelegation.withDefaultConfiguration() .withBinders( Morph.Binder.install(OverrideCallable.class) ) .to(new StaticMethodsInterWithOverrideArgs(interceptor)) ); } } else { if (isBootstrapInstrumentation()) { newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher())) .intercept( MethodDelegation.withDefaultConfiguration() .to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)) ); } else { newClassBuilder = newClassBuilder.method(isStatic().and(staticMethodsInterceptPoint.getMethodsMatcher())) .intercept( MethodDelegation.withDefaultConfiguration() .to(new StaticMethodsInter(interceptor)) ); } } } return newClassBuilder; } }
skywalking-6.6.0/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/GetTransactionMethodInterceptor.javaapache
public class GetTransactionMethodInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable { if (allArguments[0] == null) { AbstractSpan span = ContextManager.createLocalSpan(Constants.OPERATION_NAME_SPRING_TRANSACTION_NO_TRANSACTION_DEFINITION_GIVEN); span.setComponent(ComponentsDefine.SPRING_TX); return; } TransactionDefinition definition = (TransactionDefinition) allArguments[0]; AbstractSpan span = ContextManager.createLocalSpan(Constants.OPERATION_NAME_SPRING_TRANSACTION_GET_TRANSACTION_METHOD + buildOperationName(definition.getName())); span.tag(Constants.TAG_SPRING_TRANSACTION_ISOLATION_LEVEL, String.valueOf(definition.getIsolationLevel())); span.tag(Constants.TAG_SPRING_TRANSACTION_PROPAGATION_BEHAVIOR, String.valueOf(definition.getPropagationBehavior())); span.tag(Constants.TAG_SPRING_TRANSACTION_TIMEOUT, String.valueOf(definition.getTimeout())); span.setComponent(ComponentsDefine.SPRING_TX); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan(); return ret; } @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } private String buildOperationName(String transactionDefinitionName) { if (!Config.Plugin.SpringTransaction.SIMPLIFY_TRANSACTION_DEFINITION_NAME) { return transactionDefinitionName; } String[] ss = transactionDefinitionName.split("\\."); int simplifiedLength = ss.length - 2; if (simplifiedLength < 0) { return transactionDefinitionName; } StringBuilder name = new StringBuilder(); for (int i = 0; i < ss.length - 1; i++) { name.append(i < simplifiedLength ? ss[i].charAt(0) : ss[i]).append("."); } return name.append(ss[ss.length - 1]).toString(); } }
skywalking-6.6.0/apm-sniffer/optional-plugins/optional-spring-plugins/spring-tx-plugin/src/main/java/org/apache/skywalking/apm/plugin/spring/transaction/EndTransactionMethodInterceptor.java數組
public class EndTransactionMethodInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable { AbstractSpan span = ContextManager.createLocalSpan(Constants.OPERATION_NAME_SPRING_TRANSACTION_PREFIX + method.getName()); TransactionStatus status = (TransactionStatus) allArguments[0]; span.tag(Constants.TAG_SPRING_TRANSACTION_IS_NEW_TRANSACTION, String.valueOf(status.isNewTransaction())); span.tag(Constants.TAG_SPRING_TRANSACTION_HAS_SAVEPOINT, String.valueOf(status.hasSavepoint())); span.tag(Constants.TAG_SPRING_TRANSACTION_ROLLBACK_ONLY, String.valueOf(status.isRollbackOnly())); span.tag(Constants.TAG_SPRING_TRANSACTION_IS_COMPLETED, String.valueOf(status.isCompleted())); span.setComponent(ComponentsDefine.SPRING_TX); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable { ContextManager.stopSpan(); return ret; } @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } }
AbstractPlatformTransactionManagerInstrumentation繼承了ClassInstanceMethodsEnhancePluginDefine,其getInstanceMethodsInterceptPoints方法建立了InstanceMethodsInterceptPoint數組,其中一個InstanceMethodsInterceptPoint的getMethodsMatcher爲named("getTransaction"),getMethodsInterceptor返回org.apache.skywalking.apm.plugin.spring.transaction.GetTransactionMethodInterceptor;另一個InstanceMethodsInterceptPoint的getMethodsMatcher爲named("commit").or(named("rollback"),getMethodsInterceptor返回的是org.apache.skywalking.apm.plugin.spring.transaction.EndTransactionMethodInterceptor;其enhanceClass方法返回的是byName("org.springframework.transaction.support.AbstractPlatformTransactionManager")app