Introduce method interceptor v2 (#6937)
This commit is contained in:
parent
6c90a954ed
commit
015d3877cb
|
|
@ -61,6 +61,7 @@ jobs:
|
|||
- postgresql-above9.4.1207-scenario
|
||||
- mssql-jtds-scenario
|
||||
- mssql-jdbc-scenario
|
||||
- mybatis-3.x-scenario
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterc
|
|||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.apache.skywalking.apm.agent.core.util.CollectionUtil;
|
||||
import org.apache.skywalking.apm.util.StringUtil;
|
||||
|
|
@ -41,6 +43,11 @@ import java.util.List;
|
|||
public abstract class AbstractClassEnhancePluginDefine {
|
||||
private static final ILog LOGGER = LogManager.getLogger(AbstractClassEnhancePluginDefine.class);
|
||||
|
||||
/**
|
||||
* New field name.
|
||||
*/
|
||||
public static final String CONTEXT_ATTR_NAME = "_$EnhancedClassField_ws";
|
||||
|
||||
/**
|
||||
* Main entrance of enhancing the class.
|
||||
*
|
||||
|
|
@ -94,8 +101,43 @@ public abstract class AbstractClassEnhancePluginDefine {
|
|||
return newClassBuilder;
|
||||
}
|
||||
|
||||
protected abstract DynamicType.Builder<?> enhance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader, EnhanceContext context) throws PluginException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
protected abstract DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
|
||||
EnhanceContext context) throws PluginException;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected abstract DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader) throws PluginException;
|
||||
|
||||
/**
|
||||
* Define the {@link ClassMatch} for filtering class.
|
||||
|
|
@ -138,10 +180,24 @@ public abstract class AbstractClassEnhancePluginDefine {
|
|||
*/
|
||||
public abstract InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints();
|
||||
|
||||
/**
|
||||
* Instance methods intercept v2 point. See {@link InstanceMethodsInterceptV2Point}
|
||||
*
|
||||
* @return collections of {@link InstanceMethodsInterceptV2Point}
|
||||
*/
|
||||
public abstract InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points();
|
||||
|
||||
/**
|
||||
* Static methods intercept point. See {@link StaticMethodsInterceptPoint}
|
||||
*
|
||||
* @return collections of {@link StaticMethodsInterceptPoint}
|
||||
*/
|
||||
public abstract StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints();
|
||||
|
||||
/**
|
||||
* Instance methods intercept v2 point. See {@link InstanceMethodsInterceptV2Point}
|
||||
*
|
||||
* @return collections of {@link InstanceMethodsInterceptV2Point}
|
||||
*/
|
||||
public abstract StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.lang.instrument.Instrumentation;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
|
|
@ -42,6 +43,8 @@ import org.apache.skywalking.apm.agent.core.plugin.PluginFinder;
|
|||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.jdk9module.JDK9ModuleExporter;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader;
|
||||
|
||||
|
|
@ -62,7 +65,12 @@ public class BootstrapInstrumentBoost {
|
|||
"org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog",
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance",
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable",
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult"
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult",
|
||||
|
||||
// interceptor v2
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2",
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2",
|
||||
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext",
|
||||
};
|
||||
|
||||
private static String INSTANCE_METHOD_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.InstanceMethodInterTemplate";
|
||||
|
|
@ -71,14 +79,23 @@ public class BootstrapInstrumentBoost {
|
|||
private static String STATIC_METHOD_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.StaticMethodInterTemplate";
|
||||
private static String STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.StaticMethodInterWithOverrideArgsTemplate";
|
||||
|
||||
private static String INSTANCE_METHOD_V2_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2.InstanceMethodInterV2Template";
|
||||
private static String INSTANCE_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2.InstanceMethodInterV2WithOverrideArgsTemplate";
|
||||
private static String STATIC_METHOD_V2_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2.StaticMethodInterV2Template";
|
||||
private static String STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2.StaticMethodInterV2WithOverrideArgsTemplate";
|
||||
|
||||
public static AgentBuilder inject(PluginFinder pluginFinder, Instrumentation instrumentation,
|
||||
AgentBuilder agentBuilder, JDK9ModuleExporter.EdgeClasses edgeClasses) throws PluginException {
|
||||
Map<String, byte[]> classesTypeMap = new HashMap<String, byte[]>();
|
||||
Map<String, byte[]> classesTypeMap = new HashMap<>();
|
||||
|
||||
if (!prepareJREInstrumentation(pluginFinder, classesTypeMap)) {
|
||||
return agentBuilder;
|
||||
}
|
||||
|
||||
if (!prepareJREInstrumentationV2(pluginFinder, classesTypeMap)) {
|
||||
return agentBuilder;
|
||||
}
|
||||
|
||||
for (String highPriorityClass : HIGH_PRIORITY_CLASSES) {
|
||||
loadHighPriorityClass(classesTypeMap, highPriorityClass);
|
||||
}
|
||||
|
|
@ -141,25 +158,76 @@ public class BootstrapInstrumentBoost {
|
|||
TypePool typePool = TypePool.Default.of(BootstrapInstrumentBoost.class.getClassLoader());
|
||||
List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefines = pluginFinder.getBootstrapClassMatchDefine();
|
||||
for (AbstractClassEnhancePluginDefine define : bootstrapClassMatchDefines) {
|
||||
for (InstanceMethodsInterceptPoint point : define.getInstanceMethodsInterceptPoints()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(classesTypeMap, typePool, INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
|
||||
.getMethodsInterceptor());
|
||||
} else {
|
||||
generateDelegator(classesTypeMap, typePool, INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
|
||||
if (Objects.nonNull(define.getInstanceMethodsInterceptPoints())) {
|
||||
for (InstanceMethodsInterceptPoint point : define.getInstanceMethodsInterceptPoints()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
|
||||
.getMethodsInterceptor());
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ConstructorInterceptPoint point : define.getConstructorsInterceptPoints()) {
|
||||
generateDelegator(classesTypeMap, typePool, CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor());
|
||||
if (Objects.nonNull(define.getConstructorsInterceptPoints())) {
|
||||
for (ConstructorInterceptPoint point : define.getConstructorsInterceptPoints()) {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor());
|
||||
}
|
||||
}
|
||||
|
||||
for (StaticMethodsInterceptPoint point : define.getStaticMethodsInterceptPoints()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(classesTypeMap, typePool, STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
|
||||
.getMethodsInterceptor());
|
||||
} else {
|
||||
generateDelegator(classesTypeMap, typePool, STATIC_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
|
||||
if (Objects.nonNull(define.getStaticMethodsInterceptPoints())) {
|
||||
for (StaticMethodsInterceptPoint point : define.getStaticMethodsInterceptPoints()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
|
||||
.getMethodsInterceptor());
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, STATIC_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bootstrapClassMatchDefines.size() > 0;
|
||||
}
|
||||
|
||||
private static boolean prepareJREInstrumentationV2(PluginFinder pluginFinder,
|
||||
Map<String, byte[]> classesTypeMap) throws PluginException {
|
||||
TypePool typePool = TypePool.Default.of(BootstrapInstrumentBoost.class.getClassLoader());
|
||||
List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefines = pluginFinder.getBootstrapClassMatchDefine();
|
||||
for (AbstractClassEnhancePluginDefine define : bootstrapClassMatchDefines) {
|
||||
if (Objects.nonNull(define.getInstanceMethodsInterceptV2Points())) {
|
||||
for (InstanceMethodsInterceptV2Point point : define.getInstanceMethodsInterceptV2Points()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(classesTypeMap, typePool,
|
||||
INSTANCE_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2()
|
||||
);
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, INSTANCE_METHOD_V2_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Objects.nonNull(define.getStaticMethodsInterceptV2Points())) {
|
||||
for (StaticMethodsInterceptV2Point point : define.getStaticMethodsInterceptV2Points()) {
|
||||
if (point.isOverrideArgs()) {
|
||||
generateDelegator(classesTypeMap, typePool,
|
||||
STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2()
|
||||
);
|
||||
} else {
|
||||
generateDelegator(
|
||||
classesTypeMap, typePool, STATIC_METHOD_V2_DELEGATE_TEMPLATE,
|
||||
point.getMethodsInterceptorV2()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class InstanceMethodInterV2Template {
|
||||
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class InstanceMethodInterV2WithOverrideArgsTemplate {
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static InstanceMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Morph OverrideCallable zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (LOGGER != null) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class StaticMethodInterV2Template {
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static StaticMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@SuperCall Callable<?> zuper) throws Throwable {
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.BootstrapInterRuntimeAssist;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.StaticMethodsAroundInterceptorV2;
|
||||
|
||||
/**
|
||||
* This class wouldn't be loaded in real env. This is a class template for dynamic class generation.
|
||||
*/
|
||||
public class StaticMethodInterV2WithOverrideArgsTemplate {
|
||||
/**
|
||||
* This field is never set in the template, but has value in the runtime.
|
||||
*/
|
||||
private static String TARGET_INTERCEPTOR;
|
||||
|
||||
private static StaticMethodsAroundInterceptorV2 INTERCEPTOR;
|
||||
private static IBootstrapLog LOGGER;
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public static Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
prepare();
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
INTERCEPTOR.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context);
|
||||
}
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
if (INTERCEPTOR != null) {
|
||||
ret = INTERCEPTOR.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the context. Link to the agent core in AppClassLoader.
|
||||
*/
|
||||
private static void prepare() {
|
||||
if (INTERCEPTOR == null) {
|
||||
ClassLoader loader = BootstrapInterRuntimeAssist.getAgentClassLoader();
|
||||
|
||||
if (loader != null) {
|
||||
IBootstrapLog logger = BootstrapInterRuntimeAssist.getLogger(loader, TARGET_INTERCEPTOR);
|
||||
if (logger != null) {
|
||||
LOGGER = logger;
|
||||
|
||||
INTERCEPTOR = BootstrapInterRuntimeAssist.createInterceptor(loader, TARGET_INTERCEPTOR, LOGGER);
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Runtime ClassLoader not found when create {}." + TARGET_INTERCEPTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -38,6 +38,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.DeclaredInstanceM
|
|||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.EnhanceException;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.util.StringUtil;
|
||||
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE;
|
||||
|
|
@ -54,28 +56,6 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
|
|||
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.
|
||||
*
|
||||
|
|
@ -83,7 +63,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi
|
|||
* @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,
|
||||
protected DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
|
||||
EnhanceContext context) throws PluginException {
|
||||
ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
|
||||
|
|
@ -194,7 +174,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi
|
|||
* @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,
|
||||
protected DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription, DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader) throws PluginException {
|
||||
StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
|
|
@ -236,4 +216,21 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi
|
|||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 instance methods.
|
||||
*/
|
||||
@Override
|
||||
public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 static methods.
|
||||
*/
|
||||
@Override
|
||||
public StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public class ConstructorInter {
|
|||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceConstructorInterceptor.", t);
|
||||
throw new PluginException("Can't create InstanceConstructorInterceptorV2.", t);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.dynamic.DynamicType;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.EnhanceContext;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.PluginException;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.bootstrap.BootstrapInstrumentBoost;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.EnhanceException;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.ConstructorInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.DeclaredInstanceMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.util.StringUtil;
|
||||
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE;
|
||||
import static net.bytebuddy.jar.asm.Opcodes.ACC_VOLATILE;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.isStatic;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* This class controls all enhance operations, including enhance constructors, instance methods and static methods. All
|
||||
* the enhances base on three types interceptor point: {@link ConstructorInterceptV2Point}, {@link
|
||||
* InstanceMethodsInterceptV2Point} and {@link StaticMethodsInterceptV2Point} If plugin is going to enhance constructors,
|
||||
* instance methods, or both, {@link ClassEnhancePluginDefineV2} will add a field of {@link Object} type.
|
||||
*/
|
||||
public abstract class ClassEnhancePluginDefineV2 extends AbstractClassEnhancePluginDefine {
|
||||
|
||||
protected DynamicType.Builder<?> enhanceClass(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder,
|
||||
ClassLoader classLoader) throws PluginException {
|
||||
StaticMethodsInterceptV2Point[] staticMethodsInterceptV2Points = getStaticMethodsInterceptV2Points();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
if (staticMethodsInterceptV2Points == null || staticMethodsInterceptV2Points.length == 0) {
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
for (StaticMethodsInterceptV2Point staticMethodsInterceptV2Point : staticMethodsInterceptV2Points) {
|
||||
String interceptor = staticMethodsInterceptV2Point.getMethodsInterceptorV2();
|
||||
if (StringUtil.isEmpty(interceptor)) {
|
||||
throw new EnhanceException(
|
||||
"no StaticMethodsAroundInterceptorV2 define to enhance class " + enhanceOriginClassName);
|
||||
}
|
||||
|
||||
if (staticMethodsInterceptV2Point.isOverrideArgs()) {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.withBinders(Morph.Binder.install(OverrideCallable.class))
|
||||
.to(new StaticMethodsInterV2WithOverrideArgs(interceptor)));
|
||||
}
|
||||
} else {
|
||||
if (isBootstrapInstrumentation()) {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(BootstrapInstrumentBoost.forInternalDelegateClass(interceptor)));
|
||||
} else {
|
||||
newClassBuilder = newClassBuilder.method(
|
||||
isStatic().and(staticMethodsInterceptV2Point.getMethodsMatcher()))
|
||||
.intercept(MethodDelegation.withDefaultConfiguration()
|
||||
.to(new StaticMethodsInterV2(interceptor)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
protected DynamicType.Builder<?> enhanceInstance(TypeDescription typeDescription,
|
||||
DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
|
||||
EnhanceContext context) throws PluginException {
|
||||
InstanceMethodsInterceptV2Point[] instanceMethodsInterceptV2Points = getInstanceMethodsInterceptV2Points();
|
||||
String enhanceOriginClassName = typeDescription.getTypeName();
|
||||
boolean existedMethodsInterceptV2Points = false;
|
||||
if (instanceMethodsInterceptV2Points != null && instanceMethodsInterceptV2Points.length > 0) {
|
||||
existedMethodsInterceptV2Points = true;
|
||||
}
|
||||
|
||||
if (!existedMethodsInterceptV2Points) {
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
if (!typeDescription.isAssignableTo(EnhancedInstance.class)) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
if (existedMethodsInterceptV2Points) {
|
||||
for (InstanceMethodsInterceptV2Point instanceMethodsInterceptV2Point : instanceMethodsInterceptV2Points) {
|
||||
String interceptor = instanceMethodsInterceptV2Point.getMethodsInterceptorV2();
|
||||
if (StringUtil.isEmpty(interceptor)) {
|
||||
throw new EnhanceException(
|
||||
"no InstanceMethodsAroundInterceptorV2 define to enhance class " + enhanceOriginClassName);
|
||||
}
|
||||
ElementMatcher.Junction<MethodDescription> junction = not(isStatic()).and(
|
||||
instanceMethodsInterceptV2Point.getMethodsMatcher());
|
||||
if (instanceMethodsInterceptV2Point instanceof DeclaredInstanceMethodsInterceptV2Point) {
|
||||
junction = junction.and(ElementMatchers.<MethodDescription>isDeclaredBy(typeDescription));
|
||||
}
|
||||
if (instanceMethodsInterceptV2Point.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 InstMethodsInterV2WithOverrideArgs(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 InstMethodsInterV2(interceptor, classLoader)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newClassBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.StaticMethodsInterceptV2Point;
|
||||
|
||||
/**
|
||||
* Plugins, which only need enhance class instance methods. Actually, inherit from {@link
|
||||
* ClassInstanceMethodsEnhancePluginDefineV2} has no differences with inherit from {@link ClassEnhancePluginDefineV2}.
|
||||
* Just override {@link ClassEnhancePluginDefineV2#getStaticMethodsInterceptPoints}, and return NULL, which means nothing
|
||||
* to enhance.
|
||||
*/
|
||||
public abstract class ClassInstanceMethodsEnhancePluginDefineV2 extends ClassEnhancePluginDefineV2 {
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 static methods.
|
||||
*/
|
||||
@Override
|
||||
public StaticMethodsInterceptV2Point[] getStaticMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
|
||||
/**
|
||||
* Plugins, which only need enhance class static methods. Actually, inherit from {@link
|
||||
* ClassStaticMethodsEnhancePluginDefineV2} has no differences with inherit from {@link ClassEnhancePluginDefineV2}. Just
|
||||
* override {@link ClassEnhancePluginDefineV2#getConstructorsInterceptPoints} and {@link
|
||||
* ClassEnhancePluginDefineV2#getInstanceMethodsInterceptV2Points}, and return NULL, which means nothing to enhance.
|
||||
*/
|
||||
public abstract class ClassStaticMethodsEnhancePluginDefineV2 extends ClassEnhancePluginDefineV2 {
|
||||
|
||||
/**
|
||||
* @return null, means enhance no constructors.
|
||||
*/
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null, means enhance no v2 instance methods.
|
||||
*/
|
||||
@Override
|
||||
public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.PluginException;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provide a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class InstMethodsInterV2 {
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterV2.class);
|
||||
|
||||
private InstanceMethodsAroundInterceptorV2 interceptor;
|
||||
|
||||
public InstMethodsInterV2(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
|
||||
}
|
||||
}
|
||||
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper,
|
||||
@Origin Method method) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.PluginException;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provide a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class InstMethodsInterV2WithOverrideArgs {
|
||||
private static final ILog LOGGER = LogManager.getLogger(InstMethodsInterV2WithOverrideArgs.class);
|
||||
|
||||
/**
|
||||
* An {@link InstanceMethodsAroundInterceptorV2} This name should only stay in {@link String}, the real {@link Class}
|
||||
* type will trigger classloader failure. If you want to know more, please check on books about Classloader or
|
||||
* Classloader appointment mechanism.
|
||||
*/
|
||||
private InstanceMethodsAroundInterceptorV2 interceptor;
|
||||
|
||||
/**
|
||||
* @param instanceMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public InstMethodsInterV2WithOverrideArgs(String instanceMethodsAroundInterceptorClassName, ClassLoader classLoader) {
|
||||
try {
|
||||
interceptor = InterceptorInstanceLoader.load(instanceMethodsAroundInterceptorClassName, classLoader);
|
||||
} catch (Throwable t) {
|
||||
throw new PluginException("Can't create InstanceMethodsAroundInterceptor.", t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target instance method.
|
||||
*
|
||||
* @param obj target class instance.
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target instance method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@This Object obj, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
EnhancedInstance targetObject = (EnhancedInstance) obj;
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
interceptor.beforeMethod(targetObject, method, allArguments, method.getParameterTypes(), context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(targetObject, method, allArguments, method.getParameterTypes(), t, context);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle method[{}] exception failure", obj.getClass(), method.getName());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(targetObject, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after method[{}] intercept failure", obj.getClass(), method.getName());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
|
||||
/**
|
||||
* A v2 interceptor, which intercept method's invocation. The target methods will be defined in {@link
|
||||
* ClassEnhancePluginDefineV2}'s subclass, most likely in {@link ClassInstanceMethodsEnhancePluginDefine}
|
||||
*/
|
||||
public interface InstanceMethodsAroundInterceptorV2 {
|
||||
/**
|
||||
* called before target method invocation.
|
||||
*
|
||||
* @param context the method invocation context including result context.
|
||||
*/
|
||||
void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInvocationContext context) throws Throwable;
|
||||
|
||||
/**
|
||||
* called after target method invocation. Even method's invocation triggers an exception.
|
||||
*
|
||||
* @param ret the method's original return value. May be null if the method triggers an exception.
|
||||
* @return the method's actual return value.
|
||||
*/
|
||||
Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret, MethodInvocationContext context) throws Throwable;
|
||||
|
||||
/**
|
||||
* called when occur exception.
|
||||
*
|
||||
* @param t the exception occur.
|
||||
*/
|
||||
void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t, MethodInvocationContext context);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
|
||||
public class MethodInvocationContext extends MethodInterceptResult {
|
||||
|
||||
private Object context;
|
||||
|
||||
public Object getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public void setContext(Object context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* The static method's interceptor v2 interface. Any plugin, which wants to intercept static methods, must implement this
|
||||
* interface.
|
||||
*/
|
||||
public interface StaticMethodsAroundInterceptorV2 {
|
||||
/**
|
||||
* called before target method invocation.
|
||||
*
|
||||
* @param context the method invocation context including result context.
|
||||
*/
|
||||
void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
MethodInvocationContext context);
|
||||
|
||||
/**
|
||||
* called after target method invocation. Even method's invocation triggers an exception.
|
||||
*
|
||||
* @param ret the method's original return value.
|
||||
* @return the method's actual return value.
|
||||
*/
|
||||
Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, Object ret,
|
||||
MethodInvocationContext context);
|
||||
|
||||
/**
|
||||
* called when occur exception.
|
||||
*
|
||||
* @param t the exception occur.
|
||||
*/
|
||||
void handleMethodException(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
|
||||
Throwable t, MethodInvocationContext context);
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.SuperCall;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provide a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class StaticMethodsInterV2 {
|
||||
private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInterV2.class);
|
||||
|
||||
/**
|
||||
* A class full name, and instanceof {@link StaticMethodsAroundInterceptorV2} This name should only stay in {@link
|
||||
* String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on
|
||||
* books about Classloader or Classloader appointment mechanism.
|
||||
*/
|
||||
private String staticMethodsAroundInterceptorClassName;
|
||||
|
||||
/**
|
||||
* Set the name of {@link StaticMethodsInterV2#staticMethodsAroundInterceptorClassName}
|
||||
*
|
||||
* @param staticMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public StaticMethodsInterV2(String staticMethodsAroundInterceptorClassName) {
|
||||
this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@SuperCall Callable<?> zuper) throws Throwable {
|
||||
StaticMethodsAroundInterceptorV2 interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName,
|
||||
clazz.getClassLoader());
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.Morph;
|
||||
import net.bytebuddy.implementation.bind.annotation.Origin;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.ILog;
|
||||
import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.loader.InterceptorInstanceLoader;
|
||||
|
||||
/**
|
||||
* The actual byte-buddy's interceptor to intercept class instance methods. In this class, it provide a bridge between
|
||||
* byte-buddy and sky-walking plugin.
|
||||
*/
|
||||
public class StaticMethodsInterV2WithOverrideArgs {
|
||||
private static final ILog LOGGER = LogManager.getLogger(StaticMethodsInterV2WithOverrideArgs.class);
|
||||
|
||||
/**
|
||||
* A class full name, and instanceof {@link StaticMethodsAroundInterceptorV2} This name should only stay in {@link
|
||||
* String}, the real {@link Class} type will trigger classloader failure. If you want to know more, please check on
|
||||
* books about Classloader or Classloader appointment mechanism.
|
||||
*/
|
||||
private String staticMethodsAroundInterceptorClassName;
|
||||
|
||||
/**
|
||||
* Set the name of {@link StaticMethodsInterV2WithOverrideArgs#staticMethodsAroundInterceptorClassName}
|
||||
*
|
||||
* @param staticMethodsAroundInterceptorClassName class full name.
|
||||
*/
|
||||
public StaticMethodsInterV2WithOverrideArgs(String staticMethodsAroundInterceptorClassName) {
|
||||
this.staticMethodsAroundInterceptorClassName = staticMethodsAroundInterceptorClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercept the target static method.
|
||||
*
|
||||
* @param clazz target class
|
||||
* @param allArguments all method arguments
|
||||
* @param method method description.
|
||||
* @param zuper the origin call ref.
|
||||
* @return the return value of target static method.
|
||||
* @throws Exception only throw exception because of zuper.call() or unexpected exception in sky-walking ( This is a
|
||||
* bug, if anything triggers this condition ).
|
||||
*/
|
||||
@RuntimeType
|
||||
public Object intercept(@Origin Class<?> clazz, @AllArguments Object[] allArguments, @Origin Method method,
|
||||
@Morph OverrideCallable zuper) throws Throwable {
|
||||
StaticMethodsAroundInterceptorV2 interceptor = InterceptorInstanceLoader.load(staticMethodsAroundInterceptorClassName,
|
||||
clazz.getClassLoader());
|
||||
|
||||
MethodInvocationContext context = new MethodInvocationContext();
|
||||
try {
|
||||
interceptor.beforeMethod(clazz, method, allArguments, method.getParameterTypes(), context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] before static method[{}] intercept failure", clazz, method.getName());
|
||||
}
|
||||
|
||||
Object ret = null;
|
||||
try {
|
||||
if (!context.isContinue()) {
|
||||
ret = context._ret();
|
||||
} else {
|
||||
ret = zuper.call(allArguments);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
interceptor.handleMethodException(clazz, method, allArguments, method.getParameterTypes(), t, context);
|
||||
} catch (Throwable t2) {
|
||||
LOGGER.error(t2, "class[{}] handle static method[{}] exception failure", clazz, method.getName(), t2.getMessage());
|
||||
}
|
||||
throw t;
|
||||
} finally {
|
||||
try {
|
||||
ret = interceptor.afterMethod(clazz, method, allArguments, method.getParameterTypes(), ret, context);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.error(t, "class[{}] after static method[{}] intercept failure:{}", clazz, method.getName(), t.getMessage());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.v2;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
|
||||
public interface ConstructorInterceptV2Point {
|
||||
|
||||
/**
|
||||
* Constructor matcher
|
||||
*
|
||||
* @return matcher instance.
|
||||
*/
|
||||
ElementMatcher<MethodDescription> getConstructorMatcher();
|
||||
|
||||
/**
|
||||
* @return represents a class name, the class instance must be a instance of {@link
|
||||
* org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor}
|
||||
*/
|
||||
String getConstructorInterceptorV2();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.v2;
|
||||
|
||||
/**
|
||||
* this interface for those who only want to enhance declared method in case of some unexpected issue, such as spring
|
||||
* controller
|
||||
*/
|
||||
public interface DeclaredInstanceMethodsInterceptV2Point extends InstanceMethodsInterceptV2Point {
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.v2;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
|
||||
/**
|
||||
* One of the three "Intercept Point". "Intercept Point" is a definition about where and how intercept happens. In this
|
||||
* "Intercept Point", the definition targets class's instance methods, and the interceptor.
|
||||
* <p>
|
||||
* ref to two others: {@link ConstructorInterceptPoint} and {@link StaticMethodsInterceptV2Point}
|
||||
* <p>
|
||||
*/
|
||||
public interface InstanceMethodsInterceptV2Point {
|
||||
/**
|
||||
* class instance methods matcher.
|
||||
*
|
||||
* @return methods matcher
|
||||
*/
|
||||
ElementMatcher<MethodDescription> getMethodsMatcher();
|
||||
|
||||
/**
|
||||
* @return represents a class name, the class instance must instanceof InstanceMethodsAroundInterceptorV2.
|
||||
*/
|
||||
String getMethodsInterceptorV2();
|
||||
|
||||
boolean isOverrideArgs();
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.agent.core.plugin.interceptor.v2;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
|
||||
/**
|
||||
* One of the three "Intercept Point". "Intercept Point" is a definition about where and how intercept happens. In this
|
||||
* "Intercept Point", the definition targets class's static methods, and the interceptor.
|
||||
* <p>
|
||||
* ref to two others: {@link ConstructorInterceptPoint} and {@link InstanceMethodsInterceptV2Point}
|
||||
* <p>
|
||||
*/
|
||||
public interface StaticMethodsInterceptV2Point {
|
||||
/**
|
||||
* static methods matcher.
|
||||
*
|
||||
* @return matcher instance.
|
||||
*/
|
||||
ElementMatcher<MethodDescription> getMethodsMatcher();
|
||||
|
||||
/**
|
||||
* @return represents a class name, the class instance must instanceof StaticMethodsAroundInterceptorV2.
|
||||
*/
|
||||
String getMethodsInterceptorV2();
|
||||
|
||||
boolean isOverrideArgs();
|
||||
}
|
||||
|
|
@ -21,4 +21,7 @@ package org.apache.skywalking.apm.plugin.mybatis;
|
|||
|
||||
public class Constants {
|
||||
public static final String MYBATIS_SHELL_METHOD_NAME = "mybatis_shell_method_name";
|
||||
|
||||
public static final Object COLLECTED_FLAG = new Object();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ public class MyBatisInterceptor implements InstanceMethodsAroundInterceptor {
|
|||
String operationName;
|
||||
if (ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME) != null) {
|
||||
operationName = String.valueOf(ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME));
|
||||
ContextManager.getRuntimeContext().remove(Constants.MYBATIS_SHELL_METHOD_NAME);
|
||||
} else {
|
||||
operationName = MethodUtil.generateOperationName(method);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,18 +19,20 @@
|
|||
package org.apache.skywalking.apm.plugin.mybatis;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
import org.apache.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
|
||||
import org.apache.skywalking.apm.agent.core.util.MethodUtil;
|
||||
|
||||
public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInterceptorV2 {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
MethodInvocationContext context) throws Throwable {
|
||||
if (ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME) == null) {
|
||||
context.setContext(Constants.COLLECTED_FLAG);
|
||||
String operationName = MethodUtil.generateOperationName(method);
|
||||
ContextManager.getRuntimeContext().put(Constants.MYBATIS_SHELL_METHOD_NAME, operationName);
|
||||
}
|
||||
|
|
@ -38,13 +40,18 @@ public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInter
|
|||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
Object ret, MethodInvocationContext context) throws Throwable {
|
||||
if (Objects.nonNull(context.getContext())) {
|
||||
ContextManager.getRuntimeContext().remove(Constants.MYBATIS_SHELL_METHOD_NAME);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
Class<?>[] argumentsTypes, Throwable t, MethodInvocationContext context) {
|
||||
if (Objects.nonNull(context.getContext())) {
|
||||
ContextManager.getRuntimeContext().remove(Constants.MYBATIS_SHELL_METHOD_NAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,14 +21,14 @@ package org.apache.skywalking.apm.plugin.mybatis.define;
|
|||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.apache.skywalking.apm.plugin.mybatis.MyBatisMethodMatch;
|
||||
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 {
|
||||
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
|
|
@ -36,16 +36,16 @@ public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhan
|
|||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
|
||||
return new InstanceMethodsInterceptV2Point[] {
|
||||
new InstanceMethodsInterceptV2Point() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return MyBatisMethodMatch.INSTANCE.getMyBatisShellMethodMatcher();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
public String getMethodsInterceptorV2() {
|
||||
return "org.apache.skywalking.apm.plugin.mybatis.MyBatisShellMethodInterceptor";
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue