diff --git a/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java
index 0582108bf4e8251923a86d01545e6a637dbbb440..0f45a0c88c07e29278fbc1029ee951a7d99e0320 100644
--- a/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-network/src/main/java/org/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -67,6 +67,8 @@ public class ComponentsDefine {
public static final OfficialComponent SHARDING_JDBC = new OfficialComponent(21, "ShardingJDBC");
+ public static final OfficialComponent GRPC = new OfficialComponent(22, "GRPC");
+
private static ComponentsDefine instance = new ComponentsDefine();
private String[] components;
@@ -76,7 +78,7 @@ public class ComponentsDefine {
}
public ComponentsDefine() {
- components = new String[22];
+ components = new String[23];
addComponent(TOMCAT);
addComponent(HTTPCLIENT);
addComponent(DUBBO);
@@ -98,6 +100,7 @@ public class ComponentsDefine {
addComponent(JETTY_SERVER);
addComponent(MEMCACHED);
addComponent(SHARDING_JDBC);
+ addComponent(GRPC);
}
private void addComponent(OfficialComponent component) {
diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml
index 8047e216183e0a2a018a2f1b5d83b50b57767982..411d68621b1732678495e94d0496e0bee769564a 100644
--- a/apm-sniffer/apm-agent/pom.xml
+++ b/apm-sniffer/apm-agent/pom.xml
@@ -153,6 +153,11 @@
apm-sharding-jdbc-1.5.x-plugin
${project.version}
+
+ org.skywalking
+ apm-grpc-1.x-plugin
+ ${project.version}
+
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7b72913a804d718dd0f4a7db427319f5f9809ba6
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml
@@ -0,0 +1,59 @@
+
+
+
+
+ 4.0.0
+
+ org.skywalking
+ apm-sdk-plugin
+ 3.2.3-2017
+
+
+ apm-grpc-1.x-plugin
+ grpc-1.x-plugin
+ jar
+
+
+ UTF-8
+
+
+
+
+ io.grpc
+ grpc-all
+ 1.6.0
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ 2.4.3
+
+ ${project.build.sourceEncoding}
+
+
+
+
+
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6c85d1ce1267621455919a487a1e5db7a458de8
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.MethodDescriptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+/**
+ * {@link ClientCallIConstructorInterceptor} pass the {@link GRPCDynamicFields} into the
+ * io.grpc.internal.ClientCallImpl
instance for propagate the information of build span.
+ *
+ * @author zhangxin
+ */
+public class ClientCallIConstructorInterceptor implements InstanceConstructorInterceptor {
+
+ @Override
+ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+ GRPCDynamicFields dynamicFields = new GRPCDynamicFields();
+ dynamicFields.setDescriptor((MethodDescriptor)allArguments[0]);
+ objInst.setSkyWalkingDynamicField(dynamicFields);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..a46de3c77ba0e1641cd2da279500f13b757a772d
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_OPERATION_NAME_SUFFIX;
+
+/**
+ * {@link ClientCallOnNextInterceptor} create a local span when the client stream receive an message that send from
+ * server stream and record the value of OnNext.count
tag.
+ *
+ * @author zhangxin
+ */
+public class ClientCallOnNextInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_OPERATION_NAME_SUFFIX);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ ContextManager.stopSpan();
+
+ // record the call count of onNext method
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ cachedObjects.incrementOnNextCount();
+
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..9515364b3061129e7c7d5226248ef216033d4ed9
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import java.lang.reflect.Method;
+import org.skywalking.apm.agent.core.context.CarrierItem;
+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.context.trace.SpanLayer;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+/**
+ * {@link ClientCallOnNextInterceptor} create a exist span when the grpc start call. it will stop span when the method
+ * type is non-unary.
+ *
+ * @author zhangxin
+ */
+public class ClientCallStartInterceptor
+ implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ final Metadata headers = (Metadata)allArguments[1];
+ final AbstractSpan span = ContextManager.createExitSpan(cachedObjects.getRequestMethodName(), cachedObjects.getAuthority());
+ span.setComponent(ComponentsDefine.GRPC);
+ SpanLayer.asRPCFramework(span);
+ final ContextCarrier contextCarrier = new ContextCarrier();
+ ContextManager.inject(contextCarrier);
+
+ CarrierItem contextItem = contextCarrier.items();
+ while (contextItem.hasNext()) {
+ contextItem = contextItem.next();
+ Metadata.Key headerKey = Metadata.Key.of(contextItem.getHeadKey(), Metadata.ASCII_STRING_MARSHALLER);
+ headers.put(headerKey, contextItem.getHeadValue());
+ }
+
+ GRPCDynamicFields listenerCachedObject = new GRPCDynamicFields();
+ listenerCachedObject.setSnapshot(ContextManager.capture());
+ listenerCachedObject.setDescriptor(cachedObjects.getDescriptor());
+ ((EnhancedInstance)allArguments[0]).setSkyWalkingDynamicField(listenerCachedObject);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+
+ if (((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getMethodType() != MethodDescriptor.MethodType.UNARY) {
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..d075179c8d2864a840541c457db41096fe78e936
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.internal.ManagedChannelImpl;
+import java.lang.reflect.Method;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+/**
+ * {@link ManagedChannelInterceptor} record the IP address of the GRPC server into {@link GRPCDynamicFields} for build
+ * span.
+ *
+ * @author zhangxin
+ */
+public class ManagedChannelInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)((EnhancedInstance)ret).getSkyWalkingDynamicField();
+ cachedObjects.setAuthority(((ManagedChannelImpl)((Object)objInst)).authority());
+ return ret;
+ }
+
+ @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf13514f1d37b61186e2591d4ae365b8009f277c
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.ServerCall;
+import java.lang.reflect.Method;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+/**
+ * {@link ServerCallHandlerInterceptor} record the {@link Metadata} argument into {@link GRPCDynamicFields} for
+ * propagate {@link org.skywalking.apm.agent.core.context.ContextCarrier} and also record the {@link
+ * io.grpc.MethodDescriptor} into {@link GRPCDynamicFields} for building span.
+ *
+ * @author zhangxin
+ */
+public class ServerCallHandlerInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ GRPCDynamicFields cachedObjects = new GRPCDynamicFields();
+ cachedObjects.setMetadata((Metadata)allArguments[1]);
+ cachedObjects.setDescriptor(((ServerCall)allArguments[0]).getMethodDescriptor());
+ ((EnhancedInstance)ret).setSkyWalkingDynamicField(cachedObjects);
+ return ret;
+ }
+
+ @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..ab64ceed6170f7a56351e38a732ca1f2935c60e9
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY;
+
+/**
+ * {@link ServerCallOnCancelInterceptor} stop the active span when the call cancelled.
+ *
+ * @author zhangxin
+ */
+public class ServerCallOnCancelInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ AbstractSpan abstractSpan = ContextManager.activeSpan();
+ abstractSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount()));
+
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd451c852d64f9f7025e1e734f17f057a3aa7d74
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY;
+
+/**
+ * {@link ServerCallOnCloseInterceptor} stop the active span when the call end.
+ *
+ * @author zhangxin
+ */
+public class ServerCallOnCloseInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ AbstractSpan abstractSpan = ContextManager.activeSpan();
+ abstractSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount()));
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1e51aa76f7a93d7778b7cb55b2c6a9231d8accaa
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_OPERATION_NAME_SUFFIX;
+
+/**
+ * {@link ServerCallOnMessageInterceptor} create a local span when the server stream receive a message that send by the
+ * client.
+ *
+ * @author zhangxin
+ */
+public class ServerCallOnMessageInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_OPERATION_NAME_SUFFIX);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ ContextManager.stopSpan();
+
+ // record the call count of onNext method
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ cachedObjects.incrementOnNextCount();
+
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..90d571579a5d0e9362c70865f4761e8a4b9802da
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import org.skywalking.apm.agent.core.context.CarrierItem;
+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;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+import org.skywalking.apm.util.StringUtil;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX;
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.BLOCK_CALL_OPERATION_NAME_SUFFIX;
+
+/**
+ * {@link ServerCallOnReadyInterceptor} create a entry span when the server side is ready for receive the message from
+ * the client side.
+ *
+ * @author zhangxin
+ */
+public class ServerCallOnReadyInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ Metadata headers = cachedObjects.getMetadata();
+ Map headerMap = new HashMap();
+ for (String key : headers.keys()) {
+ if (!key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
+ String value = headers.get(Metadata.Key.of(key, Metadata.ASCII_STRING_MARSHALLER));
+ headerMap.put(key, value);
+ }
+ }
+
+ ContextCarrier contextCarrier = new ContextCarrier();
+ CarrierItem next = contextCarrier.items();
+ while (next.hasNext()) {
+ next = next.next();
+ String contextValue = headerMap.get(next.getHeadKey());
+ if (!StringUtil.isEmpty(contextValue)) {
+ next.setHeadValue(contextValue);
+ }
+ }
+
+ final AbstractSpan span = ContextManager.createEntrySpan(cachedObjects.getRequestMethodName() + (cachedObjects.getMethodType() != MethodDescriptor.MethodType.UNARY ? STREAM_CALL_OPERATION_NAME_SUFFIX : BLOCK_CALL_OPERATION_NAME_SUFFIX), contextCarrier);
+ span.setComponent(ComponentsDefine.GRPC);
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ return ret;
+ }
+
+ @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..26be1d525adb37a9327f4204aa3fbd8d1bdd5c1f
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.Status;
+import java.lang.reflect.Method;
+import org.skywalking.apm.agent.core.context.ContextManager;
+import org.skywalking.apm.agent.core.context.tag.Tags;
+import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY;
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX;
+
+/**
+ * {@link StreamClientOnCloseInterceptor} stop the active span when the call end.
+ *
+ * @author zhangxin
+ */
+public class StreamClientOnCloseInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ Status status = (Status)allArguments[0];
+ if (status.getCode() == Status.Code.UNAVAILABLE) {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_CALL_OPERATION_NAME_SUFFIX);
+ span.setComponent(ComponentsDefine.GRPC);
+ span.setLayer(SpanLayer.RPC_FRAMEWORK);
+ ContextManager.continued(cachedObjects.getSnapshot());
+ }
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ AbstractSpan activeSpan = ContextManager.activeSpan();
+ activeSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount()));
+
+ Status status = (Status)allArguments[0];
+ if (status != Status.OK) {
+ activeSpan.errorOccurred().log(status.asRuntimeException((Metadata)allArguments[1]));
+ Tags.STATUS_CODE.set(activeSpan, status.getCode().toString());
+ }
+
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..f856eaa7438b3d71b92f15579a5b712e8c1335da
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.context.trace.SpanLayer;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX;
+
+/**
+ * {@link ServerCallOnReadyInterceptor} create a local span when the client side is ready for send the message to the
+ * server side.
+ *
+ * @author zhangxin
+ */
+public class StreamClientOnReadyInterceptor implements InstanceMethodsAroundInterceptor {
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+ GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_CALL_OPERATION_NAME_SUFFIX);
+ span.setComponent(ComponentsDefine.GRPC);
+ span.setLayer(SpanLayer.RPC_FRAMEWORK);
+
+ ContextManager.continued(cachedObjects.getSnapshot());
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ return ret;
+ }
+
+ @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+ Class>[] argumentsTypes, Throwable t) {
+ ContextManager.activeSpan().errorOccurred().log(t);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..efc04a11685d63e5f917aaebaf5818ceb020797d
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.Status;
+import java.lang.reflect.Method;
+import org.skywalking.apm.agent.core.context.ContextManager;
+import org.skywalking.apm.agent.core.context.tag.Tags;
+import org.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+
+/**
+ * {@link UnaryClientOnCloseInterceptor} stop the active span when the call end.
+ *
+ * @author zhangxin
+ */
+public class UnaryClientOnCloseInterceptor implements InstanceMethodsAroundInterceptor {
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ MethodInterceptResult result) throws Throwable {
+
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class>[] argumentsTypes,
+ Object ret) throws Throwable {
+ AbstractSpan activeSpan = ContextManager.activeSpan();
+ Status status = (Status)allArguments[0];
+
+ if (status != Status.OK) {
+ activeSpan.errorOccurred().log(status.asRuntimeException((Metadata)allArguments[1]));
+ Tags.STATUS_CODE.set(activeSpan, status.getCode().toString());
+ }
+
+ 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-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..02d0a8ffa622199fe7dd9ebcd96798d2b79bc06d
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link ClientCallInstrumentation} presents that skywalking intercept the start
method in
+ * io.grpc.internal.ClientCallImpl
class by org.skywalking.apm.plugin.grpc.v1.ClientCallStartInterceptor
+ * and the constructor in io.grpc.internal.ClientCallImpl
by org.skywalking.apm.plugin.grpc.v1.ClientCallIConstructorInterceptor
+ *
+ * @author zhangxin
+ */
+public class ClientCallInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.internal.ClientCallImpl";
+ private static final String ENHANCE_METHOD = "start";
+ public static final String CONSTRUCTOR_CLASS = "org.skywalking.apm.plugin.grpc.v1.ClientCallIConstructorInterceptor";
+ public static final String START_METHOD_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ClientCallStartInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[] {
+ new ConstructorInterceptPoint() {
+ @Override public ElementMatcher getConstructorMatcher() {
+ return any();
+ }
+
+ @Override public String getConstructorInterceptor() {
+ return CONSTRUCTOR_CLASS;
+ }
+ }
+ };
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ENHANCE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return START_METHOD_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return true;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java
new file mode 100644
index 0000000000000000000000000000000000000000..d74c6b711024aba5e6ef121434f89e94d996d3c2
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+/**
+ * GRPC Plugin constants variables.
+ *
+ * @author zhangxin
+ */
+public final class Constants {
+
+ public static final String STREAM_OPERATION_NAME_SUFFIX = "/ResponseStreamObserver/OnNext";
+
+ public static final String ON_NEXT_COUNT_TAG_KEY = "onNext.count";
+
+ public static final String STREAM_CALL_OPERATION_NAME_SUFFIX = "/StreamCall";
+
+ public static final String BLOCK_CALL_OPERATION_NAME_SUFFIX = "/BlockCall";
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..28a6b1a8bc08c19ab86923281f5523edc7c76f1c
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link ManagedChannelInstrumentation} presents that skywalking intercept the newCall
method in
+ * io.grpc.internal.ManagedChannelImpl
class by org.skywalking.apm.plugin.grpc.v1.ManagedChannelInterceptor
+ *
+ * @author zhangxin
+ */
+public class ManagedChannelInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.internal.ManagedChannelImpl";
+ private static final String ENHANCE_METHOD = "newCall";
+ public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ManagedChannelInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ENHANCE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bfddefa4bdd28b1104e39c31e3f7633f085bd54
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the onReady
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor
, the onHalfClose
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor
and the onMessage
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor
in
+ * io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener
class
+ *
+ * @author zhangxin
+ */
+public class StreamObserverToCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter";
+ public static final String ON_READY_METHOD = "onReady";
+ public static final String ON_READY_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.StreamClientOnReadyInterceptor";
+ public static final String ON_CLASS_METHOD = "onClose";
+ public static final String ON_CLOSE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.StreamClientOnCloseInterceptor";
+ public static final String ON_MESSAGE_METHOD = "onMessage";
+ public static final String ON_MESSAGE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ClientCallOnNextInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_READY_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_READY_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_CLASS_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_CLOSE_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_MESSAGE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_MESSAGE_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..5840a6b0d1c1247178c637c25e11bbf29cb0e9e8
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the startCall
+ * method in io.grpc.stub.ServerCalls$UnaryServerCallHandler
class by
+ * org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor
+ *
+ * @author zhangxin
+ */
+public class StreamingServerCallHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$UnaryServerCallHandler";
+ private static final String ENHANCE_METHOD = "startCall";
+ public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ENHANCE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..d79e15bda9dac884dd18dd579482cb3ae552b7c7
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the onReady
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor
, the onHalfClose
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor
, the onMessage
method by
+ * org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor
and the onCancel
method by
+ * org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor
in
+ * io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener
class
+ *
+ * @author zhangxin
+ */
+public class StreamingServerCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener";
+ public static final String ON_READY_METHOD = "onReady";
+ public static final String ON_READ_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor";
+ public static final String ON_HALF_CLOSE_METHOD = "onHalfClose";
+ public static final String ON_HALF_CLOSE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor";
+ public static final String ON_MESSAGE_METHOD = "onMessage";
+ public static final String ON_MESSAGE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor";
+ public static final String ON_CANCEL_METHOD = "onCancel";
+ public static final String ON_CANCEL_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_READY_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_READ_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_HALF_CLOSE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_HALF_CLOSE_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_MESSAGE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_MESSAGE_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_CANCEL_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_CANCEL_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..42b4814a54bb489bd4daf1bd85732537cbd9c5bd
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link UnaryClientCallListenerInstrumentation} indicates that skywalking enhance the onClose
method in
+ * io.grpc.stub.ClientCalls$UnaryStreamToFuture
class by org.skywalking.apm.plugin.grpc.v1.UnaryClientOnCloseInterceptor
+ *
+ * @author zhangxin
+ */
+public class UnaryClientCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls$UnaryStreamToFuture";
+ private static final String ENHANCE_METHOD = "onClose";
+ public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.UnaryClientOnCloseInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ENHANCE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..76abdc6e5f6b7a925b0d89f7eb109d681c118990
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link UnaryServerCallHandlerInstrumentation} indicates that skywalking enhance the startCall
in
+ * io.grpc.stub.ServerCalls$StreamingServerCallHandler
class by org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor
.
+ *
+ * @author zhangxin
+ */
+public class UnaryServerCallHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$StreamingServerCallHandler";
+ private static final String ENHANCE_METHOD = "startCall";
+ public static final String INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ENHANCE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java
new file mode 100644
index 0000000000000000000000000000000000000000..957480da8ae912e3214f335835d26332db3f5210
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the onReady
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor
, the onHalfClose
method
+ * by org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor
, the onMessage
method by
+ * org.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor
and the onCancel
method by
+ * org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor
in
+ * io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener
class
+ *
+ * @author zhangxin
+ */
+public class UnaryServerCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+ private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener";
+ public static final String ON_CLOSE_METHOD = "onHalfClose";
+ public static final String ON_CLOSE_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor";
+ public static final String ON_READY_METHOD = "onReady";
+ public static final String ON_READY_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor";
+ public static final String ON_CANCEL_METHOD = "onCancel";
+ public static final String ON_CANCEL_INTERCEPT_CLASS = "org.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor";
+
+ @Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+ return new InstanceMethodsInterceptPoint[] {
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_CLOSE_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_CLOSE_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_READY_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_READY_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ },
+ new InstanceMethodsInterceptPoint() {
+ @Override public ElementMatcher getMethodsMatcher() {
+ return named(ON_CANCEL_METHOD);
+ }
+
+ @Override public String getMethodsInterceptor() {
+ return ON_CANCEL_INTERCEPT_CLASS;
+ }
+
+ @Override public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override protected ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java
new file mode 100644
index 0000000000000000000000000000000000000000..03ae66a1e364517ee5236679242d2d2eb91b4e10
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.vo;
+
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import org.skywalking.apm.agent.core.context.ContextSnapshot;
+
+/**
+ * {@link GRPCDynamicFields} contain the require information of span.
+ *
+ * @author zhangxin
+ */
+public class GRPCDynamicFields {
+ private ServiceDescriptor descriptor;
+ private Metadata metadata;
+ private String authority;
+ private ContextSnapshot snapshot;
+ private int onNextCount;
+
+ public Metadata getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(Metadata metadata) {
+ this.metadata = metadata;
+ }
+
+ public String getAuthority() {
+ return authority;
+ }
+
+ public void setAuthority(String authority) {
+ this.authority = authority;
+ }
+
+ public String getRequestMethodName() {
+ return descriptor.getServiceName();
+ }
+
+ public void setDescriptor(MethodDescriptor methodDescriptor) {
+ this.descriptor = new ServiceDescriptor(methodDescriptor);
+ }
+
+ public void setDescriptor(ServiceDescriptor methodDescriptor) {
+ this.descriptor = methodDescriptor;
+ }
+
+ public ServiceDescriptor getDescriptor() {
+ return descriptor;
+ }
+
+ public ContextSnapshot getSnapshot() {
+ return snapshot;
+ }
+
+ public void setSnapshot(ContextSnapshot snapshot) {
+ this.snapshot = snapshot;
+ }
+
+ public MethodDescriptor.MethodType getMethodType() {
+ return descriptor.getMethodType();
+ }
+
+ public void incrementOnNextCount() {
+ onNextCount++;
+ }
+
+ public int getOnNextCount() {
+ return onNextCount;
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java
new file mode 100644
index 0000000000000000000000000000000000000000..1409a314473b15c0864f219a315ca3cea95d13fd
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1.vo;
+
+import io.grpc.MethodDescriptor;
+
+/**
+ * {@link ServiceDescriptor} indicate the descriptor of an grpc service. it contains {@link #methodType} and
+ * {@link #serviceName}.
+ *
+ * @author zhangxin
+ */
+public class ServiceDescriptor {
+ private MethodDescriptor.MethodType methodType;
+ private String serviceName;
+
+ public ServiceDescriptor(MethodDescriptor descriptor) {
+ this.methodType = descriptor.getType();
+ String fullMethodName = descriptor.getFullMethodName();
+ this.serviceName = formatServiceName(fullMethodName) + "." + formatMethodName(fullMethodName);
+ }
+
+ private String formatServiceName(String requestMethodName) {
+ int splitIndex = requestMethodName.lastIndexOf("/");
+ return requestMethodName.substring(0, splitIndex);
+ }
+
+ private String formatMethodName(String requestMethodName) {
+ int splitIndex = requestMethodName.lastIndexOf("/");
+ String methodName = requestMethodName.substring(splitIndex + 1);
+ methodName = methodName.substring(0, 1).toLowerCase() + methodName.substring(1);
+ return methodName;
+ }
+
+ public MethodDescriptor.MethodType getMethodType() {
+ return methodType;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000000000000000000000000000000000000..6dbb61d92e165f0178599c9b7efbc277b5856d7d
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,8 @@
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.ClientCallInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.UnaryClientCallListenerInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.UnaryServerCallListenerInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.UnaryServerCallHandlerInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.ManagedChannelInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.StreamingServerCallHandlerInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.StreamingServerCallListenerInstrumentation
+grpc-1.x=org.skywalking.apm.plugin.grpc.v1.define.StreamObserverToCallListenerInstrumentation
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d71081f887cab5b95d1c261b923813e37515c134
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.MethodDescriptor;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(MethodDescriptor.class)
+public class ClientCallIConstructorInterceptorTest {
+
+ private ClientCallIConstructorInterceptor constructorInterceptor;
+
+ @Mock
+ private EnhancedInstance enhancedInstance;
+
+ private Object[] arguments;
+
+ @Before
+ public void setUp() {
+ constructorInterceptor = new ClientCallIConstructorInterceptor();
+
+ MethodDescriptor methodDescriptor = mock(MethodDescriptor.class);
+ when(methodDescriptor.getType()).thenReturn(MethodDescriptor.MethodType.UNARY);
+ when(methodDescriptor.getFullMethodName()).thenReturn("test/testMethod");
+
+ arguments = new Object[] {methodDescriptor};
+ }
+
+ @Test
+ public void testOnConstructor() {
+ constructorInterceptor.onConstruct(enhancedInstance, arguments);
+ verify(enhancedInstance, times(1)).setSkyWalkingDynamicField(Matchers.any());
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..7524016a6c1018969002c48d8aba810dadfc9fa9
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.test.helper.SegmentHelper;
+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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class ClientCallOnNextInterceptorTest {
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+ @Mock
+ private EnhancedInstance clientCall;
+
+ @Mock
+ private GRPCDynamicFields cachedObjects;
+
+ private ClientCallOnNextInterceptor callOnNextInterceptor;
+
+ @Before
+ public void setUp() {
+ when(cachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
+ when(clientCall.getSkyWalkingDynamicField()).thenReturn(cachedObjects);
+
+ callOnNextInterceptor = new ClientCallOnNextInterceptor();
+ }
+
+ @Test
+ public void testCallOnNext() throws Throwable {
+ callOnNextInterceptor.beforeMethod(clientCall, null, null, null, null);
+ callOnNextInterceptor.afterMethod(clientCall, null, null, null, null);
+
+ verify(cachedObjects, times(1)).incrementOnNextCount();
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
+ AbstractTracingSpan span = SegmentHelper.getSpans(traceSegment).get(0);
+ assertThat(span.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
+ assertThat(span.isEntry(), is(false));
+ assertThat(span.isExit(), is(false));
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd04dc72442da6a73805f987f65b070ee606824e
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import io.grpc.Status;
+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.SpanLayer;
+import org.skywalking.apm.agent.core.context.trace.TraceSegment;
+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.SpanAssert;
+import org.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class ClientCallStartInterceptorTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+ private ClientCallStartInterceptor clientCallStartInterceptor;
+ private UnaryClientOnCloseInterceptor unaryClientOnCloseInterceptor;
+
+ @Mock
+ private EnhancedInstance clientCallImpl;
+
+ @Mock
+ private EnhancedInstance clientCallListener;
+
+ @Mock
+ private GRPCDynamicFields unaryCachedObjects;
+
+ @Mock
+ private GRPCDynamicFields streamCachedObjects;
+
+ private Status exceptionStatus = Status.NOT_FOUND.withCause(new RuntimeException());
+
+ private Object[] arguments;
+ private Class[] argumentTypes;
+
+ @Before
+ public void setUp() {
+ when(unaryCachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
+ when(unaryCachedObjects.getAuthority()).thenReturn("localhost:500051");
+ when(unaryCachedObjects.getMethodType()).thenReturn(MethodDescriptor.MethodType.UNARY);
+
+ when(streamCachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
+ when(streamCachedObjects.getAuthority()).thenReturn("localhost:500051");
+ when(streamCachedObjects.getMethodType()).thenReturn(MethodDescriptor.MethodType.SERVER_STREAMING);
+
+ arguments = new Object[] {clientCallListener, new Metadata()};
+ argumentTypes = new Class[] {clientCallListener.getClass(), Metadata.class};
+
+ clientCallStartInterceptor = new ClientCallStartInterceptor();
+ unaryClientOnCloseInterceptor = new UnaryClientOnCloseInterceptor();
+ }
+
+ @Test
+ public void testNormalUnaryCallStart() throws Throwable {
+ when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(unaryCachedObjects);
+
+ clientCallStartInterceptor.beforeMethod(clientCallImpl, null, arguments, argumentTypes, null);
+ clientCallStartInterceptor.afterMethod(clientCallImpl, null, arguments, argumentTypes, null);
+ unaryClientOnCloseInterceptor.afterMethod(null, null, new Object[] {Status.OK}, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
+ AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0);
+ SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC);
+ SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK);
+ SpanAssert.assertOccurException(abstractTracingSpan, false);
+ }
+
+ @Test
+ public void testUnaryCallStartWithException() throws Throwable {
+ when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(unaryCachedObjects);
+
+ clientCallStartInterceptor.beforeMethod(clientCallImpl, null, arguments, argumentTypes, null);
+ clientCallStartInterceptor.afterMethod(clientCallImpl, null, arguments, argumentTypes, null);
+ unaryClientOnCloseInterceptor.afterMethod(null, null, new Object[] {exceptionStatus}, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
+ AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0);
+ SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC);
+ SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK);
+ SpanAssert.assertOccurException(abstractTracingSpan, true);
+ SpanAssert.assertException(SpanHelper.getLogs(abstractTracingSpan).get(0), RuntimeException.class);
+ }
+
+ @Test
+ public void testNormalStreamCallStart() throws Throwable {
+ when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(streamCachedObjects);
+
+ clientCallStartInterceptor.beforeMethod(clientCallImpl, null, arguments, argumentTypes, null);
+ clientCallStartInterceptor.afterMethod(clientCallImpl, null, arguments, argumentTypes, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
+ AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0);
+ SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC);
+ SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK);
+ SpanAssert.assertOccurException(abstractTracingSpan, false);
+ }
+
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..de82469d1c9eafce92d1c7a5f87aec9b808257f9
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+import io.grpc.ServerCall;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+public class ServerCallHandlerInterceptorTest {
+ @Mock
+ private EnhancedInstance enhancedInstance;
+
+ private ServerCallHandlerInterceptor callHandlerInterceptor;
+
+ @Mock
+ private ServerCall serverCall;
+ @Mock
+ private MethodDescriptor methodDescriptor;
+
+ private Metadata metadata;
+
+ private Object[] arguments;
+ private Class[] argumentTypes;
+
+ @Before
+ public void setUp() {
+ when(methodDescriptor.getFullMethodName()).thenReturn("org.skywalking.test.GreetService/SayHello");
+ when(serverCall.getMethodDescriptor()).thenReturn(methodDescriptor);
+
+ callHandlerInterceptor = new ServerCallHandlerInterceptor();
+ metadata = new Metadata();
+ arguments = new Object[] {serverCall, metadata};
+ argumentTypes = new Class[] {serverCall.getClass(), metadata.getClass()};
+ }
+
+ @Test
+ public void testSetCachedObjects() throws Throwable {
+ callHandlerInterceptor.afterMethod(null, null, arguments, argumentTypes, enhancedInstance);
+ verify(enhancedInstance, times(1)).setSkyWalkingDynamicField(Matchers.any());
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..71d36d228f97b28359367e46043eb0ca0750fbea
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+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.plugin.interceptor.enhance.EnhancedInstance;
+import org.skywalking.apm.agent.test.helper.SegmentHelper;
+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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class ServerCallOnMessageInterceptorTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+ @Mock
+ private EnhancedInstance clientCall;
+
+ @Mock
+ private GRPCDynamicFields cachedObjects;
+
+ private ServerCallOnMessageInterceptor serverCallOnMessageInterceptor;
+
+ @Before
+ public void setUp() {
+ when(cachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
+ when(clientCall.getSkyWalkingDynamicField()).thenReturn(cachedObjects);
+
+ serverCallOnMessageInterceptor = new ServerCallOnMessageInterceptor();
+ }
+
+ @Test
+ public void testCallOnNext() throws Throwable {
+ serverCallOnMessageInterceptor.beforeMethod(clientCall, null, null, null, null);
+ serverCallOnMessageInterceptor.afterMethod(clientCall, null, null, null, null);
+
+ verify(cachedObjects, times(1)).incrementOnNextCount();
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+ assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
+ AbstractTracingSpan span = SegmentHelper.getSpans(traceSegment).get(0);
+ assertThat(span.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
+ assertThat(span.isEntry(), is(false));
+ assertThat(span.isExit(), is(false));
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bf3e189da2c683bfb52df9f48fb4b2c46978442
--- /dev/null
+++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2017, OpenSkywalking Organization All rights reserved.
+ *
+ * Licensed 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.
+ *
+ * Project repository: https://github.com/OpenSkywalking/skywalking
+ */
+
+package org.skywalking.apm.plugin.grpc.v1;
+
+import io.grpc.Metadata;
+import io.grpc.MethodDescriptor;
+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.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.SegmentRefAssert;
+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.plugin.grpc.v1.vo.GRPCDynamicFields;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class ServerCallOnReadyInterceptorTest {
+
+ @SegmentStoragePoint
+ private SegmentStorage segmentStorage;
+
+ @Rule
+ public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+ @Mock
+ private EnhancedInstance enhancedInstance;
+
+ private GRPCDynamicFields cachedObjects;
+
+ @Mock
+ private MethodDescriptor.Marshaller requestMarshaller;
+ @Mock
+ private MethodDescriptor.Marshaller responseMarshaller;
+
+ private ServerCallOnReadyInterceptor serverCallOnReadyInterceptor;
+
+ private ServerCallOnCloseInterceptor serverCallOnCloseInterceptor;
+
+ private ServerCallOnMessageInterceptor serverCallOnMessageInterceptor;
+
+ @Before
+ public void setUp() {
+ cachedObjects = new GRPCDynamicFields();
+ cachedObjects.setDescriptor(MethodDescriptor.create(MethodDescriptor.MethodType.SERVER_STREAMING, "org.skywalking.test.grpc.GreetService/SayHello", requestMarshaller, responseMarshaller));
+ when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(cachedObjects);
+
+ serverCallOnReadyInterceptor = new ServerCallOnReadyInterceptor();
+ serverCallOnCloseInterceptor = new ServerCallOnCloseInterceptor();
+ serverCallOnMessageInterceptor = new ServerCallOnMessageInterceptor();
+ }
+
+ @Test
+ public void testOnReadyWithoutContextCarrier() throws Throwable {
+ cachedObjects.setMetadata(new Metadata());
+ serverCallOnReadyInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
+ serverCallOnMessageInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
+ serverCallOnMessageInterceptor.afterMethod(enhancedInstance, null, null, null, null);
+ serverCallOnCloseInterceptor.afterMethod(enhancedInstance, null, null, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+
+ assertThat(segment.getRefs() == null, is(true));
+
+ assertThat(SegmentHelper.getSpans(segment).size(), is(2));
+ AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(segment).get(0);
+ assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
+
+ abstractTracingSpan = SegmentHelper.getSpans(segment).get(1);
+ assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/StreamCall"));
+ assertThat(abstractTracingSpan.isEntry(), is(true));
+ assertThat(SpanHelper.getTags(abstractTracingSpan).size(), is(1));
+ assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getKey(), is("onNext.count"));
+ assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getValue(), is("1"));
+ }
+
+ @Test
+ public void testOnReadyWithContextCarrier() throws Throwable {
+ Metadata metadata = new Metadata();
+ metadata.put(Metadata.Key.of("sw3", Metadata.ASCII_STRING_MARSHALLER), "1.234.111|3|1|1|#192.168.1.100:50051|#/portal/|#/testEntrySpan|#AQA*#AQA*Et0We0tQNQA*");
+ cachedObjects.setMetadata(metadata);
+ serverCallOnReadyInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
+ serverCallOnMessageInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
+ serverCallOnMessageInterceptor.afterMethod(enhancedInstance, null, null, null, null);
+ serverCallOnCloseInterceptor.afterMethod(enhancedInstance, null, null, null, null);
+
+ assertThat(segmentStorage.getTraceSegments().size(), is(1));
+ TraceSegment segment = segmentStorage.getTraceSegments().get(0);
+
+ assertThat(segment.getRefs() != null, is(true));
+ SegmentRefAssert.assertPeerHost(segment.getRefs().get(0), "192.168.1.100:50051");
+ SegmentRefAssert.assertEntryApplicationInstanceId(segment.getRefs().get(0), 1);
+ SegmentRefAssert.assertSpanId(segment.getRefs().get(0), 3);
+ SegmentRefAssert.assertSegmentId(segment.getRefs().get(0), "1.234.111");
+
+ assertThat(SegmentHelper.getSpans(segment).size(), is(2));
+ AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(segment).get(0);
+ assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
+
+ abstractTracingSpan = SegmentHelper.getSpans(segment).get(1);
+ assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/StreamCall"));
+ assertThat(abstractTracingSpan.isEntry(), is(true));
+ assertThat(SpanHelper.getTags(abstractTracingSpan).size(), is(1));
+ assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getKey(), is("onNext.count"));
+ assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getValue(), is("1"));
+ }
+}
diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml
index 84ccc21931d6400f536ad2faf3b564f42d9bfb8a..e986ddf28690ca6302ffd300f77b639630ed7e99 100644
--- a/apm-sniffer/apm-sdk-plugin/pom.xml
+++ b/apm-sniffer/apm-sdk-plugin/pom.xml
@@ -46,6 +46,7 @@
jetty-plugin
spymemcached-2.x-plugin
sharding-jdbc-1.5.x-plugin
+ grpc-1.x-plugin
pom