Tag annotation supports returned expression (#4327)
Co-authored-by: 吴晟 Wu Sheng <wu.sheng@foxmail.com> Co-authored-by: kezhenxu94 <kezhenxu94@163.com>
This commit is contained in:
parent
a07bfe147f
commit
e5366c0921
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -72,6 +73,11 @@ public class TestService {
|
|||
ActiveSpan.debug("TestDebugMsg");
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue