提交 903a15a3 编写于 作者: wu-sheng's avatar wu-sheng 提交者: GitHub

Merge branch 'master' into feature/351

...@@ -31,6 +31,10 @@ public class ComponentsDefine { ...@@ -31,6 +31,10 @@ public class ComponentsDefine {
public static final OfficialComponent OKHTTP = new OfficialComponent(12, "OKHttp"); public static final OfficialComponent OKHTTP = new OfficialComponent(12, "OKHttp");
public static final OfficialComponent SPRING_REST_TEMPLATE = new OfficialComponent(13, "SpringRestTemplate");
public static final OfficialComponent SPRING_MVC_ANNOTATION = new OfficialComponent(14, "SpringMVCAnnotation");
private static ComponentsDefine instance = new ComponentsDefine(); private static ComponentsDefine instance = new ComponentsDefine();
private String[] components; private String[] components;
...@@ -40,7 +44,7 @@ public class ComponentsDefine { ...@@ -40,7 +44,7 @@ public class ComponentsDefine {
} }
public ComponentsDefine() { public ComponentsDefine() {
components = new String[13]; components = new String[15];
addComponent(TOMCAT); addComponent(TOMCAT);
addComponent(HTTPCLIENT); addComponent(HTTPCLIENT);
addComponent(DUBBO); addComponent(DUBBO);
...@@ -53,6 +57,8 @@ public class ComponentsDefine { ...@@ -53,6 +57,8 @@ public class ComponentsDefine {
addComponent(RESIN); addComponent(RESIN);
addComponent(FEIGN); addComponent(FEIGN);
addComponent(OKHTTP); addComponent(OKHTTP);
addComponent(SPRING_REST_TEMPLATE);
addComponent(SPRING_MVC_ANNOTATION);
} }
private void addComponent(OfficialComponent component) { private void addComponent(OfficialComponent component) {
......
...@@ -290,19 +290,19 @@ public class TracingContext implements AbstractTracerContext { ...@@ -290,19 +290,19 @@ public class TracingContext implements AbstractTracerContext {
.find(remotePeer).doInCondition( .find(remotePeer).doInCondition(
new PossibleFound.FoundAndObtain() { new PossibleFound.FoundAndObtain() {
@Override @Override
public Object doProcess(final int applicationId) { public Object doProcess(final int peerId) {
return DictionaryManager.findOperationNameCodeSection() return DictionaryManager.findOperationNameCodeSection()
.findOrPrepare4Register(applicationId, operationName) .findOnly(segment.getApplicationId(), operationName)
.doInCondition( .doInCondition(
new PossibleFound.FoundAndObtain() { new PossibleFound.FoundAndObtain() {
@Override @Override
public Object doProcess(int operationId) { public Object doProcess(int operationId) {
return new ExitSpan(spanIdGenerator++, parentSpanId, operationId, applicationId); return new ExitSpan(spanIdGenerator++, parentSpanId, operationId, peerId);
} }
}, new PossibleFound.NotFoundAndObtain() { }, new PossibleFound.NotFoundAndObtain() {
@Override @Override
public Object doProcess() { public Object doProcess() {
return new ExitSpan(spanIdGenerator++, parentSpanId, operationName, remotePeer); return new ExitSpan(spanIdGenerator++, parentSpanId, operationName, peerId);
} }
}); });
} }
...@@ -310,7 +310,20 @@ public class TracingContext implements AbstractTracerContext { ...@@ -310,7 +310,20 @@ public class TracingContext implements AbstractTracerContext {
new PossibleFound.NotFoundAndObtain() { new PossibleFound.NotFoundAndObtain() {
@Override @Override
public Object doProcess() { public Object doProcess() {
return new ExitSpan(spanIdGenerator++, parentSpanId, operationName, remotePeer); return DictionaryManager.findOperationNameCodeSection()
.findOnly(segment.getApplicationId(), operationName)
.doInCondition(
new PossibleFound.FoundAndObtain() {
@Override
public Object doProcess(int operationId) {
return new ExitSpan(spanIdGenerator++, parentSpanId, operationId, remotePeer);
}
}, new PossibleFound.NotFoundAndObtain() {
@Override
public Object doProcess() {
return new ExitSpan(spanIdGenerator++, parentSpanId, operationName, remotePeer);
}
});
} }
}); });
push(exitSpan); push(exitSpan);
......
package org.skywalking.apm.agent.core.context.trace; package org.skywalking.apm.agent.core.context.trace;
import org.skywalking.apm.agent.core.dictionary.DictionaryManager;
import org.skywalking.apm.agent.core.dictionary.DictionaryUtil; import org.skywalking.apm.agent.core.dictionary.DictionaryUtil;
import org.skywalking.apm.agent.core.dictionary.PossibleFound;
import org.skywalking.apm.network.trace.component.Component; import org.skywalking.apm.network.trace.component.Component;
/** /**
...@@ -18,19 +16,16 @@ import org.skywalking.apm.network.trace.component.Component; ...@@ -18,19 +16,16 @@ import org.skywalking.apm.network.trace.component.Component;
* *
* @author wusheng * @author wusheng
*/ */
public class EntrySpan extends AbstractTracingSpan { public class EntrySpan extends StackBasedTracingSpan {
private int stackDepth;
private int currentMaxDepth; private int currentMaxDepth;
public EntrySpan(int spanId, int parentSpanId, String operationName) { public EntrySpan(int spanId, int parentSpanId, String operationName) {
super(spanId, parentSpanId, operationName); super(spanId, parentSpanId, operationName);
this.stackDepth = 0;
this.currentMaxDepth = 0; this.currentMaxDepth = 0;
} }
public EntrySpan(int spanId, int parentSpanId, int operationId) { public EntrySpan(int spanId, int parentSpanId, int operationId) {
super(spanId, parentSpanId, operationId); super(spanId, parentSpanId, operationId);
this.stackDepth = 0;
this.currentMaxDepth = 0; this.currentMaxDepth = 0;
} }
...@@ -81,31 +76,6 @@ public class EntrySpan extends AbstractTracingSpan { ...@@ -81,31 +76,6 @@ public class EntrySpan extends AbstractTracingSpan {
} }
} }
@Override
public boolean finish(TraceSegment owner) {
if (--stackDepth == 0) {
if (this.operationId == DictionaryUtil.nullValue()) {
this.operationId = (Integer)DictionaryManager.findOperationNameCodeSection()
.findOrPrepare4Register(owner.getApplicationId(), operationName)
.doInCondition(
new PossibleFound.FoundAndObtain() {
@Override public Object doProcess(int value) {
return value;
}
},
new PossibleFound.NotFoundAndObtain() {
@Override public Object doProcess() {
return DictionaryUtil.nullValue();
}
}
);
}
return super.finish(owner);
} else {
return false;
}
}
@Override @Override
public AbstractTracingSpan setOperationName(String operationName) { public AbstractTracingSpan setOperationName(String operationName) {
if (stackDepth == currentMaxDepth) { if (stackDepth == currentMaxDepth) {
......
...@@ -17,32 +17,34 @@ import org.skywalking.apm.network.trace.component.Component; ...@@ -17,32 +17,34 @@ import org.skywalking.apm.network.trace.component.Component;
* *
* @author wusheng * @author wusheng
*/ */
public class ExitSpan extends AbstractTracingSpan { public class ExitSpan extends StackBasedTracingSpan {
private int stackDepth;
private String peer; private String peer;
private int peerId; private int peerId;
public ExitSpan(int spanId, int parentSpanId, String operationName, String peer) { public ExitSpan(int spanId, int parentSpanId, String operationName, String peer) {
super(spanId, parentSpanId, operationName); super(spanId, parentSpanId, operationName);
this.stackDepth = 0;
this.peer = peer; this.peer = peer;
this.peerId = DictionaryUtil.nullValue(); this.peerId = DictionaryUtil.nullValue();
} }
public ExitSpan(int spanId, int parentSpanId, int operationId, int peerId) { public ExitSpan(int spanId, int parentSpanId, int operationId, int peerId) {
super(spanId, parentSpanId, operationId); super(spanId, parentSpanId, operationId);
this.stackDepth = 0;
this.peer = null; this.peer = null;
this.peerId = peerId; this.peerId = peerId;
} }
public ExitSpan(int spanId, int parentSpanId, int operationId, String peer) { public ExitSpan(int spanId, int parentSpanId, int operationId, String peer) {
super(spanId, parentSpanId, operationId); super(spanId, parentSpanId, operationId);
this.stackDepth = 0;
this.peer = peer; this.peer = peer;
this.peerId = DictionaryUtil.nullValue(); this.peerId = DictionaryUtil.nullValue();
} }
public ExitSpan(int spanId, int parentSpanId, String operationName, int peerId) {
super(spanId, parentSpanId, operationName);
this.peer = null;
this.peerId = peerId;
}
/** /**
* Set the {@link #startTime}, when the first start, which means the first service provided. * Set the {@link #startTime}, when the first start, which means the first service provided.
*/ */
...@@ -62,15 +64,6 @@ public class ExitSpan extends AbstractTracingSpan { ...@@ -62,15 +64,6 @@ public class ExitSpan extends AbstractTracingSpan {
return this; return this;
} }
@Override
public boolean finish(TraceSegment owner) {
if (--stackDepth == 0) {
return super.finish(owner);
} else {
return false;
}
}
@Override @Override
public AbstractTracingSpan setLayer(SpanLayer layer) { public AbstractTracingSpan setLayer(SpanLayer layer) {
if (stackDepth == 1) { if (stackDepth == 1) {
......
package org.skywalking.apm.agent.core.context.trace;
import org.skywalking.apm.agent.core.dictionary.DictionaryManager;
import org.skywalking.apm.agent.core.dictionary.DictionaryUtil;
import org.skywalking.apm.agent.core.dictionary.PossibleFound;
/**
* The <code>StackBasedTracingSpan</code> represents a span with an inside stack construction.
*
* This kind of span can start and finish multi times in a stack-like invoke line.
*
* @author wusheng
*/
public abstract class StackBasedTracingSpan extends AbstractTracingSpan {
protected int stackDepth;
protected StackBasedTracingSpan(int spanId, int parentSpanId, String operationName) {
super(spanId, parentSpanId, operationName);
this.stackDepth = 0;
}
protected StackBasedTracingSpan(int spanId, int parentSpanId, int operationId) {
super(spanId, parentSpanId, operationId);
this.stackDepth = 0;
}
@Override
public boolean finish(TraceSegment owner) {
if (--stackDepth == 0) {
if (this.operationId == DictionaryUtil.nullValue()) {
this.operationId = (Integer)DictionaryManager.findOperationNameCodeSection()
.findOrPrepare4Register(owner.getApplicationId(), operationName)
.doInCondition(
new PossibleFound.FoundAndObtain() {
@Override public Object doProcess(int value) {
return value;
}
},
new PossibleFound.NotFoundAndObtain() {
@Override public Object doProcess() {
return DictionaryUtil.nullValue();
}
}
);
}
return super.finish(owner);
} else {
return false;
}
}
}
package org.skywalking.apm.agent.core.plugin.match; package org.skywalking.apm.agent.core.plugin.match;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import net.bytebuddy.description.annotation.AnnotationDescription; import net.bytebuddy.description.annotation.AnnotationDescription;
...@@ -43,7 +44,7 @@ public class ClassAnnotationMatch implements IndirectMatch { ...@@ -43,7 +44,7 @@ public class ClassAnnotationMatch implements IndirectMatch {
@Override @Override
public boolean isMatch(TypeDescription typeDescription) { public boolean isMatch(TypeDescription typeDescription) {
List<String> annotationList = Arrays.asList(annotations); List<String> annotationList = new ArrayList<String>(Arrays.asList(annotations));
AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations(); AnnotationList declaredAnnotations = typeDescription.getDeclaredAnnotations();
for (AnnotationDescription annotation : declaredAnnotations) { for (AnnotationDescription annotation : declaredAnnotations) {
annotationList.remove(annotation.getAnnotationType().getActualName()); annotationList.remove(annotation.getAnnotationType().getActualName());
......
...@@ -8,7 +8,7 @@ import org.skywalking.apm.agent.core.context.trace.LogDataEntity; ...@@ -8,7 +8,7 @@ import org.skywalking.apm.agent.core.context.trace.LogDataEntity;
public class AbstractTracingSpanHelper { public class AbstractTracingSpanHelper {
public static int getParentSpanId(AbstractTracingSpan tracingSpan) { public static int getParentSpanId(AbstractTracingSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "parentSpanId"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "parentSpanId");
} catch (Exception e) { } catch (Exception e) {
} }
...@@ -17,7 +17,7 @@ public class AbstractTracingSpanHelper { ...@@ -17,7 +17,7 @@ public class AbstractTracingSpanHelper {
public static List<LogDataEntity> getLogs(AbstractTracingSpan tracingSpan) { public static List<LogDataEntity> getLogs(AbstractTracingSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "logs"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "logs");
} catch (Exception e) { } catch (Exception e) {
} }
......
...@@ -10,9 +10,10 @@ public class FieldGetter { ...@@ -10,9 +10,10 @@ public class FieldGetter {
return (T)field.get(instance); return (T)field.get(instance);
} }
public static <T> T getParentFieldValue(Object instance,
public static <T> T get2LevelParentFieldValue(Object instance,
String fieldName) throws IllegalAccessException, NoSuchFieldException { String fieldName) throws IllegalAccessException, NoSuchFieldException {
Field field = instance.getClass().getSuperclass().getDeclaredField(fieldName); Field field = instance.getClass().getSuperclass().getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true); field.setAccessible(true);
return (T)field.get(instance); return (T)field.get(instance);
} }
......
...@@ -7,7 +7,7 @@ public class SpanHelper { ...@@ -7,7 +7,7 @@ public class SpanHelper {
public static SpanLayer getLayer(AbstractSpan tracingSpan) { public static SpanLayer getLayer(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "layer"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "layer");
} catch (Exception e) { } catch (Exception e) {
} }
...@@ -16,7 +16,7 @@ public class SpanHelper { ...@@ -16,7 +16,7 @@ public class SpanHelper {
public static int getComponentId(AbstractSpan tracingSpan) { public static int getComponentId(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "componentId"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "componentId");
} catch (Exception e) { } catch (Exception e) {
} }
......
...@@ -80,6 +80,21 @@ ...@@ -80,6 +80,21 @@
<artifactId>apm-feign-default-http-9.x-plugin</artifactId> <artifactId>apm-feign-default-http-9.x-plugin</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </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>
<dependency>
<groupId>org.skywalking</groupId>
<artifactId>apm-springmvc-annotation-4.x-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<!-- activation --> <!-- activation -->
<dependency> <dependency>
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
<module>okhttp-3.x-plugin</module> <module>okhttp-3.x-plugin</module>
<module>resin-3.x-plugin</module> <module>resin-3.x-plugin</module>
<module>resin-4.x-plugin</module> <module>resin-4.x-plugin</module>
<module>spring-plugins</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>
......
<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>
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.SPRING_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);
}
}
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.SPRING_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);
}
}
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();
}
}
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();
}
}
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();
}
}
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;
}
}
}
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();
}
}
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();
}
}
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();
}
}
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
<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-springmvc-annotation-4.x-plugin</artifactId>
<packaging>jar</packaging>
<name>mvc-annotation-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>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.8.RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.0-b01</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
package org.skywalking.apm.plugin.spring.mvc;
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* The <code>ControllerConstructorInterceptor</code> intercepts the Controller's constructor, in order to acquire the
* mapping annotation, if exist.
*
* But, you can see we only use the first mapping value, <B>Why?</B>
*
* Right now, we intercept the controller by annotation as you known, so we CAN'T know which uri patten is actually
* matched. Even we know, that costs a lot.
*
* If we want to resolve that, we must intercept the Spring MVC core codes, that is not a good choice for now.
*
* Comment by @wu-sheng
*/
public class ControllerConstructorInterceptor implements InstanceConstructorInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
String basePath = "";
RequestMapping basePathRequestMapping = objInst.getClass().getAnnotation(RequestMapping.class);
if (basePathRequestMapping != null) {
basePath = basePathRequestMapping.value()[0];
}
PathMappingCache pathMappingCache = new PathMappingCache(basePath);
objInst.setSkyWalkingDynamicField(pathMappingCache);
}
}
package org.skywalking.apm.plugin.spring.mvc;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.skywalking.apm.agent.core.conf.Config;
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.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* The <code>ControllerServiceMethodInterceptor</code> only use the first mapping value.
*
* @See {@link ControllerConstructorInterceptor} to explain why we are doing this.
*/
public class ControllerServiceMethodInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
PathMappingCache pathMappingCache = (PathMappingCache)objInst.getSkyWalkingDynamicField();
String requestURL = pathMappingCache.findPathMapping(method);
if (requestURL == null) {
requestURL = method.getAnnotation(RequestMapping.class).value()[0];
pathMappingCache.addPathMapping(method, requestURL.toString());
}
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
String tracingHeaderValue = request.getHeader(Config.Plugin.Propagation.HEADER_NAME);
ContextCarrier contextCarrier = new ContextCarrier().deserialize(tracingHeaderValue);
AbstractSpan span = ContextManager.createEntrySpan(requestURL, contextCarrier);
Tags.URL.set(span, request.getRequestURL().toString());
Tags.HTTP.METHOD.set(span, request.getMethod());
span.setComponent(ComponentsDefine.SPRING_MVC_ANNOTATION);
SpanLayer.asHttp(span);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
AbstractSpan span = ContextManager.activeSpan();
if (response.getStatus() >= 400) {
span.errorOccurred();
Tags.STATUS_CODE.set(span, Integer.toString(response.getStatus()));
}
ContextManager.stopSpan();
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}
package org.skywalking.apm.plugin.spring.mvc;
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentHashMap;
/**
* The <code>PathMappingCache</code> represents a field
*
*
* @author wusheng
*/
public class PathMappingCache {
private String classPath = "";
private ConcurrentHashMap<Method, String> methodPathMapping = new ConcurrentHashMap<Method, String>();
public PathMappingCache(String classPath) {
this.classPath = classPath;
}
public String findPathMapping(Method method) {
return methodPathMapping.get(method);
}
public void addPathMapping(Method method, String methodPath) {
methodPathMapping.put(method, classPath + methodPath);
}
}
package org.skywalking.apm.plugin.spring.mvc.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.any;
import static net.bytebuddy.matcher.ElementMatchers.isAnnotatedWith;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.skywalking.apm.agent.core.plugin.match.ClassAnnotationMatch.byClassAnnotationMatch;
/**
* {@link ControllerInstrumentation} enhance all constructor and method annotated with
* <code>org.springframework.web.bind.annotation.RequestMapping</code> that class has
* <code>org.springframework.stereotype.Controller</code> annotation.
*
* <code>org.skywalking.apm.plugin.spring.mvc.ControllerConstructorInterceptor</code> set the controller base path to
* dynamic field before execute constructor.
*
* <code>org.skywalking.apm.plugin.spring.mvc.ControllerServiceMethodInterceptor</code> get the request path from
* dynamic field first, if not found, <code>ControllerServiceMethodInterceptor</code> generate request path that
* combine the path value of current annotation on current method and the base path and set the new path to the dynamic
* filed
*
* @author zhangxin
*/
public abstract class AbstractControllerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return any();
}
@Override
public String getConstructorInterceptor() {
return "org.skywalking.apm.plugin.spring.mvc.ControllerConstructorInterceptor";
}
}
};
}
@Override
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return isAnnotatedWith(named("org.springframework.web.bind.annotation.RequestMapping"));
}
@Override
public String getMethodsInterceptor() {
return "org.skywalking.apm.plugin.spring.mvc.ControllerServiceMethodInterceptor";
}
@Override
public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override
protected ClassMatch enhanceClass() {
return byClassAnnotationMatch(getEnhanceAnnotations());
}
protected abstract String[] getEnhanceAnnotations();
}
package org.skywalking.apm.plugin.spring.mvc.define;
public class ControllerInstrumentation extends AbstractControllerInstrumentation {
public static final String ENHANCE_ANNOTATION = "org.springframework.stereotype.Controller";
@Override protected String[] getEnhanceAnnotations() {
return new String[] {ENHANCE_ANNOTATION};
}
}
package org.skywalking.apm.plugin.spring.mvc.define;
public class RestControllerInstrumentation extends AbstractControllerInstrumentation {
public static final String ENHANCE_ANNOTATION = "org.springframework.web.bind.annotation.RestController";
@Override protected String[] getEnhanceAnnotations() {
return new String[] {ENHANCE_ANNOTATION};
}
}
spring-mvc-annotation-4.x=org.skywalking.apm.plugin.spring.mvc.define.ControllerInstrumentation
spring-mvc-annotation-4.x=org.skywalking.apm.plugin.spring.mvc.define.RestControllerInstrumentation
\ No newline at end of file
<?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>
<module>mvc-annotation-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>
<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>
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);
}
}
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) {
}
}
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.SPRING_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);
}
}
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);
}
}
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);
}
}
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.SPRING_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);
}
}
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) {
}
}
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);
}
}
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);
}
}
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) {
}
}
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
...@@ -16,4 +16,12 @@ public class FieldGetter { ...@@ -16,4 +16,12 @@ public class FieldGetter {
field.setAccessible(true); field.setAccessible(true);
return (T)field.get(instance); return (T)field.get(instance);
} }
public static <T> T get2LevelParentFieldValue(Object instance,
String fieldName) throws IllegalAccessException, NoSuchFieldException {
Field field = instance.getClass().getSuperclass().getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true);
return (T)field.get(instance);
}
} }
...@@ -10,8 +10,13 @@ import org.skywalking.apm.agent.core.context.util.KeyValuePair; ...@@ -10,8 +10,13 @@ import org.skywalking.apm.agent.core.context.util.KeyValuePair;
public class SpanHelper { public class SpanHelper {
public static int getParentSpanId(AbstractSpan tracingSpan) { public static int getParentSpanId(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "parentSpanId"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "parentSpanId");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "parentSpanId");
} catch (Exception e1) {
}
} }
return -9999; return -9999;
...@@ -19,8 +24,13 @@ public class SpanHelper { ...@@ -19,8 +24,13 @@ public class SpanHelper {
public static List<LogDataEntity> getLogs(AbstractSpan tracingSpan) { public static List<LogDataEntity> getLogs(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "logs"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "logs");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "logs");
} catch (Exception e1) {
}
} }
return Collections.emptyList(); return Collections.emptyList();
...@@ -28,8 +38,13 @@ public class SpanHelper { ...@@ -28,8 +38,13 @@ public class SpanHelper {
public static List<KeyValuePair> getTags(AbstractSpan tracingSpan) { public static List<KeyValuePair> getTags(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "tags"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "tags");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "tags");
} catch (Exception e1) {
}
} }
return Collections.emptyList(); return Collections.emptyList();
...@@ -37,8 +52,13 @@ public class SpanHelper { ...@@ -37,8 +52,13 @@ public class SpanHelper {
public static SpanLayer getLayer(AbstractSpan tracingSpan) { public static SpanLayer getLayer(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "layer"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "layer");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "layer");
} catch (Exception e1) {
}
} }
return null; return null;
...@@ -46,8 +66,13 @@ public class SpanHelper { ...@@ -46,8 +66,13 @@ public class SpanHelper {
public static String getComponentName(AbstractSpan tracingSpan) { public static String getComponentName(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "componentName"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "componentName");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "componentName");
} catch (Exception e1) {
}
} }
return null; return null;
...@@ -55,8 +80,13 @@ public class SpanHelper { ...@@ -55,8 +80,13 @@ public class SpanHelper {
public static int getComponentId(AbstractSpan tracingSpan) { public static int getComponentId(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "componentId"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "componentId");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "componentId");
} catch (Exception e1) {
}
} }
return -1; return -1;
...@@ -64,8 +94,13 @@ public class SpanHelper { ...@@ -64,8 +94,13 @@ public class SpanHelper {
public static boolean getErrorOccurred(AbstractSpan tracingSpan) { public static boolean getErrorOccurred(AbstractSpan tracingSpan) {
try { try {
return FieldGetter.getParentFieldValue(tracingSpan, "errorOccurred"); return FieldGetter.get2LevelParentFieldValue(tracingSpan, "errorOccurred");
} catch (Exception e) { } catch (Exception e) {
try {
return FieldGetter.getParentFieldValue(tracingSpan, "errorOccurred");
} catch (Exception e1) {
}
} }
return false; return false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册