package org.stagemonitor.web.monitor.spring;
import com.uber.jaeger.context.TracingUtils;
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.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.stagemonitor.core.Stagemonitor;
import org.stagemonitor.core.instrument.StagemonitorByteBuddyTransformer;
import org.stagemonitor.tracing.BusinessTransactionNamingStrategy;
import org.stagemonitor.tracing.TracingPlugin;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
public class SpringMvcRequestNameDeterminerTransformer extends StagemonitorByteBuddyTransformer {
@Override
public ElementMatcher.Junction<TypeDescription> getTypeMatcher() {
return named("org.springframework.web.servlet.DispatcherServlet");
}
@Override
protected ElementMatcher.Junction<MethodDescription> getExtraMethodElementMatcher() {
return named("getHandler").and(returns(named("org.springframework.web.servlet.HandlerExecutionChain")));
}
// method signatures mus not contain HandlerExecutionChain as this type is optional and introspecting the class
// with reflection would fail then
@Advice.OnMethodExit
public static void afterGetHandler(@Advice.Return Object handler) {
SpringMvcRequestNameDeterminerTransformer.setRequestNameByHandler(handler);
}
public static void setRequestNameByHandler(Object handler) {
if (!TracingUtils.getTraceContext().isEmpty()) {
final BusinessTransactionNamingStrategy namingStrategy = Stagemonitor.getPlugin(TracingPlugin.class)
.getBusinessTransactionNamingStrategy();
final String requestNameFromHandler = getRequestNameFromHandler(handler, namingStrategy);
if (requestNameFromHandler != null) {
TracingPlugin.getCurrentSpan().setOperationName(requestNameFromHandler);
}
}
}
private static String getRequestNameFromHandler(Object handler, BusinessTransactionNamingStrategy businessTransactionNamingStrategy) {
final HandlerExecutionChain handlerExecutionChain = (HandlerExecutionChain) handler;
if (handler != null && handlerExecutionChain.getHandler() instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handlerExecutionChain.getHandler();
return businessTransactionNamingStrategy.getBusinessTransationName(handlerMethod.getBeanType().getSimpleName(),
handlerMethod.getMethod().getName());
}
return null;
}
}