diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/MethodUtil.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/MethodUtil.java index 80260446e1b15feb59292ae1fbd27a169ff081d0..cec696e471af0bea10e06829291ab8f2e50442a2 100644 --- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/MethodUtil.java +++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/MethodUtil.java @@ -30,6 +30,7 @@ import java.lang.reflect.Method; public class MethodUtil { + public static String generateOperationName(Method method) { StringBuilder operationName = new StringBuilder(method.getDeclaringClass().getName() + "." + method.getName() + "("); Class[] parameterTypes = method.getParameterTypes(); @@ -42,4 +43,44 @@ public class MethodUtil { operationName.append(")"); return operationName.toString(); } + + /** + * This is a low-performance method, recommand to use this when have to, make sure it is only executed once and the result is being cached. + */ + public static boolean isMethodExist(ClassLoader classLoader, String className, String methodName, String... parameterTypes) { + try { + Class clazz = Class.forName(className, true, classLoader); + if (parameterTypes == null || parameterTypes.length == 0) { + clazz.getDeclaredMethod(methodName); + return true; + } else { + Method[] declaredMethods = clazz.getDeclaredMethods(); + for (Method declaredMethod : declaredMethods) { + if (declaredMethod.getName().equals(methodName) && isParameterTypesEquals(declaredMethod.getParameterTypes(), parameterTypes)) { + return true; + } + } + } + } catch (Exception e) { + //ignore + } + return false; + } + + + private static boolean isParameterTypesEquals(Class[] parameterTypeClazz, String[] parameterTypeString) { + if (parameterTypeClazz == null) { + return false; + } + if (parameterTypeClazz.length != parameterTypeString.length) { + return false; + } + for (int i = 0; i < parameterTypeClazz.length; i++) { + if (!parameterTypeClazz[i].getName().equals(parameterTypeString[i])) { + return false; + } + } + return true; + + } } diff --git a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java index 6700cab1dedc893b0508f00e688ef9354ed69c0c..40e62ca4cbd138d364b862e163fec67f1362e24f 100644 --- a/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/jetty-plugin/jetty-server-9.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jetty/v9/server/HandleInterceptor.java @@ -31,10 +31,20 @@ import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; 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.util.MethodUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; import org.eclipse.jetty.server.HttpChannel; public class HandleInterceptor implements InstanceMethodsAroundInterceptor { + + private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; + private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; + private static final String GET_STATUS_METHOD = "getStatus"; + + static { + IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(HandleInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); + } + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { @@ -62,7 +72,7 @@ public class HandleInterceptor implements InstanceMethodsAroundInterceptor { HttpChannel httpChannel = (HttpChannel)objInst; HttpServletResponse servletResponse = httpChannel.getResponse(); AbstractSpan span = ContextManager.activeSpan(); - if (servletResponse.getStatus() >= 400) { + if (IS_SERVLET_GET_STATUS_METHOD_EXIST && servletResponse.getStatus() >= 400) { span.errorOccurred(); Tags.STATUS_CODE.set(span, Integer.toString(servletResponse.getStatus())); } diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java index 55306493a0cc2f03a9a020ebacef877f5f0afe44..85734df5bd061e3ff87ac216362956c83be3f417 100644 --- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-commons/src/main/java/org/apache/skywalking/apm/plugin/spring/mvc/commons/interceptor/AbstractMethodInterceptor.java @@ -46,6 +46,15 @@ import static org.apache.skywalking.apm.plugin.spring.mvc.commons.Constants.RESP * the abstract method interceptor */ public abstract class AbstractMethodInterceptor implements InstanceMethodsAroundInterceptor { + + private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; + private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; + private static final String GET_STATUS_METHOD = "getStatus"; + + static { + IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(AbstractMethodInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); + } + public abstract String getRequestURL(Method method); public abstract String getAcceptedMethodTypes(Method method); @@ -151,7 +160,7 @@ public abstract class AbstractMethodInterceptor implements InstanceMethodsAround throw new ServletResponseNotFoundException(); } - if (response.getStatus() >= 400) { + if (IS_SERVLET_GET_STATUS_METHOD_EXIST && response.getStatus() >= 400) { span.errorOccurred(); Tags.STATUS_CODE.set(span, Integer.toString(response.getStatus())); } diff --git a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java index 649e5c71268d111d226c226500ed4881087d16c7..bb609a92e0cc70b0ba31167603edd48b72f29910 100644 --- a/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/tomcat78x/TomcatInvokeInterceptor.java @@ -32,6 +32,7 @@ import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment; 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.util.MethodUtil; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; /** @@ -41,6 +42,14 @@ import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; */ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor { + private static boolean IS_SERVLET_GET_STATUS_METHOD_EXIST; + private static final String SERVLET_RESPONSE_CLASS = "javax.servlet.http.HttpServletResponse"; + private static final String GET_STATUS_METHOD = "getStatus"; + + static { + IS_SERVLET_GET_STATUS_METHOD_EXIST = MethodUtil.isMethodExist(TomcatInvokeInterceptor.class.getClassLoader(), SERVLET_RESPONSE_CLASS, GET_STATUS_METHOD); + } + /** * * The {@link TraceSegment#refs} of current trace segment will reference to the * trace segment id of the previous level if the serialized context is not null. @@ -76,7 +85,7 @@ public class TomcatInvokeInterceptor implements InstanceMethodsAroundInterceptor HttpServletResponse response = (HttpServletResponse)allArguments[1]; AbstractSpan span = ContextManager.activeSpan(); - if (response.getStatus() >= 400) { + if (IS_SERVLET_GET_STATUS_METHOD_EXIST && response.getStatus() >= 400) { span.errorOccurred(); Tags.STATUS_CODE.set(span, Integer.toString(response.getStatus())); }