Merge pull request #348 from ascrutae/zhangxin/feature/support-rest-template
Support spring rest template and spring concurrent plugin
This commit is contained in:
commit
9f3434e834
|
|
@ -31,6 +31,8 @@ public class ComponentsDefine {
|
|||
|
||||
public static final OfficialComponent OKHTTP = new OfficialComponent(12, "OKHttp");
|
||||
|
||||
public static final OfficialComponent REST_TEMPLATE = new OfficialComponent(13, "RestTemplate");
|
||||
|
||||
private static ComponentsDefine instance = new ComponentsDefine();
|
||||
|
||||
private String[] components;
|
||||
|
|
@ -40,7 +42,7 @@ public class ComponentsDefine {
|
|||
}
|
||||
|
||||
public ComponentsDefine() {
|
||||
components = new String[13];
|
||||
components = new String[14];
|
||||
addComponent(TOMCAT);
|
||||
addComponent(HTTPCLIENT);
|
||||
addComponent(DUBBO);
|
||||
|
|
@ -53,6 +55,7 @@ public class ComponentsDefine {
|
|||
addComponent(RESIN);
|
||||
addComponent(FEIGN);
|
||||
addComponent(OKHTTP);
|
||||
addComponent(REST_TEMPLATE);
|
||||
}
|
||||
|
||||
private void addComponent(OfficialComponent component) {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,16 @@
|
|||
<artifactId>apm-feign-default-http-9.x-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<artifactId>apm-resttemplate-4.3.x-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<artifactId>apm-spring-concurrent-util-4.x-plugin</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- activation -->
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
<module>okhttp-3.x-plugin</module>
|
||||
<module>resin-3.x-plugin</module>
|
||||
<module>resin-4.x-plugin</module>
|
||||
<module>spring-plugins</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-plugins</artifactId>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<version>3.2-2017</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-spring-concurrent-util-4.x-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>concurrent-util-4.x-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>4.3.10.RELEASE</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.skywalking.apm.agent.core.context.ContextSnapshot;
|
||||
import org.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.skywalking.apm.agent.core.context.trace.SpanLayer;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.skywalking.apm.network.trace.component.ComponentsDefine;
|
||||
|
||||
public class FailureCallbackInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
Object[] cacheValues = (Object[])objInst.getSkyWalkingDynamicField();
|
||||
if (cacheValues == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
URI uri = (URI)cacheValues[0];
|
||||
AbstractSpan span = ContextManager.createLocalSpan("future/failureCallback:" + uri.getPath());
|
||||
span.errorOccurred().log((Throwable)allArguments[0]).setComponent(ComponentsDefine.REST_TEMPLATE).setLayer(SpanLayer.HTTP);
|
||||
Tags.URL.set(span, uri.getPath());
|
||||
ContextManager.continued((ContextSnapshot)cacheValues[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
ContextManager.activeSpan().errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.skywalking.apm.agent.core.context.ContextSnapshot;
|
||||
import org.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.skywalking.apm.agent.core.context.trace.SpanLayer;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.skywalking.apm.network.trace.component.ComponentsDefine;
|
||||
|
||||
public class SuccessCallbackInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
Object[] cacheValues = (Object[])objInst.getSkyWalkingDynamicField();
|
||||
if (cacheValues == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
URI uri = (URI)cacheValues[0];
|
||||
AbstractSpan span = ContextManager.createLocalSpan("future/successCallback:" + uri.getPath());
|
||||
span.setComponent(ComponentsDefine.REST_TEMPLATE).setLayer(SpanLayer.HTTP);
|
||||
Tags.URL.set(span, uri.getPath());
|
||||
ContextManager.continued((ContextSnapshot)cacheValues[2]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
ContextManager.activeSpan().errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.define;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.skywalking.apm.plugin.spring.concurrent.FailureCallbackInterceptor;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.skywalking.apm.plugin.spring.concurrent.match.FailedCallbackMatch.failedCallbackMatch;
|
||||
|
||||
/**
|
||||
* {@link FailureCallbackInstrumentation} enhance the onFailure method that class inherited
|
||||
* <code>org.springframework.util.concurrent.FailureCallback</code> by {@link FailureCallbackInterceptor}.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class FailureCallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
public static final String FAILURE_CALLBACK_INTERCEPTOR = "org.skywalking.apm.plugin.spring.concurrent.FailureCallbackInterceptor";
|
||||
public static final String FAILURE_METHOD_NAME = "onFailure";
|
||||
|
||||
@Override
|
||||
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(FAILURE_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return FAILURE_CALLBACK_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return failedCallbackMatch();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.define;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.skywalking.apm.plugin.spring.concurrent.match.ListenableFutureCallbackMatch.listenableFutureCallbackMatch;
|
||||
|
||||
/**
|
||||
* {@link ListenableFutureCallbackInstrumentation} enhance <code>onSuccess</code> method and <code>oonFailure</code>
|
||||
* that class inherited <code>org.springframework.util.concurrent.ListenableFutureCallback</code> by
|
||||
* <code>org.skywalking.apm.plugin.spring.concurrent.SuccessCallbackInterceptor</code> and
|
||||
* <code>org.skywalking.apm.plugin.spring.concurrent.FailureCallbackInterceptor</code>.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class ListenableFutureCallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
@Override
|
||||
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(SuccessCallbackInstrumentation.SUCCESS_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return SuccessCallbackInstrumentation.SUCCESS_CALLBACK_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(FailureCallbackInstrumentation.FAILURE_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return FailureCallbackInstrumentation.FAILURE_CALLBACK_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return listenableFutureCallbackMatch();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.define;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.skywalking.apm.plugin.spring.concurrent.match.SuccessCallbackMatch.successCallbackMatch;
|
||||
|
||||
/**
|
||||
* {@link SuccessCallbackInstrumentation} enhance the <code>onSuccess</code> method that class inherited
|
||||
* <code>org.springframework.util.concurrent.SuccessCallback</code> by <code>org.skywalking.apm.plugin.spring.concurrent.SuccessCallbackInterceptor</code>.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class SuccessCallbackInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
public static final String SUCCESS_CALLBACK_INTERCEPTOR =
|
||||
"org.skywalking.apm.plugin.spring.concurrent.SuccessCallbackInterceptor";
|
||||
public static final String SUCCESS_METHOD_NAME = "onSuccess";
|
||||
|
||||
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(SUCCESS_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return SUCCESS_CALLBACK_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override protected ClassMatch enhanceClass() {
|
||||
return successCallbackMatch();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.match;
|
||||
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.match.IndirectMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* {@link EitherInterfaceMatch} match the class inherited {@link #getMatchInterface() } and not inherited {@link
|
||||
* #getMutexInterface()}
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public abstract class EitherInterfaceMatch implements IndirectMatch {
|
||||
|
||||
private static final String SPRING_PACKAGE_PREFIX = "org.springframework";
|
||||
private static final String OBJECT_CLASS_NAME = "java.lang.Object";
|
||||
|
||||
protected EitherInterfaceMatch() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction buildJunction() {
|
||||
return not(nameStartsWith(SPRING_PACKAGE_PREFIX)).
|
||||
and(hasSuperType(named(getMatchInterface())))
|
||||
.and(not(hasSuperType(named(getMutexInterface()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(TypeDescription typeDescription) {
|
||||
MatchResult matchResult = new MatchResult();
|
||||
for (TypeDescription.Generic generic : typeDescription.getInterfaces()) {
|
||||
matchHierarchyClazz(generic, matchResult);
|
||||
}
|
||||
|
||||
matchHierarchyClazz(typeDescription.getSuperClass(), matchResult);
|
||||
return matchResult.result();
|
||||
}
|
||||
|
||||
public abstract String getMatchInterface();
|
||||
|
||||
public abstract String getMutexInterface();
|
||||
|
||||
private void matchHierarchyClazz(TypeDescription.Generic clazz, MatchResult matchResult) {
|
||||
if (clazz.asRawType().getTypeName().equals(getMutexInterface())) {
|
||||
matchResult.findMutexInterface = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (clazz.asRawType().getTypeName().equals(getMatchInterface())) {
|
||||
matchResult.findMatchInterface = true;
|
||||
}
|
||||
|
||||
for (TypeDescription.Generic generic : clazz.getInterfaces()) {
|
||||
matchHierarchyClazz(generic, matchResult);
|
||||
}
|
||||
|
||||
TypeDescription.Generic superClazz = clazz.getSuperClass();
|
||||
if (superClazz != null && !clazz.getTypeName().equals(OBJECT_CLASS_NAME)) {
|
||||
matchHierarchyClazz(superClazz, matchResult);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MatchResult {
|
||||
private boolean findMatchInterface = false;
|
||||
private boolean findMutexInterface = false;
|
||||
|
||||
public boolean result() {
|
||||
return findMatchInterface && !findMutexInterface;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.match;
|
||||
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
/**
|
||||
* {@link FailedCallbackMatch} match the class that inherited <code>org.springframework.util.concurrent.FailureCallback</code>
|
||||
* and not inherited <code>org.springframework.util.concurrent.SuccessCallback</code>
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class FailedCallbackMatch extends EitherInterfaceMatch {
|
||||
|
||||
private static final String MATCH_INTERFACE = "org.springframework.util.concurrent.FailureCallback";
|
||||
private static final String MUTEX_INTERFACE = "org.springframework.util.concurrent.SuccessCallback";
|
||||
|
||||
private FailedCallbackMatch() {
|
||||
|
||||
}
|
||||
|
||||
@Override public String getMatchInterface() {
|
||||
return MATCH_INTERFACE;
|
||||
}
|
||||
|
||||
@Override public String getMutexInterface() {
|
||||
return MUTEX_INTERFACE;
|
||||
}
|
||||
|
||||
public static ClassMatch failedCallbackMatch() {
|
||||
return new FailedCallbackMatch();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.match;
|
||||
|
||||
import net.bytebuddy.description.type.TypeDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.skywalking.apm.agent.core.plugin.match.IndirectMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.not;
|
||||
|
||||
/**
|
||||
* {@link ListenableFutureCallbackMatch} match the class that inherited <code>org.springframework.util.concurrent.ListenableFutureCallback</code>.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class ListenableFutureCallbackMatch implements IndirectMatch {
|
||||
|
||||
private static final String LISTENABLE_FUTURE_CALLBACK_CLASS_NAME = "org.springframework.util.concurrent.ListenableFutureCallback";
|
||||
|
||||
private ListenableFutureCallbackMatch() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementMatcher.Junction buildJunction() {
|
||||
return not(nameStartsWith("org.springframework")).
|
||||
and(hasSuperType(named(LISTENABLE_FUTURE_CALLBACK_CLASS_NAME)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMatch(TypeDescription typeDescription) {
|
||||
boolean isMatch = false;
|
||||
for (TypeDescription.Generic generic : typeDescription.getInterfaces()) {
|
||||
isMatch = isMatch || matchExactClass(generic);
|
||||
}
|
||||
|
||||
return isMatch || matchExactClass(typeDescription.getSuperClass());
|
||||
}
|
||||
|
||||
private boolean matchExactClass(TypeDescription.Generic clazz) {
|
||||
if (clazz.asRawType().getTypeName().equals(LISTENABLE_FUTURE_CALLBACK_CLASS_NAME)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isMatch = false;
|
||||
for (TypeDescription.Generic generic : clazz.getInterfaces()) {
|
||||
isMatch = isMatch || matchExactClass(generic);
|
||||
}
|
||||
|
||||
if (!isMatch) {
|
||||
TypeDescription.Generic superClazz = clazz.getSuperClass();
|
||||
if (superClazz != null && !clazz.getTypeName().equals("java.lang.Object")) {
|
||||
isMatch = isMatch || matchExactClass(superClazz);
|
||||
}
|
||||
}
|
||||
|
||||
return isMatch;
|
||||
}
|
||||
|
||||
public static ClassMatch listenableFutureCallbackMatch() {
|
||||
return new ListenableFutureCallbackMatch();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.skywalking.apm.plugin.spring.concurrent.match;
|
||||
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
/**
|
||||
* {@link SuccessCallbackMatch} match the class that inherited <code>org.springframework.util.concurrent.SuccessCallback</code>
|
||||
* and not inherited <code>org.springframework.util.concurrent.FailureCallback</code>
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class SuccessCallbackMatch extends EitherInterfaceMatch {
|
||||
|
||||
private static final String MATCH_INTERFACE = "org.springframework.util.concurrent.SuccessCallback";
|
||||
private static final String MUTEX_INTERFACE = "org.springframework.util.concurrent.FailureCallback";
|
||||
|
||||
private SuccessCallbackMatch() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMatchInterface() {
|
||||
return MATCH_INTERFACE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMutexInterface() {
|
||||
return MUTEX_INTERFACE;
|
||||
}
|
||||
|
||||
public static ClassMatch successCallbackMatch() {
|
||||
return new SuccessCallbackMatch();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
spring-concurrent-util-4.x=org.skywalking.apm.plugin.spring.concurrent.define.FailureCallbackInstrumentation
|
||||
spring-concurrent-util-4.x=org.skywalking.apm.plugin.spring.concurrent.define.SuccessCallbackInstrumentation
|
||||
spring-concurrent-util-4.x=org.skywalking.apm.plugin.spring.concurrent.define.ListenableFutureCallbackInstrumentation
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<artifactId>apm-sdk-plugin</artifactId>
|
||||
<version>3.2-2017</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>spring-plugins</artifactId>
|
||||
<modules>
|
||||
<module>concurrent-util-4.x-plugin</module>
|
||||
<module>resttemplate-4.x-plugin</module>
|
||||
</modules>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>apm-sdk-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-plugins</artifactId>
|
||||
<groupId>org.skywalking</groupId>
|
||||
<version>3.2-2017</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>apm-resttemplate-4.3.x-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>resttemplate-4.3.x-plugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>4.3.10.RELEASE</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.async;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
|
||||
public class FutureGetInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
Object[] cacheValues = (Object[])objInst.getSkyWalkingDynamicField();
|
||||
ContextManager.createLocalSpan("future/get:" + ((URI)cacheValues[0]).getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
AbstractSpan activeSpan = ContextManager.activeSpan();
|
||||
activeSpan.errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.async;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
|
||||
public class ResponseCallBackInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
EnhancedInstance successCallBak = (EnhancedInstance)allArguments[0];
|
||||
successCallBak.setSkyWalkingDynamicField(objInst.getSkyWalkingDynamicField());
|
||||
|
||||
if (allArguments.length == 2) {
|
||||
EnhancedInstance failedCallBack = (EnhancedInstance)allArguments[1];
|
||||
failedCallBack.setSkyWalkingDynamicField(objInst.getSkyWalkingDynamicField());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.async;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
import org.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.skywalking.apm.agent.core.context.trace.SpanLayer;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.skywalking.apm.network.trace.component.ComponentsDefine;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
final URI requestURL = (URI)allArguments[0];
|
||||
final HttpMethod httpMethod = (HttpMethod)allArguments[1];
|
||||
final ContextCarrier contextCarrier = new ContextCarrier();
|
||||
String remotePeer = requestURL.getHost() + ":" + requestURL.getPort();
|
||||
AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer);
|
||||
|
||||
span.setComponent(ComponentsDefine.REST_TEMPLATE);
|
||||
Tags.URL.set(span, requestURL.getScheme() + "://" + requestURL.getHost() + ":" + requestURL.getPort() + requestURL.getPath());
|
||||
Tags.HTTP.METHOD.set(span, httpMethod.toString());
|
||||
SpanLayer.asHttp(span);
|
||||
Object[] cacheValues = new Object[3];
|
||||
cacheValues[0] = requestURL;
|
||||
cacheValues[1] = contextCarrier.serialize();
|
||||
objInst.setSkyWalkingDynamicField(cacheValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
Object[] cacheValues = (Object[])objInst.getSkyWalkingDynamicField();
|
||||
cacheValues[2] = ContextManager.capture();
|
||||
if (ret != null) {
|
||||
((EnhancedInstance)ret).setSkyWalkingDynamicField(cacheValues);
|
||||
}
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
ContextManager.activeSpan().errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.async.define;
|
||||
|
||||
import java.net.URI;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.context.ContextSnapshot;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
import org.skywalking.apm.plugin.spring.resttemplate.async.ResponseCallBackInterceptor;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
/**
|
||||
* {@link ResponseExtractorFutureInstrumentation} enhance the <code>addCallback</code> method and <code>get</code> method of
|
||||
* <code>org.springframework.web.client.AsyncRestTemplate$ResponseExtractorFuture</code> by
|
||||
* <code>org.skywalking.apm.plugin.spring.resttemplate.async.ResponseCallBackInterceptor</code> and
|
||||
* <code>org.skywalking.apm.plugin.spring.resttemplate.async.FutureGetInterceptor</code>.
|
||||
*
|
||||
* {@link ResponseCallBackInterceptor} set the {@link URI} and {@link ContextSnapshot} to inherited
|
||||
* <code>org.springframework.util.concurrent.SuccessCallback</code> and <code>org.springframework.util.concurrent.FailureCallback</code>
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class ResponseExtractorFutureInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String ADD_CALLBACK_METHOD_NAME = "addCallback";
|
||||
private static final String ADD_CALLBACK_INTERCEPTOR = "org.skywalking.apm.plugin.spring.resttemplate.async.ResponseCallBackInterceptor";
|
||||
private static final String ENHANCE_CLASS = "org.springframework.web.client.AsyncRestTemplate$ResponseExtractorFuture";
|
||||
private static final String GET_METHOD_INTERCEPTOR = "org.skywalking.apm.plugin.spring.resttemplate.async.FutureGetInterceptor";
|
||||
private static final String GET_METHOD_NAME = "get";
|
||||
|
||||
@Override
|
||||
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(ADD_CALLBACK_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return ADD_CALLBACK_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(GET_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return GET_METHOD_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName(ENHANCE_CLASS);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.async.define;
|
||||
|
||||
import java.net.URI;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.context.ContextSnapshot;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
/**
|
||||
* {@link RestTemplateInstrumentation} enhance the <code>doExecute</code> method and <code>createAsyncRequest</code>
|
||||
* method of <code>org.springframework.web.client.AsyncRestTemplate</code> by <code>org.skywalking.apm.plugin.spring.resttemplate.async.RestExecuteInterceptor</code>
|
||||
* and <code>org.springframework.http.client.RestRequestInterceptor</code>.
|
||||
*
|
||||
* <code>org.springframework.http.client.RestRequestInterceptor</code> set {@link URI} and {@link ContextSnapshot} to
|
||||
* <code>org.springframework.web.client.AsyncRestTemplate$ResponseExtractorFuture</code> for propagate trace context
|
||||
* after execute <code>doExecute</code> .
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class RestTemplateInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String ENHANCE_CLASS = "org.springframework.web.client.AsyncRestTemplate";
|
||||
private static final String DO_EXECUTE_METHOD_NAME = "doExecute";
|
||||
private static final String DO_EXECUTE_INTERCEPTOR = "org.skywalking.apm.plugin.spring.resttemplate.async.RestExecuteInterceptor";
|
||||
private static final String CREATE_REQUEST_METHOD_NAME = "createAsyncRequest";
|
||||
private static final String CREATE_REQUEST_INTERCEPTOR = "org.springframework.http.client.RestRequestInterceptor";
|
||||
|
||||
@Override
|
||||
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(DO_EXECUTE_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return DO_EXECUTE_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(CREATE_REQUEST_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return CREATE_REQUEST_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName(ENHANCE_CLASS);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.sync;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import org.skywalking.apm.agent.core.context.ContextCarrier;
|
||||
import org.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.skywalking.apm.agent.core.context.trace.SpanLayer;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.skywalking.apm.network.trace.component.ComponentsDefine;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
public class RestExecuteInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
final URI requestURL = (URI)allArguments[0];
|
||||
final HttpMethod httpMethod = (HttpMethod)allArguments[1];
|
||||
final ContextCarrier contextCarrier = new ContextCarrier();
|
||||
String remotePeer = requestURL.getHost() + ":" + requestURL.getPort();
|
||||
AbstractSpan span = ContextManager.createExitSpan(requestURL.getPath(), contextCarrier, remotePeer);
|
||||
|
||||
span.setComponent(ComponentsDefine.REST_TEMPLATE);
|
||||
Tags.URL.set(span, requestURL.getScheme() + "://" + requestURL.getHost() + ":" + requestURL.getPort() + requestURL.getPath());
|
||||
Tags.HTTP.METHOD.set(span, httpMethod.toString());
|
||||
SpanLayer.asHttp(span);
|
||||
|
||||
objInst.setSkyWalkingDynamicField(contextCarrier.serialize());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
ContextManager.stopSpan();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
ContextManager.activeSpan().errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.sync;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.skywalking.apm.agent.core.conf.Config;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.springframework.http.client.AbstractClientHttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
|
||||
public class RestRequestInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
ClientHttpRequest clientHttpRequest = (ClientHttpRequest)ret;
|
||||
if (clientHttpRequest instanceof AbstractClientHttpRequest) {
|
||||
AbstractClientHttpRequest httpRequest = (AbstractClientHttpRequest)clientHttpRequest;
|
||||
httpRequest.getHeaders().set(Config.Plugin.Propagation.HEADER_NAME, String.valueOf(objInst.getSkyWalkingDynamicField()));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.sync;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.skywalking.apm.agent.core.context.ContextManager;
|
||||
import org.skywalking.apm.agent.core.context.tag.Tags;
|
||||
import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
public class RestResponseInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
|
||||
ClientHttpResponse response = (ClientHttpResponse)allArguments[2];
|
||||
int statusCode = response.getStatusCode().value();
|
||||
AbstractSpan span = ContextManager.activeSpan();
|
||||
if (statusCode >= 400) {
|
||||
span.errorOccurred();
|
||||
Tags.STATUS_CODE.set(span, Integer.toString(statusCode));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
ContextManager.activeSpan().errorOccurred().log(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package org.skywalking.apm.plugin.spring.resttemplate.sync.define;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
|
||||
import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
/**
|
||||
* {@link RestTemplateInstrumentation} enhance the <code>doExecute</code> method,<code>handleResponse</code> method and
|
||||
* <code>handleResponse</code> method of <code>org.springframework.web.client.RestTemplate</code> by
|
||||
* <code>org.skywalking.apm.plugin.spring.resttemplate.sync.RestExecuteInterceptor</code>,
|
||||
* <code>org.skywalking.apm.plugin.spring.resttemplate.sync.RestResponseInterceptor</code> and
|
||||
* <code>org.skywalking.apm.plugin.spring.resttemplate.sync.RestRequestInterceptor</code>.
|
||||
*
|
||||
* <code>org.skywalking.apm.plugin.spring.resttemplate.sync.RestResponseInterceptor</code> set context to header for
|
||||
* propagate trace context after execute <code>createRequest</code>.
|
||||
*
|
||||
* @author zhangxin
|
||||
*/
|
||||
public class RestTemplateInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
|
||||
private static final String ENHANCE_CLASS = "org.springframework.web.client.RestTemplate";
|
||||
private static final String DO_EXECUTE_METHOD_NAME = "doExecute";
|
||||
private static final String DO_EXECUTE_INTERCEPTOR = "org.skywalking.apm.plugin.spring.resttemplate.sync.RestExecuteInterceptor";
|
||||
private static final String HANDLE_REQUEST_METHOD_NAME = "handleResponse";
|
||||
private static final String HAND_REQUEST_INTERCEPTOR = "org.skywalking.apm.plugin.spring.resttemplate.sync.RestResponseInterceptor";
|
||||
private static final String CREATE_REQUEST_METHOD_NAME = "createRequest";
|
||||
private static final String CREATE_REQUEST_INTERCEPTOR = "org.skywalking.apm.plugin.spring.resttemplate.sync.RestRequestInterceptor";
|
||||
|
||||
@Override
|
||||
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(DO_EXECUTE_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return DO_EXECUTE_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(HANDLE_REQUEST_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return HAND_REQUEST_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(CREATE_REQUEST_METHOD_NAME);
|
||||
}
|
||||
|
||||
@Override public String getMethodsInterceptor() {
|
||||
return CREATE_REQUEST_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName(ENHANCE_CLASS);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package org.springframework.http.client;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import org.skywalking.apm.agent.core.conf.Config;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
|
||||
public class RestRequestInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
MethodInterceptResult result) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
|
||||
Object ret) throws Throwable {
|
||||
AbstractAsyncClientHttpRequest clientHttpRequest = (AbstractAsyncClientHttpRequest)ret;
|
||||
if (ret != null) {
|
||||
clientHttpRequest.getHeaders().set(Config.Plugin.Propagation.HEADER_NAME, String.valueOf(((Object[])objInst.getSkyWalkingDynamicField())[1]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
|
||||
Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
spring-resttemplate-4.x=org.skywalking.apm.plugin.spring.resttemplate.async.define.RestTemplateInstrumentation
|
||||
spring-resttemplate-4.x=org.skywalking.apm.plugin.spring.resttemplate.async.define.ResponseExtractorFutureInstrumentation
|
||||
spring-resttemplate-4.x=org.skywalking.apm.plugin.spring.resttemplate.sync.define.RestTemplateInstrumentation
|
||||
Loading…
Reference in New Issue