Commit 137b142a authored by li.can's avatar li.can Committed by 吴晟
Browse files

Support servlet 2.5 for Jetty,Tomcat,SpringMvc (#3120)

* servlet 2.5

* method exist

* update MethodUtil

* Update MethodUtil.java

Add a comment to the new core util method. @candyleer I am concerning this method will be used widely even unnecessary.
parent f4ca4c8a
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -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;

    }
}
+11 −1
Original line number Diff line number Diff line
@@ -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()));
        }
+10 −1
Original line number Diff line number Diff line
@@ -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()));
                }
+10 −1
Original line number Diff line number Diff line
@@ -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()));
        }