diff --git a/apm-application-toolkit/apm-toolkit-trace/pom.xml b/apm-application-toolkit/apm-toolkit-trace/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4a5a4ad8cc96c2495281e4f37f0152f415c305d
--- /dev/null
+++ b/apm-application-toolkit/apm-toolkit-trace/pom.xml
@@ -0,0 +1,45 @@
+
+
+ apm-application-toolkit
+ org.skywalking
+ 3.2-2017
+
+ 4.0.0
+
+ apm-toolkit-trace
+ jar
+
+ http://maven.apache.org
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+
+ attach-sources
+
+ jar
+
+
+
+ 2.4
+
+
+
+
+
+
+ bintray-wu-sheng-sky-walking-repository
+ wu-sheng-sky-walking-repository
+
+ https://api.bintray.com/maven/wu-sheng/skywalking/org.skywalking.apm-toolkit-trace/;publish=1
+
+
+
+
diff --git a/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/skywalking/apm/toolkit/trace/ActiveSpan.java b/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/skywalking/apm/toolkit/trace/ActiveSpan.java
new file mode 100644
index 0000000000000000000000000000000000000000..a1776d7a83fa312e3e524eab55245de5c8655b88
--- /dev/null
+++ b/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/skywalking/apm/toolkit/trace/ActiveSpan.java
@@ -0,0 +1,16 @@
+package org.skywalking.apm.toolkit.trace;
+
+/**
+ * provide custom api that set tag for current active span.
+ *
+ * @author zhangxin
+ */
+public class ActiveSpan {
+ /**
+ * @param key tag key
+ * @param value tag value
+ */
+ public static void tag(String key, String value) {
+
+ }
+}
diff --git a/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/skywalking/apm/toolkit/trace/Trace.java b/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/skywalking/apm/toolkit/trace/Trace.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d5f7f4625ee470dcb2f289b04df0baf8192f16e
--- /dev/null
+++ b/apm-application-toolkit/apm-toolkit-trace/src/main/java/org/skywalking/apm/toolkit/trace/Trace.java
@@ -0,0 +1,22 @@
+package org.skywalking.apm.toolkit.trace;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The agent create local span if the method that annotation with {@link Trace}. The value of span operation name will
+ * fetch by {@link #operationName()}. if the value of {@link #operationName()} is blank string. the operation name will
+ * be set the class name + method name.
+ *
+ * @author zhangxin
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Trace {
+ /**
+ * @return operation name, the default value is blank string.
+ */
+ String operationName() default "";
+}
diff --git a/apm-application-toolkit/pom.xml b/apm-application-toolkit/pom.xml
index c786e2fff484505506de0fb3084c836ed9b43272..b8f68ffd72ea5462235ebbdba5c12af0772e6dd4 100644
--- a/apm-application-toolkit/pom.xml
+++ b/apm-application-toolkit/pom.xml
@@ -19,5 +19,6 @@
apm-toolkit-logback-1.x
apm-toolkit-trace-context
apm-toolkit-opentracing
+ apm-toolkit-trace
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/ContextManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/ContextManager.java
index 01765f638580508a4230a36e09e45eb77a75ac0c..c950031f7a29dcfdb2e091aa5a8f1a89007914fd 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/ContextManager.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/context/ContextManager.java
@@ -39,7 +39,7 @@ public class ContextManager implements TracingContextListener, BootService, Igno
context = new IgnoredTracerContext();
} else {
if (RemoteDownstreamConfig.Agent.APPLICATION_ID != DictionaryUtil.nullValue()
- || RemoteDownstreamConfig.Agent.APPLICATION_INSTANCE_ID != DictionaryUtil.nullValue()
+ && RemoteDownstreamConfig.Agent.APPLICATION_INSTANCE_ID != DictionaryUtil.nullValue()
) {
int suffixIdx = operationName.lastIndexOf(".");
if (suffixIdx > -1 && Config.Agent.IGNORE_SUFFIX.contains(operationName.substring(suffixIdx))) {
@@ -108,6 +108,12 @@ public class ContextManager implements TracingContextListener, BootService, Igno
return span;
}
+ public static AbstractSpan createExitSpan(String operationName, String remotePeer) {
+ AbstractTracerContext context = getOrCreate(operationName, false);
+ AbstractSpan span = context.createExitSpan(operationName, remotePeer);
+ return span;
+ }
+
public static void inject(ContextCarrier carrier) {
get().inject(carrier);
}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java
index b8059aea082d38c9969fab0f79ffa690c5a7060d..0a91ff56a971a3c6e00c0487431aa34403b7fe2a 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/skywalking/apm/agent/core/plugin/match/MethodAnnotationMatch.java
@@ -1,5 +1,6 @@
package org.skywalking.apm.agent.core.plugin.match;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.bytebuddy.description.annotation.AnnotationDescription;
@@ -47,7 +48,7 @@ public class MethodAnnotationMatch implements IndirectMatch {
@Override
public boolean isMatch(TypeDescription typeDescription) {
for (MethodDescription.InDefinedShape methodDescription : typeDescription.getDeclaredMethods()) {
- List annotationList = Arrays.asList(annotations);
+ List annotationList = new ArrayList(Arrays.asList(annotations));
AnnotationList declaredAnnotations = methodDescription.getDeclaredAnnotations();
for (AnnotationDescription annotation : declaredAnnotations) {
diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml
index bda4d71373ce3734d15e7b3850ca6c50a7863af5..b9d1845b1e7244dc42cbee82c381211c0d4e4939 100644
--- a/apm-sniffer/apm-agent/pom.xml
+++ b/apm-sniffer/apm-agent/pom.xml
@@ -126,6 +126,12 @@
${project.version}
+
+ org.skywalking
+ apm-toolkit-trace-activation
+ ${project.version}
+
+
skywalking-agent
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/CallableStatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/CallableStatementTracing.java
index 30d82ae34640ccb739b65af181fca253896846b2..f41884d25ddcd9ea9bc97b428c03e7efbf13a18a 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/CallableStatementTracing.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/CallableStatementTracing.java
@@ -1,7 +1,6 @@
package org.skywalking.apm.plugin.jdbc;
import java.sql.SQLException;
-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;
@@ -20,7 +19,7 @@ public class CallableStatementTracing {
} else {
remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort();
}
- AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/CallableStatement/" + method, new ContextCarrier(), remotePeer);
+ AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/CallableStatement/" + method, remotePeer);
Tags.DB_TYPE.set(span, "sql");
SpanLayer.asDB(span);
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java
index c87685ba3bdd644e67746ea0def3ce54e42585e2..46e9b59f80d90bcfde316e15c692a98caf8067ed 100755
--- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/ConnectionTracing.java
@@ -1,7 +1,6 @@
package org.skywalking.apm.plugin.jdbc;
import java.sql.SQLException;
-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;
@@ -20,7 +19,7 @@ public class ConnectionTracing {
} else {
remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort();
}
- AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Connection/" + method, new ContextCarrier(), remotePeer);
+ AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Connection/" + method, remotePeer);
Tags.DB_TYPE.set(span, "sql");
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
Tags.DB_STATEMENT.set(span, sql);
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/PreparedStatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/PreparedStatementTracing.java
index 3d94b45aabb509f9c3e7a734b29131c75e5e41cc..a0db29ba34d15cc62b3ec9fe09c824a95a3d50bc 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/PreparedStatementTracing.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/PreparedStatementTracing.java
@@ -1,7 +1,6 @@
package org.skywalking.apm.plugin.jdbc;
import java.sql.SQLException;
-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;
@@ -21,7 +20,7 @@ public class PreparedStatementTracing {
remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort();
}
- AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/PreparedStatement/" + method, new ContextCarrier(), remotePeer);
+ AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/PreparedStatement/" + method, remotePeer);
Tags.DB_TYPE.set(span, "sql");
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
Tags.DB_STATEMENT.set(span, sql);
diff --git a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/StatementTracing.java b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/StatementTracing.java
index a8510864714a77c05abc13ea73f2930bfe50140f..6d496f6bc8411f9a28e3d958997d35de85642826 100644
--- a/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/StatementTracing.java
+++ b/apm-sniffer/apm-sdk-plugin/jdbc-plugin/src/main/java/org/skywalking/apm/plugin/jdbc/StatementTracing.java
@@ -1,7 +1,6 @@
package org.skywalking.apm.plugin.jdbc;
import java.sql.SQLException;
-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;
@@ -20,7 +19,7 @@ public class StatementTracing {
remotePeer = connectInfo.getHost() + ":" + connectInfo.getPort();
}
- AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Statement/" + method, new ContextCarrier(), remotePeer);
+ AbstractSpan span = ContextManager.createExitSpan(connectInfo.getDBType() + "/JDBI/Statement/" + method, remotePeer);
Tags.DB_TYPE.set(span, "sql");
Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName());
Tags.DB_STATEMENT.set(span, sql);
diff --git a/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jedis/v2/JedisMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jedis/v2/JedisMethodInterceptor.java
index 83b3c41ee66c67cb1bc55e2b27eccc1aa756b893..d16deb8a56131f392acb9938fecc741d95104c56 100644
--- a/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jedis/v2/JedisMethodInterceptor.java
+++ b/apm-sniffer/apm-sdk-plugin/jedis-2.x-plugin/src/main/java/org/skywalking/apm/plugin/jedis/v2/JedisMethodInterceptor.java
@@ -1,7 +1,6 @@
package org.skywalking.apm.plugin.jedis.v2;
import java.lang.reflect.Method;
-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;
@@ -16,7 +15,7 @@ public class JedisMethodInterceptor implements InstanceMethodsAroundInterceptor
@Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
String peer = String.valueOf(objInst.getSkyWalkingDynamicField());
- AbstractSpan span = ContextManager.createExitSpan("Jedis/" + method.getName(), new ContextCarrier(), peer);
+ AbstractSpan span = ContextManager.createExitSpan("Jedis/" + method.getName(), peer);
span.setComponent(ComponentsDefine.REDIS);
Tags.DB_TYPE.set(span, "Redis");
SpanLayer.asDB(span);
diff --git a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/skywalking/apm/plugin/spring/mvc/ControllerServiceMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/skywalking/apm/plugin/spring/mvc/ControllerServiceMethodInterceptor.java
index a735251c4385cc19034ceee6148dd8db37d4a071..4a5ba25715b82efad2d8abb2878181e305dabd68 100644
--- a/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/skywalking/apm/plugin/spring/mvc/ControllerServiceMethodInterceptor.java
+++ b/apm-sniffer/apm-sdk-plugin/spring-plugins/mvc-annotation-4.x-plugin/src/main/java/org/skywalking/apm/plugin/spring/mvc/ControllerServiceMethodInterceptor.java
@@ -36,6 +36,7 @@ public class ControllerServiceMethodInterceptor implements InstanceMethodsAround
requestURL = "";
}
pathMappingCache.addPathMapping(method, requestURL);
+ requestURL = pathMappingCache.findPathMapping(method);
}
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
diff --git a/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/helper/SpanHelper.java b/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/helper/SpanHelper.java
index 0b752e9474715b412e5b7d81cb043ba24b33196a..ff5ba70345187dcb02b27f16e666154e4ef6d116 100644
--- a/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/helper/SpanHelper.java
+++ b/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/helper/SpanHelper.java
@@ -24,10 +24,16 @@ public class SpanHelper {
public static List getLogs(AbstractSpan tracingSpan) {
try {
- return FieldGetter.get2LevelParentFieldValue(tracingSpan, "logs");
+ List logs = FieldGetter.get2LevelParentFieldValue(tracingSpan, "logs");
+ if (logs != null) {
+ return logs;
+ }
} catch (Exception e) {
try {
- return FieldGetter.getParentFieldValue(tracingSpan, "logs");
+ List logs = FieldGetter.getParentFieldValue(tracingSpan, "logs");
+ if (logs != null) {
+ return logs;
+ }
} catch (Exception e1) {
}
@@ -38,10 +44,16 @@ public class SpanHelper {
public static List getTags(AbstractSpan tracingSpan) {
try {
- return FieldGetter.get2LevelParentFieldValue(tracingSpan, "tags");
+ List tags = FieldGetter.get2LevelParentFieldValue(tracingSpan, "tags");
+ if (tags != null) {
+ return tags;
+ }
} catch (Exception e) {
try {
- return FieldGetter.getParentFieldValue(tracingSpan, "tags");
+ List tags = FieldGetter.getParentFieldValue(tracingSpan, "tags");
+ if (tags != null) {
+ return tags;
+ }
} catch (Exception e1) {
}
diff --git a/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/tools/SpanAssert.java b/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/tools/SpanAssert.java
index 584c870f7d470dab1c9b1ad202e6b284fd43acce..ca6280e1135902eacdf0934743ae2b0064097082 100644
--- a/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/tools/SpanAssert.java
+++ b/apm-sniffer/apm-test-tools/src/main/java/org/skywalking/apm/agent/test/tools/SpanAssert.java
@@ -17,6 +17,10 @@ public class SpanAssert {
assertThat(SpanHelper.getLogs(span).size(), is(exceptedSize));
}
+ public static void assertTagSize(AbstractSpan span, int exceptedSize) {
+ assertThat(SpanHelper.getTags(span).size(), is(exceptedSize));
+ }
+
public static void assertException(LogDataEntity logDataEntity, Class extends Throwable> throwableClass,
String message) {
Assert.assertThat(logDataEntity.getLogs().size(), is(4));
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/java/org/skywalking/apm/toolkit/activation/opentracing/span/ConstructorWithSpanBuilderInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/java/org/skywalking/apm/toolkit/activation/opentracing/span/ConstructorWithSpanBuilderInterceptor.java
index b9127ab20573318039b26bb63323a7f9dcb9a464..387abd4dfdc1d5528a0ea1cf1004c2f9a41be0ff 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/java/org/skywalking/apm/toolkit/activation/opentracing/span/ConstructorWithSpanBuilderInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-opentracing-activation/src/main/java/org/skywalking/apm/toolkit/activation/opentracing/span/ConstructorWithSpanBuilderInterceptor.java
@@ -1,6 +1,5 @@
package org.skywalking.apm.toolkit.activation.opentracing.span;
-import org.skywalking.apm.agent.core.context.ContextCarrier;
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;
@@ -19,8 +18,7 @@ public class ConstructorWithSpanBuilderInterceptor implements InstanceConstructo
if (spanBuilder.isEntry()) {
span = ContextManager.createEntrySpan(spanBuilder.getOperationName(), null);
} else if (spanBuilder.isExit() && (!StringUtil.isEmpty(spanBuilder.getPeer()))) {
- span = ContextManager.createExitSpan(spanBuilder.getOperationName(),
- new ContextCarrier(), buildRemotePeer(spanBuilder));
+ span = ContextManager.createExitSpan(spanBuilder.getOperationName(), buildRemotePeer(spanBuilder));
} else {
span = ContextManager.createLocalSpan(spanBuilder.getOperationName());
}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ff76498e887df30fbf4f02e6c0c0b5bf56ddb7b7
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/pom.xml
@@ -0,0 +1,22 @@
+
+
+
+ apm-toolkit-activation
+ org.skywalking
+ 3.2-2017
+
+ 4.0.0
+
+ apm-toolkit-trace-activation
+
+
+
+ org.skywalking
+ apm-toolkit-trace
+ ${project.version}
+ provided
+
+
+
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/ActiveSpanTagActivation.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/ActiveSpanTagActivation.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba810d9a9604ece0d4fff991a0a8015484f70a1b
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/ActiveSpanTagActivation.java
@@ -0,0 +1,50 @@
+package org.skywalking.apm.toolkit.activation.trace;
+
+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.StaticMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
+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 TraceAnnotationActivation} enhance the tag
method of org.skywalking.apm.toolkit.trace.ActiveSpan
+ * by org.skywalking.apm.toolkit.activation.trace.ActiveSpanTagInterceptor
.
+ *
+ * @author zhangxin
+ */
+public class ActiveSpanTagActivation extends ClassStaticMethodsEnhancePluginDefine {
+
+ public static final String ENHANCE_CLASS = "org.skywalking.apm.toolkit.trace.ActiveSpan";
+ public static final String INTERCEPTOR_CLASS = "org.skywalking.apm.toolkit.activation.trace.ActiveSpanTagInterceptor";
+ public static final String INTERCEPTOR_METHOD_NAME = "tag";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
+ return new StaticMethodsInterceptPoint[] {
+ new StaticMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(INTERCEPTOR_METHOD_NAME);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return INTERCEPTOR_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/ActiveSpanTagInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/ActiveSpanTagInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..17f4741332a30dba97c821c5941866c9f91dbdfb
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/ActiveSpanTagInterceptor.java
@@ -0,0 +1,26 @@
+package org.skywalking.apm.toolkit.activation.trace;
+
+import java.lang.reflect.Method;
+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.MethodInterceptResult;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
+
+public class ActiveSpanTagInterceptor implements StaticMethodsAroundInterceptor {
+ @Override public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class>[] parameterTypes,
+ MethodInterceptResult result) {
+ AbstractSpan activeSpan = ContextManager.activeSpan();
+ activeSpan.tag(String.valueOf(allArguments[0]), String.valueOf(allArguments[1]));
+ }
+
+ @Override public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class>[] parameterTypes,
+ Object ret) {
+ return ret;
+ }
+
+ @Override
+ public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class>[] parameterTypes,
+ Throwable t) {
+
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationActivation.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationActivation.java
new file mode 100644
index 0000000000000000000000000000000000000000..f02709102387ddf3c08ad13e4ebcbfef34187092
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationActivation.java
@@ -0,0 +1,50 @@
+package org.skywalking.apm.toolkit.activation.trace;
+
+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.isAnnotatedWith;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.MethodAnnotationMatch.byMethodAnnotationMatch;
+
+/**
+ * {@link TraceAnnotationActivation} enhance all method that annotated with org.skywalking.apm.toolkit.trace.annotation.Trace
+ * by org.skywalking.apm.toolkit.activation.trace.TraceAnnotationMethodInterceptor
.
+ *
+ * @author zhangxin
+ */
+public class TraceAnnotationActivation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ public static final String TRACE_ANNOTATION_METHOD_INTERCEPTOR = "org.skywalking.apm.toolkit.activation.trace.TraceAnnotationMethodInterceptor";
+ public static final String TRACE_ANNOTATION = "org.skywalking.apm.toolkit.trace.Trace";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return isAnnotatedWith(named(TRACE_ANNOTATION));
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return TRACE_ANNOTATION_METHOD_INTERCEPTOR;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byMethodAnnotationMatch(new String[] {TRACE_ANNOTATION});
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..39f0988bbdc8e474320947e43afd07b9ef574583
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java
@@ -0,0 +1,54 @@
+package org.skywalking.apm.toolkit.activation.trace;
+
+import java.lang.reflect.Method;
+import org.skywalking.apm.agent.core.context.ContextManager;
+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.toolkit.trace.Trace;
+
+/**
+ * {@link TraceAnnotationMethodInterceptor} create a local span and set the operation name which fetch from
+ * org.skywalking.apm.toolkit.trace.annotation.Trace.operationName
. if the fetch value is blank string, and
+ * the operation name will be the method name.
+ *
+ * @author zhangxin
+ */
+public class TraceAnnotationMethodInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ Trace trace = method.getAnnotation(Trace.class);
+ String operationName = trace.operationName();
+ if (operationName.length() == 0) {
+ operationName = generateOperationName(method);
+ }
+
+ ContextManager.createLocalSpan(operationName);
+ }
+
+ private String generateOperationName(Method method) {
+ StringBuilder operationName = new StringBuilder(method.getDeclaringClass().getName() + "." + method.getName() + "(");
+ Class>[] parameterTypes = method.getParameterTypes();
+ for (int i = 0; i < parameterTypes.length; i++) {
+ operationName.append(parameterTypes[i].getName());
+ if (i < (parameterTypes.length - 1)) {
+ operationName.append(",");
+ }
+ }
+ operationName.append(")");
+ return operationName.toString();
+ }
+
+ @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);
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000000000000000000000000000000000000..42ba1a8e60521e8590174b8d245f7f09c7bb85fe
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,2 @@
+trace-annotation=org.skywalking.apm.toolkit.activation.trace.ActiveSpanTagActivation
+trace-annotation=org.skywalking.apm.toolkit.activation.trace.TraceAnnotationActivation
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce5350e6f6e5104346696427f056f836371ef932
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java
@@ -0,0 +1,103 @@
+package org.skywalking.apm.toolkit.activation.trace;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.skywalking.apm.agent.core.context.util.KeyValuePair;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.skywalking.apm.agent.test.helper.SpanHelper;
+import org.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.skywalking.apm.toolkit.trace.Trace;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.skywalking.apm.agent.test.tools.SpanAssert.assertLogSize;
+import static org.skywalking.apm.agent.test.tools.SpanAssert.assertTagSize;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class TraceAnnotationTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage storage;
+
+ @Rule
+ public AgentServiceRule serviceRule = new AgentServiceRule();
+
+ @Mock
+ private EnhancedInstance enhancedInstance;
+
+ private TraceAnnotationMethodInterceptor methodInterceptor;
+ private ActiveSpanTagInterceptor tagInterceptor;
+ private Object[] tagParameters;
+ private Class[] tagParameterTypes;
+
+ @Before
+ public void setUp() throws Exception {
+ methodInterceptor = new TraceAnnotationMethodInterceptor();
+ tagInterceptor = new ActiveSpanTagInterceptor();
+ tagParameters = new Object[] {"testTagKey", "testTagValue"};
+ tagParameterTypes = new Class[] {String.class, String.class};
+ }
+
+ @Test
+ public void testTraceWithOperationName() throws Throwable {
+ Method withOperationNameMethod = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithOperationName");
+ methodInterceptor.beforeMethod(enhancedInstance, withOperationNameMethod, null, null, null);
+ tagInterceptor.beforeMethod(TestAnnotationMethodClass.class, withOperationNameMethod, tagParameters, tagParameterTypes, null);
+ tagInterceptor.afterMethod(TestAnnotationMethodClass.class, withOperationNameMethod, tagParameters, tagParameterTypes, null);
+ methodInterceptor.afterMethod(enhancedInstance, withOperationNameMethod, null, null, null);
+
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is("testMethod"));
+ assertLogSize(tracingSpan, 0);
+ assertTagSize(tracingSpan, 1);
+ List tags = SpanHelper.getTags(tracingSpan);
+ assertThat(tags.get(0).getKey(), is("testTagKey"));
+ assertThat(tags.get(0).getValue(), is("testTagValue"));
+ }
+
+ @Test
+ public void testTrace() throws Throwable {
+ Method withOperationNameMethod = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithDefaultValue");
+ methodInterceptor.beforeMethod(enhancedInstance, withOperationNameMethod, null, null, null);
+ methodInterceptor.afterMethod(enhancedInstance, withOperationNameMethod, null, null, null);
+
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is(TestAnnotationMethodClass.class.getName() + "." + withOperationNameMethod.getName() + "()"));
+ assertLogSize(tracingSpan, 0);
+ assertTagSize(tracingSpan, 0);
+ }
+
+ private class TestAnnotationMethodClass {
+ @Trace(operationName = "testMethod")
+ public void testMethodWithOperationName() {
+ }
+
+ @Trace
+ public void testMethodWithDefaultValue() {
+ }
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/pom.xml b/apm-sniffer/apm-toolkit-activation/pom.xml
index 655cfd01f1cb54b7e2a9feb0ad25445d5c6f31cd..32b2aa533012bf3f84e79ffd34c0e6ef43825a74 100644
--- a/apm-sniffer/apm-toolkit-activation/pom.xml
+++ b/apm-sniffer/apm-toolkit-activation/pom.xml
@@ -15,6 +15,7 @@
apm-toolkit-logback-1.x-activation
apm-toolkit-trace-context-activation
apm-toolkit-opentracing-activation
+ apm-toolkit-trace-activation
apm-toolkit-activation