You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2020/02/12 06:03:11 UTC
[skywalking] branch master updated: Tag annotation supports
returned expression (#4327)
This is an automated email from the ASF dual-hosted git repository.
kezhenxu94 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git
The following commit(s) were added to refs/heads/master by this push:
new e5366c0 Tag annotation supports returned expression (#4327)
e5366c0 is described below
commit e5366c0921f0ec0052db33aa87ca72257cd3c7f1
Author: lxliuxuankb <38...@qq.com>
AuthorDate: Wed Feb 12 14:03:02 2020 +0800
Tag annotation supports returned expression (#4327)
Co-authored-by: 吴晟 Wu Sheng <wu...@foxmail.com>
Co-authored-by: kezhenxu94 <ke...@163.com>
---
.../apm/agent/core/util/CustomizeExpression.java | 24 +++
.../trace/TagAnnotationMethodInterceptor.java | 39 +++--
.../trace/TraceAnnotationMethodInterceptor.java | 37 +++--
.../apm/toolkit/activation/util/TagUtil.java | 43 ++++++
.../activation/trace/TagAnnotationTest.java | 169 +++++++++++++++++++++
.../activation/trace/TraceAnnotationTest.java | 76 ++++++++-
.../java-agent/Application-toolkit-trace.md | 8 +-
.../config/expectedData.yaml | 15 ++
.../apache/skywalking/apm/toolkit/model/User.java | 45 ++++++
.../toolkit/controller/TestController.java | 1 +
.../testcase/toolkit/controller/TestService.java | 6 +
11 files changed, 435 insertions(+), 28 deletions(-)
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CustomizeExpression.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CustomizeExpression.java
index df261c7..c03a121 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CustomizeExpression.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/util/CustomizeExpression.java
@@ -47,6 +47,20 @@ public class CustomizeExpression {
return context;
}
+ public static Map<String, Object> evaluationReturnContext(Object ret) {
+ Map<String, Object> context = new HashMap<>();
+ Field[] fields = ret.getClass().getDeclaredFields();
+ for (Field field : fields) {
+ field.setAccessible(true);
+ try {
+ context.put(field.getName(), field.get(ret));
+ } catch (Exception e) {
+ logger.debug("evaluationReturnContext error, ret is {}, exception is {}", ret, e.getMessage());
+ }
+ }
+ return context;
+ }
+
public static String parseExpression(String expression, Map<String, Object> context) {
try {
String[] es = expression.split("\\.");
@@ -56,7 +70,17 @@ public class CustomizeExpression {
logger.debug("parse expression error, expression is {}, exception is {}", expression, e.getMessage());
}
return "null";
+ }
+ public static String parseReturnExpression(String expression, Map<String, Object> context) {
+ try {
+ String[] es = expression.split("\\.");
+ Object o = context.get(es[1]);
+ return o == null ? "null" : String.valueOf(parse(es, o, 1));
+ } catch (Exception e) {
+ logger.debug("parse expression error, expression is {}, exception is {}", expression, e.getMessage());
+ }
+ return "null";
}
private static Object parse(String[] expressions, Object o, int i) {
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationMethodInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationMethodInterceptor.java
index 50bcf33..fcb701c 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationMethodInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationMethodInterceptor.java
@@ -22,8 +22,8 @@ import java.lang.reflect.Method;
import java.util.Map;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
-import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.toolkit.activation.util.TagUtil;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
@@ -46,23 +46,42 @@ public class TagAnnotationMethodInterceptor implements InstanceMethodsAroundInte
final Tags tags = method.getAnnotation(Tags.class);
if (tags != null && tags.value().length > 0) {
for (final Tag tag : tags.value()) {
- tagSpan(activeSpan, tag, context);
+ if (!TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagParamsSpan(activeSpan, context, tag);
+ }
}
}
final Tag tag = method.getAnnotation(Tag.class);
- if (tag != null) {
- tagSpan(activeSpan, tag, context);
+ if (tag != null && !TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagParamsSpan(activeSpan, context, tag);
}
}
- private void tagSpan(final AbstractSpan span, final Tag tag, final Map<String, Object> context) {
- new StringTag(tag.key()).set(span, CustomizeExpression.parseExpression(tag.value(), context));
- }
-
@Override
- public Object afterMethod(final EnhancedInstance objInst, final Method method, final Object[] allArguments,
- final Class<?>[] argumentsTypes, final Object ret) {
+ public Object afterMethod(
+ final EnhancedInstance objInst,
+ final Method method,
+ final Object[] allArguments,
+ final Class<?>[] argumentsTypes,
+ final Object ret) {
+ if (ret == null || !ContextManager.isActive()) {
+ return ret;
+ }
+ final AbstractSpan localSpan = ContextManager.activeSpan();
+ final Map<String, Object> context = CustomizeExpression.evaluationReturnContext(ret);
+ final Tags tags = method.getAnnotation(Tags.class);
+ if (tags != null && tags.value().length > 0) {
+ for (final Tag tag : tags.value()) {
+ if (TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagReturnSpanSpan(localSpan, context, tag);
+ }
+ }
+ }
+ final Tag tag = method.getAnnotation(Tag.class);
+ if (tag != null && TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagReturnSpanSpan(localSpan, context, tag);
+ }
return ret;
}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java
index 04de351..95c4fb5 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationMethodInterceptor.java
@@ -22,8 +22,8 @@ import java.lang.reflect.Method;
import java.util.Map;
import org.apache.skywalking.apm.agent.core.conf.Config;
-import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.toolkit.activation.util.TagUtil;
import org.apache.skywalking.apm.agent.core.util.CustomizeExpression;
import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Tags;
@@ -56,24 +56,41 @@ public class TraceAnnotationMethodInterceptor implements InstanceMethodsAroundIn
final Tags tags = method.getAnnotation(Tags.class);
if (tags != null && tags.value().length > 0) {
for (final Tag tag : tags.value()) {
- tagSpan(localSpan, tag, context);
+ if (!TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagParamsSpan(localSpan, context, tag);
+ }
}
}
-
final Tag tag = method.getAnnotation(Tag.class);
- if (tag != null) {
- tagSpan(localSpan, tag, context);
+ if (tag != null && !TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagParamsSpan(localSpan, context, tag);
}
}
- private void tagSpan(final AbstractSpan span, final Tag tag, final Map<String, Object> context) {
- new StringTag(tag.key()).set(span, CustomizeExpression.parseExpression(tag.value(), context));
- }
-
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
- ContextManager.stopSpan();
+ try {
+ if (ret == null) {
+ return ret;
+ }
+ final AbstractSpan localSpan = ContextManager.activeSpan();
+ final Map<String, Object> context = CustomizeExpression.evaluationReturnContext(ret);
+ final Tags tags = method.getAnnotation(Tags.class);
+ if (tags != null && tags.value().length > 0) {
+ for (final Tag tag : tags.value()) {
+ if (TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagReturnSpanSpan(localSpan, context, tag);
+ }
+ }
+ }
+ final Tag tag = method.getAnnotation(Tag.class);
+ if (tag != null && TagUtil.isReturnTag(tag.value())) {
+ TagUtil.tagReturnSpanSpan(localSpan, context, tag);
+ }
+ } finally {
+ ContextManager.stopSpan();
+ }
return ret;
}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/util/TagUtil.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/util/TagUtil.java
new file mode 100644
index 0000000..f5b5153
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/util/TagUtil.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.toolkit.activation.util;
+
+import java.util.Map;
+
+import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.util.CustomizeExpression;
+import org.apache.skywalking.apm.toolkit.trace.Tag;
+
+public class TagUtil {
+ public static void tagParamsSpan(final AbstractSpan span, final Map<String, Object> context,
+ final Tag tag) {
+ new StringTag(tag.key()).set(span, CustomizeExpression.parseExpression(tag.value(), context));
+ }
+
+ public static void tagReturnSpanSpan(final AbstractSpan span, final Map<String, Object> context,
+ final Tag tag) {
+ new StringTag(tag.key()).set(span, CustomizeExpression.parseReturnExpression(tag.value(), context));
+ }
+
+ public static Boolean isReturnTag(String expression) {
+ String[] es = expression.split("\\.");
+ return es.length == 2 && "returnedObj".equals(es[0]);
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationTest.java
new file mode 100644
index 0000000..02ddf68
--- /dev/null
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TagAnnotationTest.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.toolkit.activation.trace;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.context.util.TagValuePair;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.helper.SpanHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.toolkit.trace.Tag;
+import org.apache.skywalking.apm.toolkit.trace.Tags;
+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 static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class TagAnnotationTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage storage;
+
+ @Rule
+ public AgentServiceRule serviceRule = new AgentServiceRule();
+
+ @Mock
+ private EnhancedInstance enhancedInstance;
+
+ private TagAnnotationMethodInterceptor methodInterceptor;
+ private ActiveSpanTagInterceptor tagInterceptor;
+ private Object[] tagParameters;
+ private Class[] tagParameterTypes;
+
+ @Before
+ public void setUp() throws Exception {
+ methodInterceptor = new TagAnnotationMethodInterceptor();
+ tagInterceptor = new ActiveSpanTagInterceptor();
+ tagParameters = new Object[] {"testTagKey", "testTagValue"};
+ tagParameterTypes = new Class[] {String.class, String.class};
+
+ String operationName = "testMethod";
+ ContextManager.createLocalSpan(operationName);
+ }
+
+ @Test
+ public void testTraceWithTag() throws Throwable {
+ Method testMethodWithTag = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithTag", String.class);
+ methodInterceptor.beforeMethod(enhancedInstance, testMethodWithTag, new Object[]{"zhangsan"}, null, null);
+ methodInterceptor.afterMethod(enhancedInstance, testMethodWithTag, null, null, null);
+ ContextManager.stopSpan();
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is("testMethod"));
+ SpanAssert.assertLogSize(tracingSpan, 0);
+ SpanAssert.assertTagSize(tracingSpan, 1);
+ List<TagValuePair> tags = SpanHelper.getTags(tracingSpan);
+ assertThat(tags.get(0).getKey().key(), is("username"));
+ assertThat(tags.get(0).getValue(), is("zhangsan"));
+ }
+
+ @Test
+ public void testTraceWithReturnTag() throws Throwable {
+ Method testMethodWithTag = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithReturnTag", String.class, Integer.class);
+ methodInterceptor.beforeMethod(enhancedInstance, testMethodWithTag, new Object[]{"lisi", 14}, null, null);
+ methodInterceptor.afterMethod(enhancedInstance, testMethodWithTag, null, null, new User("lisi", 14));
+ ContextManager.stopSpan();
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is("testMethod"));
+ SpanAssert.assertLogSize(tracingSpan, 0);
+ SpanAssert.assertTagSize(tracingSpan, 1);
+ List<TagValuePair> tags = SpanHelper.getTags(tracingSpan);
+
+ assertThat(tags.get(0).getKey().key(), is("username"));
+ assertThat(tags.get(0).getValue(), is("lisi"));
+
+ }
+
+ @Test
+ public void testTraceWithTags() throws Throwable {
+ Method testMethodWithTags = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithTags", String.class, Integer.class);
+ methodInterceptor.beforeMethod(enhancedInstance, testMethodWithTags, new Object[]{"lisi", 14}, null, null);
+ methodInterceptor.afterMethod(enhancedInstance, testMethodWithTags, null, null, new User("lisi", 14));
+ ContextManager.stopSpan();
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is("testMethod"));
+ SpanAssert.assertLogSize(tracingSpan, 0);
+ SpanAssert.assertTagSize(tracingSpan, 2);
+ List<TagValuePair> tags = SpanHelper.getTags(tracingSpan);
+
+ assertThat(tags.get(0).getKey().key(), is("username"));
+ assertThat(tags.get(0).getValue(), is("lisi"));
+ assertThat(tags.get(1).getKey().key(), is("info"));
+ assertThat(tags.get(1).getValue(), is("username=lisi,age=14"));
+
+ }
+
+ private class TestAnnotationMethodClass {
+
+ @Tag(key = "username", value = "arg[0]")
+ public void testMethodWithTag(String username) {
+ }
+
+ @Tag(key = "username", value = "returnedObj.username")
+ public User testMethodWithReturnTag(String username, Integer age) {
+ return new User(username, age);
+ }
+
+ @Tags({@Tag(key = "username", value = "arg[0]"), @Tag(key = "info", value = "returnedObj.info")})
+ public User testMethodWithTags(String username, Integer age) {
+ return new User(username, age);
+ }
+ }
+
+ private class User {
+ private String username;
+ private Integer age;
+ private String info;
+
+ public User(String username, Integer age) {
+ this.username = username;
+ this.age = age;
+ info = String.format("username=%s,age=%s", username, age);
+ }
+ }
+}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java
index 86b9a4a..9c09881 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-trace-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/trace/TraceAnnotationTest.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.apm.toolkit.activation.trace;
import java.lang.reflect.Method;
import java.util.List;
+import lombok.AllArgsConstructor;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.context.util.TagValuePair;
@@ -31,6 +32,7 @@ import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.apache.skywalking.apm.toolkit.trace.Tag;
import org.apache.skywalking.apm.toolkit.trace.Trace;
import org.junit.Before;
import org.junit.Rule;
@@ -98,10 +100,12 @@ public class TraceAnnotationTest {
}
@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);
+ public void testTraceWithTag() throws Throwable {
+ Method testMethodWithTag = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithTag", String.class);
+ methodInterceptor.beforeMethod(enhancedInstance, testMethodWithTag, new Object[]{"zhangsan"}, null, null);
+ tagInterceptor.beforeMethod(TestAnnotationMethodClass.class, testMethodWithTag, tagParameters, tagParameterTypes, null);
+ tagInterceptor.afterMethod(TestAnnotationMethodClass.class, testMethodWithTag, tagParameters, tagParameterTypes, null);
+ methodInterceptor.afterMethod(enhancedInstance, testMethodWithTag, null, null, null);
assertThat(storage.getTraceSegments().size(), is(1));
TraceSegment traceSegment = storage.getTraceSegments().get(0);
@@ -109,8 +113,51 @@ public class TraceAnnotationTest {
assertThat(spans.size(), is(1));
AbstractTracingSpan tracingSpan = spans.get(0);
- assertThat(tracingSpan.getOperationName(), is(TestAnnotationMethodClass.class.getName() + "." + withOperationNameMethod
- .getName() + "()"));
+ assertThat(tracingSpan.getOperationName(), is("testMethod"));
+ SpanAssert.assertLogSize(tracingSpan, 0);
+ SpanAssert.assertTagSize(tracingSpan, 2);
+ List<TagValuePair> tags = SpanHelper.getTags(tracingSpan);
+ assertThat(tags.get(0).getKey().key(), is("username"));
+ assertThat(tags.get(0).getValue(), is("zhangsan"));
+ assertThat(tags.get(1).getKey().key(), is("testTagKey"));
+ assertThat(tags.get(1).getValue(), is("testTagValue"));
+ }
+
+ @Test
+ public void testTraceWithReturnTag() throws Throwable {
+ Method testMethodWithReturnTag = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithReturnTag", String.class, Integer.class);
+ methodInterceptor.beforeMethod(enhancedInstance, testMethodWithReturnTag, new Object[]{"lisi", 14}, null, null);
+ tagInterceptor.beforeMethod(TestAnnotationMethodClass.class, testMethodWithReturnTag, tagParameters, tagParameterTypes, null);
+ tagInterceptor.afterMethod(TestAnnotationMethodClass.class, testMethodWithReturnTag, tagParameters, tagParameterTypes, null);
+ methodInterceptor.afterMethod(enhancedInstance, testMethodWithReturnTag, null, null, new User("lisi", 14));
+
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is("testMethod"));
+ SpanAssert.assertLogSize(tracingSpan, 0);
+ SpanAssert.assertTagSize(tracingSpan, 2);
+ List<TagValuePair> tags = SpanHelper.getTags(tracingSpan);
+ assertThat(tags.get(0).getKey().key(), is("testTagKey"));
+ assertThat(tags.get(0).getValue(), is("testTagValue"));
+ assertThat(tags.get(1).getKey().key(), is("username"));
+ assertThat(tags.get(1).getValue(), is("lisi"));
+ }
+
+ @Test
+ public void testTrace() throws Throwable {
+ Method testMethodWithDefaultValue = TestAnnotationMethodClass.class.getDeclaredMethod("testMethodWithDefaultValue");
+ methodInterceptor.beforeMethod(enhancedInstance, testMethodWithDefaultValue, null, null, null);
+ methodInterceptor.afterMethod(enhancedInstance, testMethodWithDefaultValue, null, null, null);
+
+ assertThat(storage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = storage.getTraceSegments().get(0);
+ List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+ assertThat(spans.size(), is(1));
+ AbstractTracingSpan tracingSpan = spans.get(0);
+ assertThat(tracingSpan.getOperationName(), is(TestAnnotationMethodClass.class.getName() + "." + testMethodWithDefaultValue.getName() + "()"));
SpanAssert.assertLogSize(tracingSpan, 0);
SpanAssert.assertTagSize(tracingSpan, 0);
}
@@ -120,8 +167,25 @@ public class TraceAnnotationTest {
public void testMethodWithOperationName() {
}
+ @Trace(operationName = "testMethod")
+ @Tag(key = "username", value = "arg[0]")
+ public void testMethodWithTag(String username) {
+ }
+
+ @Trace(operationName = "testMethod")
+ @Tag(key = "username", value = "returnedObj.username")
+ public User testMethodWithReturnTag(String username, Integer age) {
+ return new User(username, age);
+ }
+
@Trace
public void testMethodWithDefaultValue() {
}
}
+
+ @AllArgsConstructor
+ private class User {
+ private String username;
+ private Integer age;
+ }
}
diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md
index 2c96e31..4b61f31 100644
--- a/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md
+++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-trace.md
@@ -39,12 +39,16 @@ ActiveSpan.debug("Test-debug-Msg");
/**
* The codes below will generate a span,
- * and two tags, keys are `tag1` and `tag2`, values are the passed-in parameters, respectively
+ * and two types of tags,
+ one type tag: keys are `tag1` and `tag2`, values are the passed-in parameters, respectively,
+ the other type tag: keys are `username` and `age`, values are the return value in User, respectively
*/
@Trace
@Tag(key = "tag1", value = "arg[0]")
@Tag(key = "tag2", value = "arg[1]")
-public void methodYouWantToTrace(String param1, String param2) {
+@Tag(key = "username", value = "returnedObj.username")
+@Tag(key = "age", value = "returnedObj.age")
+public User methodYouWantToTrace(String param1, String param2) {
// ...
}
```
diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml b/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml
index 307453d..683c3dd 100644
--- a/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/config/expectedData.yaml
@@ -145,6 +145,21 @@ segmentItems:
tags:
- {key: p1, value: testTagAnnotationParam1}
- {key: p2, value: testTagAnnotationParam2}
+ - operationName: test.org.apache.skywalking.apm.testcase.toolkit.controller.TestService.testTagAnnotationReturnInfo(java.lang.String,java.lang.Integer)
+ operationId: 0
+ parentSpanId: 0
+ spanId: 8
+ spanLayer: Unknown
+ startTime: nq 0
+ endTime: nq 0
+ componentId: 0
+ componentName: ''
+ isError: false
+ spanType: Local
+ peer: ''
+ peerId: 0
+ tags:
+ - {key: username, value: zhangsan}
- operationName: /case/tool-kit
operationId: 0
parentSpanId: -1
diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/model/User.java b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/model/User.java
new file mode 100644
index 0000000..0ae2339
--- /dev/null
+++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/org/apache/skywalking/apm/toolkit/model/User.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.toolkit.model;
+
+public class User {
+ private String username;
+ private Integer age;
+
+ public User(String username, Integer age) {
+ this.username = username;
+ this.age = age;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public Integer getAge() {
+ return age;
+ }
+
+ public void setAge(Integer age) {
+ this.age = age;
+ }
+}
diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestController.java b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestController.java
index 3b9af9e..cf7941a 100644
--- a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestController.java
+++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestController.java
@@ -47,6 +47,7 @@ public class TestController {
testService.testErrorMsg();
testService.testErrorThrowable();
testService.testTagAnnotation("testTagAnnotationParam1", "testTagAnnotationParam2");
+ testService.testTagAnnotationReturnInfo("zhangsan", 15);
testService.asyncCallable(() -> {
visit("http://localhost:8080/apm-toolkit-trace-scenario/case/asyncVisit/callable");
return true;
diff --git a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestService.java b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestService.java
index a193bf1..4c8827d 100644
--- a/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestService.java
+++ b/test/plugin/scenarios/apm-toolkit-trace-scenario/src/main/java/test/org/apache/skywalking/apm/testcase/toolkit/controller/TestService.java
@@ -18,6 +18,7 @@
package test.org.apache.skywalking.apm.testcase.toolkit.controller;
+import org.apache.skywalking.apm.toolkit.model.User;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -73,6 +74,11 @@ public class TestService {
}
@Trace
+ @Tag(key = "username", value = "returnedObj.username")
+ public User testTagAnnotationReturnInfo(final String username, final Integer age) {
+ return new User(username, age);
+ }
+ @Trace
@Tag(key = "testTag", value = "arg[0]")
public void testInfo(final String testInfoParam) {
ActiveSpan.info("TestInfoMsg");