From c17866cf8b923ace345a833327d81d4717400f44 Mon Sep 17 00:00:00 2001 From: ascrutae Date: Mon, 16 Oct 2017 21:33:54 +0800 Subject: [PATCH] support grpc plugin --- .../trace/component/ComponentsDefine.java | 5 +- apm-sniffer/apm-agent/pom.xml | 5 + .../apm-sdk-plugin/grpc-1.x-plugin/pom.xml | 59 +++++++ .../v1/ClientCallIConstructorInterceptor.java | 40 +++++ .../grpc/v1/ClientCallOnNextInterceptor.java | 61 ++++++++ .../grpc/v1/ClientCallStartInterceptor.java | 82 ++++++++++ .../grpc/v1/ManagedChannelInterceptor.java | 51 ++++++ .../grpc/v1/ServerCallHandlerInterceptor.java | 57 +++++++ .../v1/ServerCallOnCancelInterceptor.java | 57 +++++++ .../grpc/v1/ServerCallOnCloseInterceptor.java | 57 +++++++ .../v1/ServerCallOnMessageInterceptor.java | 61 ++++++++ .../grpc/v1/ServerCallOnReadyInterceptor.java | 85 ++++++++++ .../v1/StreamClientOnCloseInterceptor.java | 78 ++++++++++ .../v1/StreamClientOnReadyInterceptor.java | 62 ++++++++ .../v1/UnaryClientOnCloseInterceptor.java | 62 ++++++++ .../v1/define/ClientCallInstrumentation.java | 80 ++++++++++ .../apm/plugin/grpc/v1/define/Constants.java | 36 +++++ .../define/ManagedChannelInstrumentation.java | 67 ++++++++ ...ObserverToCallListenerInstrumentation.java | 100 ++++++++++++ ...amingServerCallHandlerInstrumentation.java | 68 ++++++++ ...mingServerCallListenerInstrumentation.java | 116 ++++++++++++++ ...naryClientCallListenerInstrumentation.java | 67 ++++++++ ...UnaryServerCallHandlerInstrumentation.java | 67 ++++++++ ...naryServerCallListenerInstrumentation.java | 101 ++++++++++++ .../plugin/grpc/v1/vo/GRPCDynamicFields.java | 88 +++++++++++ .../plugin/grpc/v1/vo/ServiceDescriptor.java | 58 +++++++ .../src/main/resources/skywalking-plugin.def | 8 + ...ClientCallIConstructorInterceptorTest.java | 64 ++++++++ .../v1/ClientCallOnNextInterceptorTest.java | 84 ++++++++++ .../v1/ClientCallStartInterceptorTest.java | 147 ++++++++++++++++++ .../v1/ServerCallHandlerInterceptorTest.java | 69 ++++++++ .../ServerCallOnMessageInterceptorTest.java | 85 ++++++++++ .../v1/ServerCallOnReadyInterceptorTest.java | 138 ++++++++++++++++ apm-sniffer/apm-sdk-plugin/pom.xml | 1 + 34 files changed, 2265 insertions(+), 1 deletion(-) create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ManagedChannelInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCancelInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnCloseInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnCloseInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/StreamClientOnReadyInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/UnaryClientOnCloseInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ClientCallInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/Constants.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/ManagedChannelInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamObserverToCallListenerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallHandlerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/StreamingServerCallListenerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryClientCallListenerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallHandlerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/define/UnaryServerCallListenerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/GRPCDynamicFields.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/skywalking/apm/plugin/grpc/v1/vo/ServiceDescriptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallIConstructorInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallOnNextInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ClientCallStartInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallHandlerInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnMessageInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/test/java/org/skywalking/apm/plugin/grpc/v1/ServerCallOnReadyInterceptorTest.java 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 0582108bf..0f45a0c88 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 8047e2161..411d68621 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 000000000..7b72913a8 --- /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 000000000..b6c85d1ce --- /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 000000000..a46de3c77 --- /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 000000000..9515364b3 --- /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 000000000..d075179c8 --- /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 000000000..cf13514f1 --- /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 000000000..ab64ceed6 --- /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 000000000..fd451c852 --- /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 000000000..1e51aa76f --- /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 000000000..90d571579 --- /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 000000000..26be1d525 --- /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 000000000..f856eaa74 --- /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 000000000..efc04a116 --- /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 000000000..02d0a8ffa --- /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 000000000..d74c6b711 --- /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 000000000..28a6b1a8b --- /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 000000000..8bfddefa4 --- /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 000000000..5840a6b0d --- /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 000000000..d79e15bda --- /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 000000000..42b4814a5 --- /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 000000000..76abdc6e5 --- /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 000000000..957480da8 --- /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 000000000..03ae66a1e --- /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 000000000..1409a3144 --- /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 000000000..6dbb61d92 --- /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 000000000..d71081f88 --- /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 000000000..7524016a6 --- /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 000000000..fd04dc724 --- /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 000000000..de82469d1 --- /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 000000000..71d36d228 --- /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 000000000..8bf3e189d --- /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 84ccc2193..e986ddf28 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 -- GitLab