未验证 提交 015d3877 编写于 作者: D Daming 提交者: GitHub

Introduce method interceptor v2 (#6937)

上级 6c90a954
...@@ -61,6 +61,7 @@ jobs: ...@@ -61,6 +61,7 @@ jobs:
- postgresql-above9.4.1207-scenario - postgresql-above9.4.1207-scenario
- mssql-jtds-scenario - mssql-jtds-scenario
- mssql-jdbc-scenario - mssql-jdbc-scenario
- mybatis-3.x-scenario
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
......
...@@ -26,6 +26,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterc ...@@ -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.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint; 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.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.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.util.CollectionUtil; import org.apache.skywalking.apm.agent.core.util.CollectionUtil;
import org.apache.skywalking.apm.util.StringUtil; import org.apache.skywalking.apm.util.StringUtil;
...@@ -41,6 +43,11 @@ import java.util.List; ...@@ -41,6 +43,11 @@ import java.util.List;
public abstract class AbstractClassEnhancePluginDefine { public abstract class AbstractClassEnhancePluginDefine {
private static final ILog LOGGER = LogManager.getLogger(AbstractClassEnhancePluginDefine.class); 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. * Main entrance of enhancing the class.
* *
...@@ -94,8 +101,43 @@ public abstract class AbstractClassEnhancePluginDefine { ...@@ -94,8 +101,43 @@ public abstract class AbstractClassEnhancePluginDefine {
return newClassBuilder; 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. * Define the {@link ClassMatch} for filtering class.
...@@ -138,10 +180,24 @@ public abstract class AbstractClassEnhancePluginDefine { ...@@ -138,10 +180,24 @@ public abstract class AbstractClassEnhancePluginDefine {
*/ */
public abstract InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints(); 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} * Static methods intercept point. See {@link StaticMethodsInterceptPoint}
* *
* @return collections of {@link StaticMethodsInterceptPoint} * @return collections of {@link StaticMethodsInterceptPoint}
*/ */
public abstract StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints(); 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; ...@@ -25,6 +25,7 @@ import java.lang.instrument.Instrumentation;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
...@@ -42,6 +43,8 @@ import org.apache.skywalking.apm.agent.core.plugin.PluginFinder; ...@@ -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.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; 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.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.jdk9module.JDK9ModuleExporter;
import org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader; import org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader;
...@@ -62,7 +65,12 @@ public class BootstrapInstrumentBoost { ...@@ -62,7 +65,12 @@ public class BootstrapInstrumentBoost {
"org.apache.skywalking.apm.agent.core.plugin.bootstrap.IBootstrapLog", "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.EnhancedInstance",
"org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.OverrideCallable", "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"; private static String INSTANCE_METHOD_DELEGATE_TEMPLATE = "org.apache.skywalking.apm.agent.core.plugin.bootstrap.template.InstanceMethodInterTemplate";
...@@ -71,14 +79,23 @@ public class BootstrapInstrumentBoost { ...@@ -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_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 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, public static AgentBuilder inject(PluginFinder pluginFinder, Instrumentation instrumentation,
AgentBuilder agentBuilder, JDK9ModuleExporter.EdgeClasses edgeClasses) throws PluginException { 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)) { if (!prepareJREInstrumentation(pluginFinder, classesTypeMap)) {
return agentBuilder; return agentBuilder;
} }
if (!prepareJREInstrumentationV2(pluginFinder, classesTypeMap)) {
return agentBuilder;
}
for (String highPriorityClass : HIGH_PRIORITY_CLASSES) { for (String highPriorityClass : HIGH_PRIORITY_CLASSES) {
loadHighPriorityClass(classesTypeMap, highPriorityClass); loadHighPriorityClass(classesTypeMap, highPriorityClass);
} }
...@@ -141,25 +158,76 @@ public class BootstrapInstrumentBoost { ...@@ -141,25 +158,76 @@ public class BootstrapInstrumentBoost {
TypePool typePool = TypePool.Default.of(BootstrapInstrumentBoost.class.getClassLoader()); TypePool typePool = TypePool.Default.of(BootstrapInstrumentBoost.class.getClassLoader());
List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefines = pluginFinder.getBootstrapClassMatchDefine(); List<AbstractClassEnhancePluginDefine> bootstrapClassMatchDefines = pluginFinder.getBootstrapClassMatchDefine();
for (AbstractClassEnhancePluginDefine define : bootstrapClassMatchDefines) { for (AbstractClassEnhancePluginDefine define : bootstrapClassMatchDefines) {
for (InstanceMethodsInterceptPoint point : define.getInstanceMethodsInterceptPoints()) { if (Objects.nonNull(define.getInstanceMethodsInterceptPoints())) {
if (point.isOverrideArgs()) { for (InstanceMethodsInterceptPoint point : define.getInstanceMethodsInterceptPoints()) {
generateDelegator(classesTypeMap, typePool, INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point if (point.isOverrideArgs()) {
.getMethodsInterceptor()); generateDelegator(
} else { classesTypeMap, typePool, INSTANCE_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point
generateDelegator(classesTypeMap, typePool, INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor()); .getMethodsInterceptor());
} else {
generateDelegator(
classesTypeMap, typePool, INSTANCE_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor());
}
}
}
if (Objects.nonNull(define.getConstructorsInterceptPoints())) {
for (ConstructorInterceptPoint point : define.getConstructorsInterceptPoints()) {
generateDelegator(
classesTypeMap, typePool, CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor());
}
}
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;
}
for (ConstructorInterceptPoint point : define.getConstructorsInterceptPoints()) { private static boolean prepareJREInstrumentationV2(PluginFinder pluginFinder,
generateDelegator(classesTypeMap, typePool, CONSTRUCTOR_DELEGATE_TEMPLATE, point.getConstructorInterceptor()); 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()
);
}
}
} }
for (StaticMethodsInterceptPoint point : define.getStaticMethodsInterceptPoints()) { if (Objects.nonNull(define.getStaticMethodsInterceptV2Points())) {
if (point.isOverrideArgs()) { for (StaticMethodsInterceptV2Point point : define.getStaticMethodsInterceptV2Points()) {
generateDelegator(classesTypeMap, typePool, STATIC_METHOD_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE, point if (point.isOverrideArgs()) {
.getMethodsInterceptor()); generateDelegator(classesTypeMap, typePool,
} else { STATIC_METHOD_V2_WITH_OVERRIDE_ARGS_DELEGATE_TEMPLATE,
generateDelegator(classesTypeMap, typePool, STATIC_METHOD_DELEGATE_TEMPLATE, point.getMethodsInterceptor()); point.getMethodsInterceptorV2()
);
} else {
generateDelegator(
classesTypeMap, typePool, STATIC_METHOD_V2_DELEGATE_TEMPLATE,
point.getMethodsInterceptorV2()
);
}
} }
} }
} }
......
/*
* 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);
}
}
}
}
/*
* 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);
}
}
}
}
/*
* 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);
}
}
}
}
/*
* 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 ...@@ -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.EnhanceException;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; 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.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 org.apache.skywalking.apm.util.StringUtil;
import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE; import static net.bytebuddy.jar.asm.Opcodes.ACC_PRIVATE;
...@@ -54,28 +56,6 @@ import static net.bytebuddy.matcher.ElementMatchers.not; ...@@ -54,28 +56,6 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePluginDefine { public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePluginDefine {
private static final ILog LOGGER = LogManager.getLogger(ClassEnhancePluginDefine.class); 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. * Enhance a class to intercept constructors and class instance methods.
* *
...@@ -83,7 +63,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi ...@@ -83,7 +63,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
* @return new byte-buddy's builder for further manipulation. * @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, DynamicType.Builder<?> newClassBuilder, ClassLoader classLoader,
EnhanceContext context) throws PluginException { EnhanceContext context) throws PluginException {
ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints(); ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints();
...@@ -194,7 +174,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi ...@@ -194,7 +174,7 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi
* @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @param newClassBuilder byte-buddy's builder to manipulate class bytecode.
* @return new byte-buddy's builder for further manipulation. * @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 { ClassLoader classLoader) throws PluginException {
StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints(); StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints();
String enhanceOriginClassName = typeDescription.getTypeName(); String enhanceOriginClassName = typeDescription.getTypeName();
...@@ -236,4 +216,21 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi ...@@ -236,4 +216,21 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi
return newClassBuilder; 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 { ...@@ -47,7 +47,7 @@ public class ConstructorInter {
try { try {
interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, classLoader); interceptor = InterceptorInstanceLoader.load(constructorInterceptorClassName, classLoader);
} catch (Throwable t) { } catch (Throwable t) {
throw new PluginException("Can't create InstanceConstructorInterceptor.", t); throw new PluginException("Can't create InstanceConstructorInterceptorV2.", t);
} }
} }
......
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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);
}
/*
* 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;
}
}
/*
* 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);
}
/*
* 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;
}
}
/*
* 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;
}
}
/*
* 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();
}
/*
* 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 {
}
/*
* 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();
}
/*
* 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; ...@@ -21,4 +21,7 @@ package org.apache.skywalking.apm.plugin.mybatis;
public class Constants { public class Constants {
public static final String MYBATIS_SHELL_METHOD_NAME = "mybatis_shell_method_name"; 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 { ...@@ -36,7 +36,6 @@ public class MyBatisInterceptor implements InstanceMethodsAroundInterceptor {
String operationName; String operationName;
if (ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME) != null) { if (ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME) != null) {
operationName = String.valueOf(ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME)); operationName = String.valueOf(ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME));
ContextManager.getRuntimeContext().remove(Constants.MYBATIS_SHELL_METHOD_NAME);
} else { } else {
operationName = MethodUtil.generateOperationName(method); operationName = MethodUtil.generateOperationName(method);
} }
......
...@@ -19,18 +19,20 @@ ...@@ -19,18 +19,20 @@
package org.apache.skywalking.apm.plugin.mybatis; package org.apache.skywalking.apm.plugin.mybatis;
import java.lang.reflect.Method; 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.context.ContextManager;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; 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.v2.InstanceMethodsAroundInterceptorV2;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
import org.apache.skywalking.apm.agent.core.util.MethodUtil; import org.apache.skywalking.apm.agent.core.util.MethodUtil;
public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInterceptor { public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInterceptorV2 {
@Override @Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, 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) { if (ContextManager.getRuntimeContext().get(Constants.MYBATIS_SHELL_METHOD_NAME) == null) {
context.setContext(Constants.COLLECTED_FLAG);
String operationName = MethodUtil.generateOperationName(method); String operationName = MethodUtil.generateOperationName(method);
ContextManager.getRuntimeContext().put(Constants.MYBATIS_SHELL_METHOD_NAME, operationName); ContextManager.getRuntimeContext().put(Constants.MYBATIS_SHELL_METHOD_NAME, operationName);
} }
...@@ -38,13 +40,18 @@ public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInter ...@@ -38,13 +40,18 @@ public class MyBatisShellMethodInterceptor implements InstanceMethodsAroundInter
@Override @Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, 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; return ret;
} }
@Override @Override
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, 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; ...@@ -21,14 +21,14 @@ package org.apache.skywalking.apm.plugin.mybatis.define;
import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher; import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; 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.v2.ClassInstanceMethodsEnhancePluginDefineV2;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; 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.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.plugin.mybatis.MyBatisMethodMatch; import org.apache.skywalking.apm.plugin.mybatis.MyBatisMethodMatch;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhancePluginDefineV2 {
@Override @Override
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
...@@ -36,16 +36,16 @@ public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhan ...@@ -36,16 +36,16 @@ public class MyBatisShellMethodInstrumentation extends ClassInstanceMethodsEnhan
} }
@Override @Override
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { public InstanceMethodsInterceptV2Point[] getInstanceMethodsInterceptV2Points() {
return new InstanceMethodsInterceptPoint[] { return new InstanceMethodsInterceptV2Point[] {
new InstanceMethodsInterceptPoint() { new InstanceMethodsInterceptV2Point() {
@Override @Override
public ElementMatcher<MethodDescription> getMethodsMatcher() { public ElementMatcher<MethodDescription> getMethodsMatcher() {
return MyBatisMethodMatch.INSTANCE.getMyBatisShellMethodMatcher(); return MyBatisMethodMatch.INSTANCE.getMyBatisShellMethodMatcher();
} }
@Override @Override
public String getMethodsInterceptor() { public String getMethodsInterceptorV2() {
return "org.apache.skywalking.apm.plugin.mybatis.MyBatisShellMethodInterceptor"; return "org.apache.skywalking.apm.plugin.mybatis.MyBatisShellMethodInterceptor";
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册