com.catchpoint.trace.instrument.integrations.spring.web.advice.SpringDispatcherServletAdviceInstrumenter Maven / Gradle / Ivy
package com.catchpoint.trace.instrument.integrations.spring.web.advice;
import com.catchpoint.trace.instrument.core.advice.AbstractAdviceInstrumenter;
import com.catchpoint.trace.instrument.core.advice.AdviceInstrumenter;
import com.catchpoint.trace.core.scope.CatchpointScope;
import com.catchpoint.trace.core.CatchpointTracer;
import com.catchpoint.trace.core.TraceSupport;
import com.catchpoint.trace.instrument.core.advice.matcher.ClassLoaderMatchers;
import com.catchpoint.trace.instrument.integrations.spring.web.SpringWebHelper;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static net.bytebuddy.matcher.ElementMatchers.*;
/**
*
* {@link AdviceInstrumenter} implementation which instruments
* Spring Web versions 3.x, 4.x and 5.x to monitor Spring web requests/responses.
*
*
* Enabled by default and disabled by catchpoint.trace.instrument.integrations.spring.disable
* system property.
*
*
* @author serkan
*/
public class SpringDispatcherServletAdviceInstrumenter extends AbstractAdviceInstrumenter {
@Override
public boolean isEnabled() {
return SpringWebHelper.isEnabled();
}
@Override
protected ElementMatcher super TypeDescription> typeMatcher() {
return named("org.springframework.web.servlet.DispatcherServlet");
}
@Override
protected Collection helperClassNames() {
return Arrays.asList(
"com.catchpoint.trace.instrument.integrations.spring.web.advice.SpringWebAdviceHelper",
"com.catchpoint.trace.instrument.integrations.spring.web.advice.PatternMatchAwareHttpServletRequestWrapper");
}
@Override
protected ElementMatcher classLoaderMatcher() {
return ClassLoaderMatchers.hasClassesNamed(new String[]{
"javax.servlet.http.HttpServletRequest",
"javax.servlet.http.HttpServletResponse",
"org.springframework.web.servlet.DispatcherServlet"});
}
@Override
protected Map extends ElementMatcher super MethodDescription>, String> transformers() {
Map, String> transformers = new HashMap();
transformers.put(
isMethod().
and(isProtected()).
and(named("doDispatch")).
and(takesArgument(0, named("javax.servlet.http.HttpServletRequest"))).
and(takesArgument(1, named("javax.servlet.http.HttpServletResponse"))),
SpringDispatcherServletAdviceInstrumenter.class.getName() + "$DispatcherServletDoDispatchAdvice");
return transformers;
}
public static class DispatcherServletDoDispatchAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static CatchpointScope enter(@Advice.This DispatcherServlet dispatcherServlet,
@Advice.Argument(value = 0, readOnly = false) HttpServletRequest request,
@Advice.Argument(value = 1, readOnly = false) HttpServletResponse response) {
CatchpointTracer tracer = TraceSupport.getTracer();
CatchpointScope scope = SpringWebAdviceHelper.createAndStartSpan(tracer, dispatcherServlet, request, response);
if (scope == null) {
return null;
}
if (!(request instanceof PatternMatchAwareHttpServletRequestWrapper)) {
request = new PatternMatchAwareHttpServletRequestWrapper(request, response, scope);
}
request = SpringWebAdviceHelper.checkAndWrapRequest(request, scope);
response = SpringWebAdviceHelper.checkAndWrapResponse(response, scope);
return scope;
}
@Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class)
public static void exit(@Advice.Enter CatchpointScope scope,
@Advice.Thrown Throwable error) {
if (scope == null) {
return;
}
SpringWebAdviceHelper.finishScope(scope, error);
}
}
}