diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index b23f30cf3b470a3953d7715d4cc3813f19c43816..3cfa017997694d2803154cec9ffa8bf3c95e27e3 100644
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -78,6 +78,8 @@ public class ComponentsDefine {
public static final OfficialComponent HTTP_ASYNC_CLIENT = new OfficialComponent(26, "httpasyncclient");
+ public static final OfficialComponent SERVICECOMB = new OfficialComponent(27, "ServiceComb");
+
private static ComponentsDefine INSTANCE = new ComponentsDefine();
private String[] components;
@@ -87,7 +89,7 @@ public class ComponentsDefine {
}
public ComponentsDefine() {
- components = new String[27];
+ components = new String[28];
addComponent(TOMCAT);
addComponent(HTTPCLIENT);
addComponent(DUBBO);
@@ -114,6 +116,7 @@ public class ComponentsDefine {
addComponent(ELASTIC_JOB);
addComponent(ROCKET_MQ);
addComponent(HTTP_ASYNC_CLIENT);
+ addComponent(SERVICECOMB);
}
private void addComponent(OfficialComponent component) {
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 4b81d1d8cd7317582c467e7611fc5a1fb7b9d2ec..2717502fac958626182517505baca1c0b8400e54 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -53,6 +53,7 @@
elastic-job-2.x-plugin
mongodb-2.x-plugin
httpasyncclient-4.x-plugin
+ servicecomb-java-chassis-plugin
pom
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..afd9a30310f50a740ec363f50ccd55f030abfd9e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/pom.xml
@@ -0,0 +1,81 @@
+
+
+
+ apm-sdk-plugin
+ org.apache.skywalking
+ 5.0.0-alpha
+
+ 4.0.0
+
+ apm-servicecomb-java-chassis-plugin
+ jar
+
+ servicecomb-java-chassis-plugin
+ http://maven.apache.org
+
+
+
+
+ io.servicecomb
+ java-chassis-core
+ 0.5.0
+ provided
+
+
+ io.servicecomb
+ swagger-invocation-core
+ 0.5.0
+ provided
+
+
+ io.servicecomb
+ foundation-common
+ 0.5.0
+ test
+
+
+ io.servicecomb
+ service-registry
+ 0.5.0
+ test
+
+
+ io.swagger
+ swagger-core
+ 1.5.17
+ test
+
+
+ org.slf4j
+ log4j-over-slf4j
+ 1.7.25
+ test
+
+
+ javax.ws.rs
+ jsr311-api
+ 1.1.1
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+
+ attach-sources
+ none
+
+ jar
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/InvocationInterceptor.java b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/InvocationInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..4e2c4e7e9e4453fa67d086f6efefc8bf5166ab58
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/InvocationInterceptor.java
@@ -0,0 +1,95 @@
+/*
+ * 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.plugin.servicecomb;
+
+import java.lang.reflect.Method;
+import javax.ws.rs.core.Response.StatusType;
+import io.servicecomb.core.Invocation;
+import io.servicecomb.swagger.invocation.InvocationType;
+import io.servicecomb.swagger.invocation.SwaggerInvocation;
+import io.servicecomb.swagger.invocation.context.InvocationContext;
+import org.apache.skywalking.apm.agent.core.context.CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+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;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+/**
+ * {@link InvocationInterceptor} define how to enhance class {@link Invocation#getHandlerChain()}.
+ *
+ * @author lytscu
+ */
+public class InvocationInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+ SwaggerInvocation swagger = (SwaggerInvocation)objInst;
+ InvocationType type = swagger.getInvocationType();
+ Invocation invocation = (Invocation)objInst;
+ AbstractSpan span;
+ boolean isConsumer = type.equals(InvocationType.CONSUMER);
+ if (!isConsumer) {
+
+ ContextCarrier contextCarrier = new ContextCarrier();
+ CarrierItem next = contextCarrier.items();
+ while (next.hasNext()) {
+ next = next.next();
+ next.setHeadValue(invocation.getContext().get(next.getHeadKey()));
+ }
+ String operationName = invocation.getOperationName();
+ span = ContextManager.createEntrySpan(operationName, contextCarrier);
+ String url = invocation.getOperationMeta().getOperationPath();
+ Tags.URL.set(span, url);
+ span.setComponent(ComponentsDefine.SERVICECOMB);
+ SpanLayer.asRPCFramework(span);
+ }
+ }
+
+ @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Object ret) throws Throwable {
+ SwaggerInvocation swagger = (SwaggerInvocation)objInst;
+ InvocationType type = swagger.getInvocationType();
+ boolean isConsumer = type.equals(InvocationType.CONSUMER);
+ if (!isConsumer) {
+ AbstractSpan span = ContextManager.activeSpan();
+ StatusType statusType = ((InvocationContext)objInst).getStatus();
+ int statusCode = statusType.getStatusCode();
+ if (statusCode >= 400) {
+ span.errorOccurred();
+ Tags.STATUS_CODE.set(span, Integer.toString(statusCode));
+ }
+ ContextManager.stopSpan();
+ }
+ return ret;
+ }
+
+ @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ AbstractSpan span = ContextManager.activeSpan();
+ span.errorOccurred();
+ span.log(t);
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/NextInterceptor.java b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/NextInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..e169ec24fa4747eb33250bd0a0e335ffd89b907e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/NextInterceptor.java
@@ -0,0 +1,117 @@
+/*
+ * 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.plugin.servicecomb;
+
+import io.servicecomb.core.Invocation;
+import io.servicecomb.swagger.invocation.InvocationType;
+import io.servicecomb.swagger.invocation.SwaggerInvocation;
+import io.servicecomb.swagger.invocation.context.InvocationContext;
+import java.lang.reflect.Method;
+import javax.ws.rs.core.Response.StatusType;
+import org.apache.skywalking.apm.agent.core.context.CarrierItem;
+import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+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;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+/**
+ * {@link NextInterceptor} define how to enhance class {@link Invocation#next(io.servicecomb.swagger.invocation.AsyncResponse)}.
+ *
+ * @author lytscu
+ */
+public class NextInterceptor implements InstanceMethodsAroundInterceptor {
+ static final ThreadLocal DEEP = new ThreadLocal() {
+ @Override
+ protected Integer initialValue() {
+ Integer deepindex = 0;
+ return deepindex;
+ }
+ };
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+ SwaggerInvocation swagger = (SwaggerInvocation)objInst;
+ InvocationType type = swagger.getInvocationType();
+ Invocation invocation = (Invocation)objInst;
+ AbstractSpan span;
+ boolean isConsumer = type.equals(InvocationType.CONSUMER);
+ if (isConsumer) {
+ Integer count = (Integer)DEEP.get();
+ try {
+ if (count == 2) {
+ String peer = invocation.getEndpoint().getAddress().toString();
+ final ContextCarrier contextCarrier = new ContextCarrier();
+ span = ContextManager.createExitSpan(invocation.getOperationName(), contextCarrier, peer);
+ CarrierItem next = contextCarrier.items();
+ while (next.hasNext()) {
+ next = next.next();
+ invocation.getContext().put(next.getHeadKey(), next.getHeadValue());
+ }
+ String url = invocation.getOperationMeta().getOperationPath();
+ Tags.URL.set(span, url);
+ span.setComponent(ComponentsDefine.SERVICECOMB);
+ SpanLayer.asRPCFramework(span);
+ }
+ } finally {
+ count++;
+ DEEP.set(count);
+ }
+ }
+ }
+
+ @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Object ret) throws Throwable {
+ SwaggerInvocation swagger = (SwaggerInvocation)objInst;
+ InvocationType type = swagger.getInvocationType();
+ boolean isConsumer = type.equals(InvocationType.CONSUMER);
+ if (isConsumer) {
+ Integer count = (Integer)DEEP.get();
+ try {
+ if (count == 1) {
+ AbstractSpan span = ContextManager.activeSpan();
+ StatusType statusType = ((InvocationContext)objInst).getStatus();
+ int statusCode = statusType.getStatusCode();
+ if (statusCode >= 400) {
+ span.errorOccurred();
+ Tags.STATUS_CODE.set(span, Integer.toString(statusCode));
+ }
+ ContextManager.stopSpan();
+ }
+ } finally {
+ count--;
+ DEEP.set(count);
+ }
+ }
+ return ret;
+ }
+
+ @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ AbstractSpan span = ContextManager.activeSpan();
+ span.errorOccurred();
+ span.log(t);
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/define/InvocationInstrumentation.java b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/define/InvocationInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..a173161cbc4fa870e340bf8d63a96c64cb2b9a56
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/java/org/apache/skywalking/apm/plugin/servicecomb/define/InvocationInstrumentation.java
@@ -0,0 +1,92 @@
+/*
+ * 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.plugin.servicecomb.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import io.servicecomb.core.Invocation;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
+import org.apache.skywalking.apm.plugin.servicecomb.InvocationInterceptor;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
+/**
+ * {@link InvocationInstrumentation} presents that skywalking intercept {@link io.servicecomb.core.Invocation#next(AsyncResponse)}by
+ * using {@link InvocationInterceptor}, and {@link Invocation#getHandlerChain() by using {@link NextInterceptor},
+ *
+ * @author lytscu
+ */
+public class InvocationInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+ private static final String ENHANCE_CLASS = "io.servicecomb.core.Invocation";
+
+ private static final String PRODUCER_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.servicecomb.InvocationInterceptor";
+
+ private static final String CONSUMER_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.servicecomb.NextInterceptor";
+
+ @Override
+ protected ClassMatch enhanceClass() {
+ return NameMatch.byName(ENHANCE_CLASS);
+ }
+
+ @Override
+ protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("getHandlerChain");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return PRODUCER_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override
+ public ElementMatcher getMethodsMatcher() {
+ return named("next");
+ }
+
+ @Override
+ public String getMethodsInterceptor() {
+ return CONSUMER_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000000000000000000000000000000000000..89240686eff6499483a1f15691035643ad039a37
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1 @@
+servicecomb-0.6=org.apache.skywalking.apm.plugin.servicecomb.define.InvocationInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/test/java/org/apache/skywalking/apm/plugin/servicecomb/InvocationInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/test/java/org/apache/skywalking/apm/plugin/servicecomb/InvocationInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c06dde790f12e436b602699a5f49cfbf252b2d01
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/test/java/org/apache/skywalking/apm/plugin/servicecomb/InvocationInterceptorTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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.plugin.servicecomb;
+
+import io.servicecomb.core.Endpoint;
+import io.servicecomb.core.Invocation;
+import io.servicecomb.core.definition.OperationMeta;
+import io.servicecomb.core.definition.SchemaMeta;
+import io.servicecomb.core.provider.consumer.ReferenceConfig;
+import io.servicecomb.swagger.invocation.InvocationType;
+import io.servicecomb.swagger.invocation.SwaggerInvocation;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.conf.Config;
+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.KeyValuePair;
+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.TracingSegmentRunner;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class InvocationInterceptorTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+ private InvocationInterceptor invocationInterceptor;
+ @Mock
+ private OperationMeta operationMeta;
+
+ @Mock
+ private MockInvocation enhancedInstance;
+
+ @Mock
+ private Endpoint endpoint;
+
+ @Mock
+ Response.StatusType statusType;
+
+ @Mock
+ ReferenceConfig referenceConfig;
+
+ @Mock
+ private SwaggerInvocation swagger;
+ private Object[] allArguments;
+ private Class[] argumentsType;
+ private Object[] swaggerArguments;
+
+ @Mock
+ private SchemaMeta schemaMeta;
+
+ @Before
+ public void setUp() throws Exception {
+ ServiceManager.INSTANCE.boot();
+ invocationInterceptor = new InvocationInterceptor();
+ PowerMockito.mock(Invocation.class);
+ when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta);
+ when(endpoint.getAddress()).thenReturn("0.0.0.0:7777");
+ when(enhancedInstance.getEndpoint()).thenReturn(endpoint);
+ when(enhancedInstance.getOperationName()).thenReturn("productorTest");
+ when(operationMeta.getOperationPath()).thenReturn("/bmi");
+ when(enhancedInstance.getOperationMeta()).thenReturn(operationMeta);
+ when(enhancedInstance.getStatus()).thenReturn(statusType);
+ when(statusType.getStatusCode()).thenReturn(200);
+ when(enhancedInstance.getInvocationType()).thenReturn(InvocationType.PRODUCER);
+ Config.Agent.APPLICATION_CODE = "serviceComnTestCases-APP";
+
+ allArguments = new Object[] {};
+ argumentsType = new Class[] {};
+ swaggerArguments = new Class[] {};
+ }
+
+ @Test
+ public void testConsumer() throws Throwable {
+
+ invocationInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null);
+ invocationInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, null);
+
+ Assert.assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+
+ List spans = SegmentHelper.getSpans(traceSegment);
+ assertCombSpan(spans.get(0));
+ verify(enhancedInstance, times(1)).getContext();
+ }
+
+ private void assertCombSpan(AbstractTracingSpan span) {
+ assertThat(span.getOperationName(), is("productorTest"));
+ assertThat(SpanHelper.getComponentId(span), is(27));
+ List tags = SpanHelper.getTags(span);
+ assertThat(tags.get(0).getValue(), is("/bmi"));
+ assertThat(span.isEntry(), is(true));
+ }
+
+ private class MockInvocation extends Invocation implements EnhancedInstance {
+ public MockInvocation(ReferenceConfig referenceConfig, OperationMeta operationMeta, Object[] swaggerArguments) {
+ super(referenceConfig, operationMeta, swaggerArguments);
+ }
+
+ @Override public Object getSkyWalkingDynamicField() {
+ return null;
+ }
+
+ @Override public void setSkyWalkingDynamicField(Object value) {
+
+ }
+
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/test/java/org/apache/skywalking/apm/plugin/servicecomb/NextInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/test/java/org/apache/skywalking/apm/plugin/servicecomb/NextInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c3576246c6f2a9825e9f35861c217cda014c64e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/servicecomb-java-chassis-plugin/src/test/java/org/apache/skywalking/apm/plugin/servicecomb/NextInterceptorTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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.plugin.servicecomb;
+
+import io.servicecomb.core.Endpoint;
+import io.servicecomb.core.Invocation;
+import io.servicecomb.core.definition.OperationMeta;
+import io.servicecomb.core.definition.SchemaMeta;
+import io.servicecomb.core.provider.consumer.ReferenceConfig;
+import io.servicecomb.swagger.invocation.InvocationType;
+import io.servicecomb.swagger.invocation.SwaggerInvocation;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.conf.Config;
+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.KeyValuePair;
+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.TracingSegmentRunner;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import static org.apache.skywalking.apm.plugin.servicecomb.NextInterceptor.DEEP;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class NextInterceptorTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+ private NextInterceptor nextInterceptor;
+ @Mock
+ private OperationMeta operationMeta;
+
+ @Mock
+ private MockInvocation enhancedInstance;
+
+ @Mock
+ private Endpoint endpoint;
+
+ @Mock
+ Response.StatusType statusType;
+
+ @Mock
+ ReferenceConfig referenceConfig;
+
+ @Mock
+ private SwaggerInvocation swagger;
+ private Object[] allArguments;
+ private Class[] argumentsType;
+ private Object[] swaggerArguments;
+
+ @Mock
+ private SchemaMeta schemaMeta;
+
+ @Before
+ public void setUp() throws Exception {
+ ServiceManager.INSTANCE.boot();
+ nextInterceptor = new NextInterceptor();
+ PowerMockito.mock(Invocation.class);
+ when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta);
+ when(endpoint.getAddress()).thenReturn("0.0.0.0:7777");
+ when(enhancedInstance.getEndpoint()).thenReturn(endpoint);
+ when(enhancedInstance.getOperationName()).thenReturn("consumerTest");
+ when(operationMeta.getOperationPath()).thenReturn("/bmi");
+ when(enhancedInstance.getOperationMeta()).thenReturn(operationMeta);
+ when(enhancedInstance.getStatus()).thenReturn(statusType);
+ when(statusType.getStatusCode()).thenReturn(200);
+ when(enhancedInstance.getInvocationType()).thenReturn(InvocationType.CONSUMER);
+ Config.Agent.APPLICATION_CODE = "serviceComnTestCases-APP";
+
+ allArguments = new Object[] {};
+ argumentsType = new Class[] {};
+ swaggerArguments = new Class[] {};
+ }
+
+ @Test
+ public void testConsumer() throws Throwable {
+ Integer count = 2;
+ DEEP.set(count);
+ nextInterceptor.beforeMethod(enhancedInstance, null, allArguments, argumentsType, null);
+ count = 1;
+ DEEP.set(count);
+ nextInterceptor.afterMethod(enhancedInstance, null, allArguments, argumentsType, null);
+
+ Assert.assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+
+ List spans = SegmentHelper.getSpans(traceSegment);
+ assertCombSpan(spans.get(0));
+ verify(enhancedInstance, times(1)).getContext();
+ }
+
+ private void assertCombSpan(AbstractTracingSpan span) {
+ assertThat(span.getOperationName(), is("consumerTest"));
+ assertThat(SpanHelper.getComponentId(span), is(27));
+ List tags = SpanHelper.getTags(span);
+ assertThat(tags.get(0).getValue(), is("/bmi"));
+ assertThat(span.isExit(), is(true));
+ }
+
+ private class MockInvocation extends Invocation implements EnhancedInstance {
+ public MockInvocation(ReferenceConfig referenceConfig, OperationMeta operationMeta, Object[] swaggerArguments) {
+ super(referenceConfig, operationMeta, swaggerArguments);
+ }
+
+ @Override public Object getSkyWalkingDynamicField() {
+ return null;
+ }
+
+ @Override public void setSkyWalkingDynamicField(Object value) {
+
+ }
+
+ }
+}