From 97950807fafb503a0b083cd035f42e4f6e7c9ac5 Mon Sep 17 00:00:00 2001 From: Kanro Date: Thu, 30 Jan 2020 20:12:48 +0800 Subject: [PATCH] Enhance gRPC plugin (#4177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enhance gRPC plugin Co-authored-by: Kanro Co-authored-by: kezhenxu94 Co-authored-by: GuoDuanLZ <739537111@qq.com> Co-authored-by: 吴晟 Wu Sheng --- .../AsyncUnaryRequestCallCallInterceptor.java | 59 -- .../v1/BlockingCallClientInterceptor.java | 63 -- .../plugin/grpc/v1/CallServerInterceptor.java | 150 ---- .../apm/plugin/grpc/v1/Constants.java | 47 +- .../plugin/grpc/v1/GRPCClientInterceptor.java | 45 - .../grpc/v1/OperationNameFormatUtil.java | 2 +- .../grpc/v1/StreamCallClientInterceptor.java | 141 ---- .../{ => client}/AbstractStubInterceptor.java | 20 +- .../{ => client}/BlockingCallInterceptor.java | 27 +- .../ClientInterceptor.java} | 18 +- .../grpc/v1/client/TracingClientCall.java | 203 +++++ ...tractServerImplBuilderInstrumentation.java | 2 +- .../define/AbstractStubInstrumentation.java | 2 +- .../v1/define/ClientCallsInstrumentation.java | 30 +- .../AbstractServerImplBuilderInterceptor.java | 17 +- .../grpc/v1/server/ServerInterceptor.java | 58 ++ .../grpc/v1/server/TracingServerCall.java | 112 +++ .../v1/server/TracingServerCallListener.java | 104 +++ .../grpc-scenario/config/expectedData.yaml | 776 ++++++++++++------ .../grpc/controller/CaseController.java | 13 +- .../grpc/provider/ProviderConfiguration.java | 8 +- .../GreeterBlockingErrorServiceImpl.java | 31 + .../provider/service/GreeterServiceImpl.java | 1 + .../src/main/proto/GreetService.proto | 4 + 24 files changed, 1160 insertions(+), 773 deletions(-) delete mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AsyncUnaryRequestCallCallInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/BlockingCallClientInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallServerInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/GRPCClientInterceptor.java delete mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/StreamCallClientInterceptor.java rename apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/{ => client}/AbstractStubInterceptor.java (79%) rename apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/{ => client}/BlockingCallInterceptor.java (70%) rename apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/{CallClientInterceptor.java => client/ClientInterceptor.java} (60%) create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/TracingClientCall.java rename apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/{ => server}/AbstractServerImplBuilderInterceptor.java (76%) create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java create mode 100644 apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java create mode 100644 test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AsyncUnaryRequestCallCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AsyncUnaryRequestCallCallInterceptor.java deleted file mode 100644 index 9cd51d4bf..000000000 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AsyncUnaryRequestCallCallInterceptor.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.grpc.v1; - -import io.grpc.Channel; -import io.grpc.MethodDescriptor; -import java.lang.reflect.Method; -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; -import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; - -import static org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil.formatOperationName; - -/** - * @author zhang xin - */ -public class AsyncUnaryRequestCallCallInterceptor implements StaticMethodsAroundInterceptor { - @Override public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, - MethodInterceptResult result) { - CallClientInterceptor originClientCall = (CallClientInterceptor)allArguments[0]; - Channel channel = originClientCall.getChannel(); - MethodDescriptor methodDescriptor = originClientCall.getMethodDescriptor(); - - final AbstractSpan span = ContextManager.createExitSpan(formatOperationName(methodDescriptor), channel.authority()); - span.setComponent(ComponentsDefine.GRPC); - SpanLayer.asRPCFramework(span); - } - - @Override public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, - Object ret) { - ContextManager.stopSpan(); - return ret; - } - - @Override - public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, - Throwable t) { - ContextManager.activeSpan().errorOccurred().log(t); - } -} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/BlockingCallClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/BlockingCallClientInterceptor.java deleted file mode 100644 index 98f25de62..000000000 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/BlockingCallClientInterceptor.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.grpc.v1; - -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ForwardingClientCall; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; -import org.apache.skywalking.apm.agent.core.context.ContextCarrier; -import org.apache.skywalking.apm.agent.core.context.ContextManager; - -/** - * @author zhang xin - */ -public class BlockingCallClientInterceptor extends ForwardingClientCall.SimpleForwardingClientCall implements CallClientInterceptor { - - private final MethodDescriptor methodDescriptor; - private final Channel channel; - - public BlockingCallClientInterceptor(ClientCall delegate, MethodDescriptor method, Channel channel) { - super(delegate); - this.methodDescriptor = method; - this.channel = channel; - } - - @Override public void start(Listener responseListener, Metadata headers) { - 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()); - } - delegate().start(responseListener, headers); - } - - public MethodDescriptor getMethodDescriptor() { - return methodDescriptor; - } - - public Channel getChannel() { - return channel; - } -} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallServerInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallServerInterceptor.java deleted file mode 100644 index f8045c4a3..000000000 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallServerInterceptor.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.grpc.v1; - -import io.grpc.ForwardingServerCall; -import io.grpc.ForwardingServerCallListener; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.ServerCall; -import io.grpc.ServerCallHandler; -import io.grpc.ServerInterceptor; -import java.util.HashMap; -import java.util.Map; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; -import org.apache.skywalking.apm.agent.core.context.ContextCarrier; -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; -import org.apache.skywalking.apm.util.StringUtil; - -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.SERVER; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_REQUEST_OBSERVER_ON_COMPLETE_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_REQUEST_OBSERVER_ON_ERROR_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_REQUEST_OBSERVER_ON_NEXT_OPERATION_NAME; - -/** - * @author zhang xin - */ -public class CallServerInterceptor implements ServerInterceptor { - @Override - public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler handler) { - 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(OperationNameFormatUtil.formatOperationName(call.getMethodDescriptor()), contextCarrier); - span.setComponent(ComponentsDefine.GRPC); - SpanLayer.asRPCFramework(span); - try { - return new ServerCallListener(handler.startCall(new ForwardingServerCall.SimpleForwardingServerCall(call) { - @Override - public void sendHeaders(Metadata responseHeaders) { - delegate().sendHeaders(responseHeaders); - } - }, headers), call.getMethodDescriptor(), ContextManager.capture()); - } finally { - ContextManager.stopSpan(); - } - } - - public class ServerCallListener extends ForwardingServerCallListener.SimpleForwardingServerCallListener { - - private final ContextSnapshot contextSnapshot; - private final MethodDescriptor.MethodType methodType; - private final String operationPrefix; - - protected ServerCallListener(ServerCall.Listener delegate, MethodDescriptor descriptor, - ContextSnapshot contextSnapshot) { - super(delegate); - this.contextSnapshot = contextSnapshot; - this.methodType = descriptor.getType(); - this.operationPrefix = OperationNameFormatUtil.formatOperationName(descriptor) + SERVER; - } - - @Override public void onReady() { - delegate().onReady(); - } - - @Override public void onMessage(Object message) { - try { - ContextManager.createLocalSpan(operationPrefix + STREAM_REQUEST_OBSERVER_ON_NEXT_OPERATION_NAME); - ContextManager.continued(contextSnapshot); - delegate().onMessage(message); - } catch (Throwable t) { - ContextManager.activeSpan().errorOccurred().log(t); - } finally { - ContextManager.stopSpan(); - } - } - - @Override public void onComplete() { - if (methodType != MethodDescriptor.MethodType.UNARY) { - try { - ContextManager.createLocalSpan(operationPrefix + STREAM_REQUEST_OBSERVER_ON_COMPLETE_OPERATION_NAME); - ContextManager.continued(contextSnapshot); - delegate().onComplete(); - } catch (Throwable t) { - ContextManager.activeSpan().errorOccurred().log(t); - } finally { - ContextManager.stopSpan(); - } - } else { - delegate().onComplete(); - } - } - - @Override public void onCancel() { - if (methodType != MethodDescriptor.MethodType.UNARY) { - try { - ContextManager.createLocalSpan(operationPrefix + STREAM_REQUEST_OBSERVER_ON_ERROR_OPERATION_NAME); - ContextManager.continued(contextSnapshot); - delegate().onCancel(); - } catch (Throwable t) { - ContextManager.activeSpan().errorOccurred().log(t); - } finally { - ContextManager.stopSpan(); - } - } else { - delegate().onCancel(); - } - } - - @Override public void onHalfClose() { - delegate().onHalfClose(); - } - } - -} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/Constants.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/Constants.java index a03459079..f46ce28ac 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/Constants.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/Constants.java @@ -21,23 +21,52 @@ package org.apache.skywalking.apm.plugin.grpc.v1; /** * Constant variables * - * @author zhang xin + * @author zhang xin, wang zheng, kanro */ public class Constants { + + /** + * Mark the current application is the gRPC client in current tracing span. + */ public static final String CLIENT = "/client"; + /** + * Mark the current application is the gRPC server in current tracing span. + */ public static final String SERVER = "/server"; - public static final String STREAM_REQUEST_OBSERVER_ON_NEXT_OPERATION_NAME = "/RequestObserver/onNext"; + /** + * Operation name for request message received on server or sent on client. + * + * Spans of this operations just be create with request stream calls. + */ + public static final String REQUEST_ON_MESSAGE_OPERATION_NAME = "/Request/onMessage"; - public static final String STREAM_REQUEST_OBSERVER_ON_ERROR_OPERATION_NAME = "/RequestObserver/onError"; + /** + * Operation name for client has completed request sending, there are no more incoming request. + * + * It should happen with half close state usually. + */ + public static final String REQUEST_ON_COMPLETE_OPERATION_NAME = "/Request/onComplete"; - public static final String STREAM_REQUEST_OBSERVER_ON_COMPLETE_OPERATION_NAME = "/RequestObserver/onComplete"; + /** + * Operation name for client has cancelled the call. + */ + public static final String REQUEST_ON_CANCEL_OPERATION_NAME = "/Request/onCancel"; - public static final String STREAM_RESPONSE_OBSERVER_ON_NEXT_OPERATION_NAME = "/ResponseObserver/onNext"; + /** + * Operation name for response message received on client or sent on server. + * + * Spans of this operations just be create with response stream calls. + */ + public static final String RESPONSE_ON_MESSAGE_OPERATION_NAME = "/Response/onMessage"; - public static final String STREAM_RESPONSE_OBSERVER_ON_ERROR_OPERATION_NAME = "/ResponseObserver/onError"; + /** + * Operation name for call closed with status and trailers. + * + * Exceptions will be logs here. + */ + public static final String RESPONSE_ON_CLOSE_OPERATION_NAME = "/Response/onClose"; - public static final String STREAM_RESPONSE_OBSERVER_ON_COMPLETE_OPERATION_NAME = "/ResponseObserver/onComplete"; - -} + public static final String BLOCKING_CALL_EXIT_SPAN = "SW_GRPC_BLOCKING_CALL_EXIT_SPAN"; +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/GRPCClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/GRPCClientInterceptor.java deleted file mode 100644 index 29e0f047a..000000000 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/GRPCClientInterceptor.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.grpc.v1; - -import io.grpc.CallOptions; -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ClientInterceptor; -import io.grpc.MethodDescriptor; - -/** - * {@link GRPCClientInterceptor} determines the returned Interceptor based on the method type. If the method type is - * UNARY, {@link GRPCClientInterceptor} returns BlockingCallClientInterceptor, or it returns - * StreamCallClientInterceptor. - * - * @author zhang xin - */ -public class GRPCClientInterceptor implements ClientInterceptor { - - @Override - public ClientCall interceptCall(MethodDescriptor method, - CallOptions callOptions, Channel channel) { - if (method.getType() != MethodDescriptor.MethodType.UNARY) { - return new StreamCallClientInterceptor(channel.newCall(method, callOptions), method, channel); - } - return new BlockingCallClientInterceptor(channel.newCall(method, callOptions), method, channel); - } - -} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/OperationNameFormatUtil.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/OperationNameFormatUtil.java index e5fa97eb5..245d6b3dc 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/OperationNameFormatUtil.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/OperationNameFormatUtil.java @@ -27,7 +27,7 @@ import io.grpc.MethodDescriptor; */ public class OperationNameFormatUtil { - public static String formatOperationName(MethodDescriptor methodDescriptor) { + public static String formatOperationName(MethodDescriptor methodDescriptor) { String fullMethodName = methodDescriptor.getFullMethodName(); return formatServiceName(fullMethodName) + "." + formatMethodName(fullMethodName); } diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/StreamCallClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/StreamCallClientInterceptor.java deleted file mode 100644 index 57cdadb57..000000000 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/StreamCallClientInterceptor.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package org.apache.skywalking.apm.plugin.grpc.v1; - -import io.grpc.Channel; -import io.grpc.ClientCall; -import io.grpc.ForwardingClientCall; -import io.grpc.ForwardingClientCallListener; -import io.grpc.Metadata; -import io.grpc.MethodDescriptor; -import io.grpc.Status; -import org.apache.skywalking.apm.agent.core.context.CarrierItem; -import org.apache.skywalking.apm.agent.core.context.ContextCarrier; -import org.apache.skywalking.apm.agent.core.context.ContextManager; -import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; -import org.apache.skywalking.apm.agent.core.context.tag.Tags; -import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; -import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; -import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; - -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.CLIENT; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_RESPONSE_OBSERVER_ON_COMPLETE_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_RESPONSE_OBSERVER_ON_ERROR_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_RESPONSE_OBSERVER_ON_NEXT_OPERATION_NAME; -import static org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil.formatOperationName; - -/** - * @author zhangxin - */ -public class StreamCallClientInterceptor extends ForwardingClientCall.SimpleForwardingClientCall implements CallClientInterceptor { - - private final String serviceName; - private final String remotePeer; - private final String operationPrefix; - private final Channel channel; - private final MethodDescriptor methodDescriptor; - - protected StreamCallClientInterceptor(ClientCall delegate, MethodDescriptor method, Channel channel) { - super(delegate); - this.channel = channel; - this.methodDescriptor = method; - this.serviceName = formatOperationName(method); - this.remotePeer = channel.authority(); - this.operationPrefix = OperationNameFormatUtil.formatOperationName(method) + CLIENT; - } - - @Override - public void start(Listener responseListener, Metadata headers) { - final ContextCarrier contextCarrier = new ContextCarrier(); - final AbstractSpan span = ContextManager.createExitSpan(serviceName, contextCarrier, remotePeer); - span.setComponent(ComponentsDefine.GRPC); - SpanLayer.asRPCFramework(span); - 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()); - } - delegate().start(new CallListener(responseListener, ContextManager.capture()), headers); - ContextManager.stopSpan(); - } - - @Override - public Channel getChannel() { - return channel; - } - - @Override - public MethodDescriptor getMethodDescriptor() { - return methodDescriptor; - } - - private class CallListener extends ForwardingClientCallListener.SimpleForwardingClientCallListener { - - private final ContextSnapshot contextSnapshot; - - protected CallListener(Listener delegate, ContextSnapshot contextSnapshot) { - super(delegate); - this.contextSnapshot = contextSnapshot; - } - - @Override - public void onReady() { - delegate().onReady(); - } - - @Override - public void onHeaders(Metadata headers) { - delegate().onHeaders(headers); - } - - @Override - public void onMessage(Object message) { - try { - ContextManager.createLocalSpan(operationPrefix + STREAM_RESPONSE_OBSERVER_ON_NEXT_OPERATION_NAME); - ContextManager.continued(contextSnapshot); - delegate().onMessage(message); - } catch (Throwable t) { - ContextManager.activeSpan().errorOccurred().log(t); - } finally { - ContextManager.stopSpan(); - } - } - - @Override - public void onClose(Status status, Metadata trailers) { - try { - if (!status.isOk()) { - AbstractSpan abstractSpan = ContextManager.createLocalSpan(operationPrefix + STREAM_RESPONSE_OBSERVER_ON_ERROR_OPERATION_NAME); - abstractSpan.errorOccurred().log(status.asRuntimeException()); - Tags.STATUS_CODE.set(abstractSpan, status.getCode().name()); - } else { - AbstractSpan abstractSpan = ContextManager.createLocalSpan(operationPrefix + STREAM_RESPONSE_OBSERVER_ON_COMPLETE_OPERATION_NAME); - } - delegate().onClose(status, trailers); - ContextManager.continued(contextSnapshot); - } catch (Throwable t) { - ContextManager.activeSpan().errorOccurred().log(t); - } finally { - ContextManager.stopSpan(); - } - } - } - -} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AbstractStubInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/AbstractStubInterceptor.java similarity index 79% rename from apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AbstractStubInterceptor.java rename to apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/AbstractStubInterceptor.java index fb6edd9e5..ebc2df0a8 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AbstractStubInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/AbstractStubInterceptor.java @@ -16,40 +16,42 @@ * */ -package org.apache.skywalking.apm.plugin.grpc.v1; +package org.apache.skywalking.apm.plugin.grpc.v1.client; import io.grpc.Channel; import io.grpc.ClientInterceptors; -import java.lang.reflect.Method; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import java.lang.reflect.Method; + /** * {@link AbstractStubInterceptor} add the interceptor for every ClientCall. * - * @author zhang xin + * @author zhang xin, kanro */ public class AbstractStubInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { @Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { - Channel channel = (Channel)allArguments[0]; - objInst.setSkyWalkingDynamicField(ClientInterceptors.intercept(channel, new GRPCClientInterceptor())); + Channel channel = (Channel) allArguments[0]; + objInst.setSkyWalkingDynamicField(ClientInterceptors.intercept(channel, new ClientInterceptor())); } @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { + MethodInterceptResult result) throws Throwable { } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { + Object ret) throws Throwable { return objInst.getSkyWalkingDynamicField(); } - @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { + @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/apache/skywalking/apm/plugin/grpc/v1/BlockingCallInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/BlockingCallInterceptor.java similarity index 70% rename from apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/BlockingCallInterceptor.java rename to apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/BlockingCallInterceptor.java index abf5d9883..890389f94 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/BlockingCallInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/BlockingCallInterceptor.java @@ -16,11 +16,10 @@ * */ -package org.apache.skywalking.apm.plugin.grpc.v1; +package org.apache.skywalking.apm.plugin.grpc.v1.client; import io.grpc.Channel; import io.grpc.MethodDescriptor; -import java.lang.reflect.Method; import org.apache.skywalking.apm.agent.core.context.ContextManager; import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; @@ -28,31 +27,37 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInt import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor; import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import java.lang.reflect.Method; + +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.BLOCKING_CALL_EXIT_SPAN; import static org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil.formatOperationName; /** - * @author zhang xin + * @author zhang xin, kanro */ public class BlockingCallInterceptor implements StaticMethodsAroundInterceptor { - @Override public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, - MethodInterceptResult result) { - Channel channel = (Channel)allArguments[0]; - MethodDescriptor methodDescriptor = (MethodDescriptor)allArguments[1]; + @Override + public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + MethodInterceptResult result) { + Channel channel = (Channel) allArguments[0]; + MethodDescriptor methodDescriptor = (MethodDescriptor) allArguments[1]; final AbstractSpan span = ContextManager.createExitSpan(formatOperationName(methodDescriptor), channel.authority()); span.setComponent(ComponentsDefine.GRPC); - SpanLayer.asRPCFramework(span); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.getRuntimeContext().put(BLOCKING_CALL_EXIT_SPAN, span); } - @Override public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, - Object ret) { + @Override + public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, + Object ret) { ContextManager.stopSpan(); return ret; } @Override public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class[] parameterTypes, - Throwable t) { + Throwable t) { ContextManager.activeSpan().errorOccurred().log(t); } } diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallClientInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/ClientInterceptor.java similarity index 60% rename from apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallClientInterceptor.java rename to apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/ClientInterceptor.java index 291081770..21f31d7b7 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/CallClientInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/ClientInterceptor.java @@ -16,19 +16,21 @@ * */ -package org.apache.skywalking.apm.plugin.grpc.v1; +package org.apache.skywalking.apm.plugin.grpc.v1.client; +import io.grpc.CallOptions; import io.grpc.Channel; +import io.grpc.ClientCall; import io.grpc.MethodDescriptor; /** - * @author AI - * 2019-07-22 + * @author zhang xin, kanro */ -public interface CallClientInterceptor { - - public Channel getChannel(); - - public MethodDescriptor getMethodDescriptor(); +public class ClientInterceptor implements io.grpc.ClientInterceptor { + @Override + public ClientCall interceptCall(MethodDescriptor method, + CallOptions callOptions, Channel channel) { + return new TracingClientCall<>(channel.newCall(method, callOptions), method, channel); + } } diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/TracingClientCall.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/TracingClientCall.java new file mode 100644 index 000000000..dde2198c2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/client/TracingClientCall.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.grpc.v1.client; + +import io.grpc.*; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil; + +import javax.annotation.Nullable; + +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.*; +import static org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil.formatOperationName; + +/** + * Fully client tracing for gRPC servers. + * + * @author zhang xin, kanro + */ +class TracingClientCall extends ForwardingClientCall.SimpleForwardingClientCall { + + private final String serviceName; + private final String remotePeer; + private final String operationPrefix; + private final MethodDescriptor methodDescriptor; + private ContextSnapshot snapshot; + + TracingClientCall(ClientCall delegate, MethodDescriptor method, Channel channel) { + super(delegate); + + this.methodDescriptor = method; + this.serviceName = formatOperationName(method); + this.remotePeer = channel.authority(); + this.operationPrefix = OperationNameFormatUtil.formatOperationName(method) + CLIENT; + } + + @Override + public void start(Listener responseListener, Metadata headers) { + final AbstractSpan blockingSpan = (AbstractSpan) ContextManager.getRuntimeContext().get(BLOCKING_CALL_EXIT_SPAN); + final ContextCarrier contextCarrier = new ContextCarrier(); + + // Avoid create ExitSpan repeatedly, ExitSpan of blocking calls will create by BlockingCallInterceptor. + if (blockingSpan == null) { + final AbstractSpan span = ContextManager.createExitSpan(serviceName, remotePeer); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + } else { + ContextManager.getRuntimeContext().remove(BLOCKING_CALL_EXIT_SPAN); + } + + 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()); + } + + snapshot = ContextManager.capture(); + try { + delegate().start(new TracingClientCallListener(responseListener, snapshot), headers); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + if (blockingSpan == null) { + ContextManager.stopSpan(); + } + } + } + + @Override + public void sendMessage(REQUEST message) { + if (methodDescriptor.getType().clientSendsOneMessage()) { + super.sendMessage(message); + return; + } + + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_MESSAGE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(snapshot); + + try { + super.sendMessage(message); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public void halfClose() { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_COMPLETE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(snapshot); + + try { + super.halfClose(); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public void cancel(@Nullable String message, @Nullable Throwable cause) { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_CANCEL_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(snapshot); + + if (cause != null) { + span.log(cause); + } + + try { + super.cancel(message, cause); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } + + class TracingClientCallListener extends ForwardingClientCallListener.SimpleForwardingClientCallListener { + private final ContextSnapshot contextSnapshot; + + TracingClientCallListener(Listener delegate, ContextSnapshot contextSnapshot) { + super(delegate); + this.contextSnapshot = contextSnapshot; + } + + @Override + public void onMessage(RESPONSE message) { + if (methodDescriptor.getType().serverSendsOneMessage()) { + super.onMessage(message); + return; + } + + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + RESPONSE_ON_MESSAGE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + + try { + delegate().onMessage(message); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public void onClose(Status status, Metadata trailers) { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + RESPONSE_ON_CLOSE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + if (!status.isOk()) { + span.errorOccurred().log(status.asRuntimeException()); + Tags.STATUS_CODE.set(span, status.getCode().name()); + } + + try { + delegate().onClose(status, trailers); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + } finally { + ContextManager.stopSpan(); + } + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java index fe75cc81e..d57b09ba3 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractServerImplBuilderInstrumentation.java @@ -33,7 +33,7 @@ public class AbstractServerImplBuilderInstrumentation extends ClassInstanceMetho public static final String ENHANCE_CLASS = "io.grpc.internal.AbstractServerImplBuilder"; public static final String ENHANCE_METHOD = "addService"; - public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.AbstractServerImplBuilderInterceptor"; + public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.server.AbstractServerImplBuilderInterceptor"; public static final String ARGUMENT_TYPE = "io.grpc.ServerServiceDefinition"; @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractStubInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractStubInstrumentation.java index 54bab2262..db34681d5 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractStubInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/AbstractStubInstrumentation.java @@ -31,7 +31,7 @@ import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName public class AbstractStubInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { - public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.AbstractStubInterceptor"; + public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.client.AbstractStubInterceptor"; public static final String ENHANCE_METHOD = "getChannel"; public static final String ENHANCE_CLASS = "io.grpc.stub.AbstractStub"; diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/ClientCallsInstrumentation.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/ClientCallsInstrumentation.java index 07f98144b..99beb9c0e 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/ClientCallsInstrumentation.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/define/ClientCallsInstrumentation.java @@ -32,10 +32,8 @@ import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName * @author zhang xin */ public class ClientCallsInstrumentation extends ClassStaticMethodsEnhancePluginDefine { - private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls"; - private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.BlockingCallInterceptor"; - private static final String FUTURE_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.AsyncUnaryRequestCallCallInterceptor"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.client.BlockingCallInterceptor"; @Override public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() { return new StaticMethodsInterceptPoint[] { @@ -51,32 +49,6 @@ public class ClientCallsInstrumentation extends ClassStaticMethodsEnhancePluginD @Override public boolean isOverrideArgs() { return false; } - }, -// new StaticMethodsInterceptPoint() { -// @Override public ElementMatcher getMethodsMatcher() { -// return named("blockingServerStreamingCall").and(takesArgumentWithType(1, "io.grpc.MethodDescriptor")); -// } -// -// @Override public String getMethodsInterceptor() { -// return INTERCEPTOR_CLASS; -// } -// -// @Override public boolean isOverrideArgs() { -// return false; -// } -// }, - new StaticMethodsInterceptPoint() { - @Override public ElementMatcher getMethodsMatcher() { - return named("asyncUnaryRequestCall").and(takesArgumentWithType(2, "io.grpc.ClientCall$Listener")); - } - - @Override public String getMethodsInterceptor() { - return FUTURE_INTERCEPTOR_CLASS; - } - - @Override public boolean isOverrideArgs() { - return true; - } } }; } diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AbstractServerImplBuilderInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java similarity index 76% rename from apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AbstractServerImplBuilderInterceptor.java rename to apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java index 6d5b00e64..251217cad 100644 --- a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/AbstractServerImplBuilderInterceptor.java +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/AbstractServerImplBuilderInterceptor.java @@ -16,17 +16,19 @@ * */ -package org.apache.skywalking.apm.plugin.grpc.v1; +package org.apache.skywalking.apm.plugin.grpc.v1.server; import io.grpc.ServerInterceptors; import io.grpc.ServerServiceDefinition; + import java.lang.reflect.Method; + import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; /** - * {@link AbstractServerImplBuilderInterceptor} add the {@link CallServerInterceptor} interceptor for every + * {@link AbstractServerImplBuilderInterceptor} add the {@link ServerInterceptor} interceptor for every * ServerService. * * @author zhang xin @@ -34,18 +36,19 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInt public class AbstractServerImplBuilderInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - MethodInterceptResult result) throws Throwable { - allArguments[0] = ServerInterceptors.intercept((ServerServiceDefinition)allArguments[0], new CallServerInterceptor()); + MethodInterceptResult result) { + allArguments[0] = ServerInterceptors.intercept((ServerServiceDefinition) allArguments[0], new ServerInterceptor()); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, - Object ret) throws Throwable { + Object ret) { return ret; } - @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, - Class[] argumentsTypes, Throwable t) { + @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/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java new file mode 100644 index 000000000..3113fca23 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/ServerInterceptor.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.grpc.v1.server; + +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil; +import org.apache.skywalking.apm.util.StringUtil; + +/** + * @author zhang xin, wang zheng, kanro + */ +public class ServerInterceptor implements io.grpc.ServerInterceptor { + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler handler) { + final ContextCarrier contextCarrier = new ContextCarrier(); + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + String contextValue = headers.get(Metadata.Key.of(next.getHeadKey(), Metadata.ASCII_STRING_MARSHALLER)); + if (!StringUtil.isEmpty(contextValue)) { + next.setHeadValue(contextValue); + } + } + + final AbstractSpan span = ContextManager.createEntrySpan(OperationNameFormatUtil.formatOperationName(call.getMethodDescriptor()), contextCarrier); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + try { + return new TracingServerCallListener<>(handler.startCall(new TracingServerCall<>(call, ContextManager.capture()), headers), call.getMethodDescriptor(), ContextManager.capture()); + } finally { + ContextManager.stopSpan(); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java new file mode 100644 index 000000000..48572bf98 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCall.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.grpc.v1.server; + +import io.grpc.ForwardingServerCall; +import io.grpc.Metadata; +import io.grpc.ServerCall; +import io.grpc.Status; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil; + +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.*; + +/** + * @author wang zheng, kanro + */ +public class TracingServerCall extends ForwardingServerCall.SimpleForwardingServerCall { + + private final String operationPrefix; + private final ContextSnapshot contextSnapshot; + + protected TracingServerCall(ServerCall delegate, ContextSnapshot contextSnapshot) { + super(delegate); + this.operationPrefix = OperationNameFormatUtil.formatOperationName(delegate.getMethodDescriptor()) + SERVER; + this.contextSnapshot = contextSnapshot; + } + + @Override + public void sendMessage(RESPONSE message) { + // We just create the request on message span for server stream calls. + if (!getMethodDescriptor().getType().serverSendsOneMessage()) { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + RESPONSE_ON_MESSAGE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + + try { + super.sendMessage(message); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } else { + super.sendMessage(message); + } + } + + @Override + public void close(Status status, Metadata trailers) { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + RESPONSE_ON_CLOSE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + switch (status.getCode()) { + case OK: + break; + // UNKNOWN/INTERNAL status code will case error in this span. + // Those status code means some unexpected error occurred in server. + // Similar to 5XX in HTTP status. + case UNKNOWN: + case INTERNAL: + if (status.getCause() == null) { + span.errorOccurred().log(status.asRuntimeException()); + } else { + span.errorOccurred().log(status.getCause()); + } + break; + // Other status code means some predictable error occurred in server. + // Like PERMISSION_DENIED or UNAUTHENTICATED somethings. + // Similar to 4XX in HTTP status. + default: + // But if the status still has cause exception, we will log it too. + if (status.getCause() != null) { + span.errorOccurred().log(status.getCause()); + } + break; + } + Tags.STATUS_CODE.set(span, status.getCode().name()); + + try { + super.close(status, trailers); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java new file mode 100644 index 000000000..eaec5510b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/grpc-1.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/grpc/v1/server/TracingServerCallListener.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.grpc.v1.server; + +import io.grpc.ForwardingServerCallListener; +import io.grpc.MethodDescriptor; +import io.grpc.ServerCall; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.ContextSnapshot; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil; + +import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.*; + +/** + * @author wang zheng, kanro + */ +public class TracingServerCallListener extends ForwardingServerCallListener.SimpleForwardingServerCallListener { + + private final ContextSnapshot contextSnapshot; + private final MethodDescriptor.MethodType methodType; + private final String operationPrefix; + + protected TracingServerCallListener(ServerCall.Listener delegate, MethodDescriptor descriptor, + ContextSnapshot contextSnapshot) { + super(delegate); + this.contextSnapshot = contextSnapshot; + this.methodType = descriptor.getType(); + this.operationPrefix = OperationNameFormatUtil.formatOperationName(descriptor) + SERVER; + } + + @Override + public void onMessage(REQUEST message) { + // We just create the request on message span for client stream calls. + if (!methodType.clientSendsOneMessage()) { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_MESSAGE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + try { + super.onMessage(message); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } else { + super.onMessage(message); + } + } + + @Override + public void onCancel() { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_CANCEL_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + + try { + super.onCancel(); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } + + @Override + public void onHalfClose() { + final AbstractSpan span = ContextManager.createLocalSpan(operationPrefix + REQUEST_ON_COMPLETE_OPERATION_NAME); + span.setComponent(ComponentsDefine.GRPC); + span.setLayer(SpanLayer.RPC_FRAMEWORK); + ContextManager.continued(contextSnapshot); + + try { + super.onHalfClose(); + } catch (Throwable t) { + ContextManager.activeSpan().errorOccurred().log(t); + throw t; + } finally { + ContextManager.stopSpan(); + } + } +} diff --git a/test/plugin/scenarios/grpc-scenario/config/expectedData.yaml b/test/plugin/scenarios/grpc-scenario/config/expectedData.yaml index 51a02e1c9..b0a870ca2 100644 --- a/test/plugin/scenarios/grpc-scenario/config/expectedData.yaml +++ b/test/plugin/scenarios/grpc-scenario/config/expectedData.yaml @@ -15,239 +15,551 @@ # limitations under the License. registryItems: applications: - - {grpc-scenario: 2} + - { grpc-scenario: 2 } instances: - - {grpc-scenario: 1} + - { grpc-scenario: 1 } operationNames: - - grpc-scenario: [Greeter.sayHello, GreeterBlocking.sayHello, - /grpc-scenario/case/grpc-scenario] + - grpc-scenario: [Greeter.sayHello, GreeterBlocking.sayHello, GreeterBlockingError.sayHello, /grpc-scenario/case/grpc-scenario] heartbeat: [] segmentItems: - - applicationCode: grpc-scenario - segmentSize: gt 10 - segments: - - segmentId: not null - spans: - - operationName: GreeterBlocking.sayHello - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: RPCFramework - startTime: nq 0 - endTime: nq 0 - componentId: 23 - componentName: '' - isError: false - spanType: Entry - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '127.0.0.1:18080', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: RPCFramework - startTime: nq 0 - endTime: nq 0 - componentId: 23 - componentName: '' - isError: false - spanType: Entry - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, - entryEndpointId: 0, refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '127.0.0.1:18080', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: GreeterBlocking.sayHello/server/RequestObserver/onNext - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: GreeterBlocking.sayHello, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello/server/RequestObserver/onNext - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello/client/ResponseObserver/onNext - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello/client/ResponseObserver/onComplete - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello/server/RequestObserver/onNext - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello/server/RequestObserver/onComplete - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - - segmentId: not null - spans: - - operationName: Greeter.sayHello - operationId: 0 - parentSpanId: 0 - spanId: 1 - spanLayer: RPCFramework - startTime: nq 0 - endTime: nq 0 - componentId: 23 - componentName: '' - isError: false - spanType: Exit - peer: '127.0.0.1:18080' - peerId: 0 - - operationName: GreeterBlocking.sayHello - operationId: 0 - parentSpanId: 0 - spanId: 2 - spanLayer: RPCFramework - startTime: nq 0 - endTime: nq 0 - componentId: 23 - componentName: '' - isError: false - spanType: Exit - peer: '127.0.0.1:18080' - peerId: 0 - - operationName: /grpc-scenario/case/grpc-scenario - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Http - startTime: nq 0 - endTime: nq 0 - componentId: 1 - componentName: '' - isError: false - spanType: Entry - peer: '' - peerId: 0 - tags: - - {key: url, value: 'http://localhost:8080/grpc-scenario/case/grpc-scenario'} - - {key: http.method, value: GET} - - segmentId: not null - spans: - - operationName: Greeter.sayHello/client/ResponseObserver/onNext - operationId: 0 - parentSpanId: -1 - spanId: 0 - spanLayer: Unknown - startTime: nq 0 - endTime: nq 0 - componentId: 0 - componentName: '' - isError: false - spanType: Local - peer: '' - peerId: 0 - refs: - - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, - entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, - parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, - entryServiceInstanceId: 1} - +- applicationCode: grpc-scenario + segmentSize: gt 10 + segments: + - segmentId: not null + spans: + - operationName: GreeterBlocking.sayHello + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Entry + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 2, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '127.0.0.1:18080', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onMessage + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onMessage + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Request/onComplete + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Entry + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '127.0.0.1:18080', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onMessage + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - operationName: Greeter.sayHello/server/Request/onMessage + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onMessage + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: GreeterBlocking.sayHello/server/Response/onClose + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + tags: + - { key: status_code, value: OK } + refs: + - {parentEndpointId: 0, parentEndpoint: GreeterBlocking.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - operationName: GreeterBlocking.sayHello/server/Request/onComplete + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: GreeterBlocking.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onMessage + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - operationName: Greeter.sayHello/server/Request/onMessage + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/server/Response/onClose + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + tags: + - {key: status_code, value: OK} + refs: + - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - operationName: Greeter.sayHello/server/Request/onComplete + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: Greeter.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onMessage + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello/client/Response/onClose + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 1, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: GreeterBlockingError.sayHello + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Entry + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: /grpc-scenario/case/grpc-scenario, networkAddressId: 0, + entryEndpointId: 0, refType: CrossProcess, parentSpanId: 5, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '127.0.0.1:18080', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: GreeterBlockingError.sayHello/server/Response/onClose + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: true + spanType: Local + peer: '' + peerId: 0 + tags: + - { key: status_code, value: UNKNOWN } + logs: + - logEvent: + - { key: event, value: error } + - { key: error.kind, value: java.lang.Exception } + - { key: message, value: '' } + - key: stack + value: not null + refs: + - {parentEndpointId: 0, parentEndpoint: GreeterBlockingError.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - operationName: GreeterBlockingError.sayHello/server/Request/onComplete + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + refs: + - {parentEndpointId: 0, parentEndpoint: GreeterBlockingError.sayHello, networkAddressId: 0, + entryEndpointId: 0, refType: CrossThread, parentSpanId: 0, parentTraceSegmentId: not null, + parentServiceInstanceId: 1, networkAddress: '', entryEndpoint: /grpc-scenario/case/grpc-scenario, + entryServiceInstanceId: 1} + - segmentId: not null + spans: + - operationName: Greeter.sayHello + operationId: 0 + parentSpanId: 0 + spanId: 1 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Exit + peer: '127.0.0.1:18080' + peerId: 0 + - operationName: GreeterBlocking.sayHello/client/Request/onComplete + operationId: 0 + parentSpanId: 2 + spanId: 3 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + - operationName: GreeterBlocking.sayHello/client/Response/onClose + operationId: 0 + parentSpanId: 2 + spanId: 4 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + - operationName: GreeterBlocking.sayHello + operationId: 0 + parentSpanId: 0 + spanId: 2 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Exit + peer: '127.0.0.1:18080' + peerId: 0 + - operationName: GreeterBlockingError.sayHello/client/Request/onComplete + operationId: 0 + parentSpanId: 5 + spanId: 6 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + - operationName: GreeterBlockingError.sayHello/client/Response/onClose + operationId: 0 + parentSpanId: 5 + spanId: 7 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: true + spanType: Local + peer: '' + peerId: 0 + tags: + - {key: status_code, value: UNKNOWN} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - key: stack + value: not null + - operationName: GreeterBlockingError.sayHello/client/Request/onCancel + operationId: 0 + parentSpanId: 5 + spanId: 8 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: false + spanType: Local + peer: '' + peerId: 0 + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - key: stack + value: not null + - operationName: GreeterBlockingError.sayHello + operationId: 0 + parentSpanId: 0 + spanId: 5 + spanLayer: RPCFramework + startTime: nq 0 + endTime: nq 0 + componentId: 23 + componentName: '' + isError: true + spanType: Exit + peer: 127.0.0.1:18080 + peerId: 0 + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: io.grpc.StatusRuntimeException} + - {key: message, value: UNKNOWN} + - key: stack + value: not null + - operationName: /grpc-scenario/case/grpc-scenario + operationId: 0 + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + componentName: '' + isError: true + spanType: Entry + peer: '' + peerId: 0 + tags: + - {key: url, value: 'http://localhost:8080/grpc-scenario/case/grpc-scenario'} + - {key: http.method, value: GET} + - {key: status_code, value: '500'} + logs: + - logEvent: + - {key: event, value: error} + - {key: error.kind, value: org.springframework.web.util.NestedServletException} + - {key: message, value: 'Request processing failed; nested exception is io.grpc.StatusRuntimeException: UNKNOWN'} + - key: stack + value: not null + - logEvent: + - {key: forward-url, value: /grpc-scenario/error} diff --git a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java index 75795829d..708770a9d 100644 --- a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java +++ b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/controller/CaseController.java @@ -26,10 +26,7 @@ import io.grpc.stub.ClientResponseObserver; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.skywalking.apm.testcase.grpc.consumr.ConsumerInterceptor; -import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingGrpc; -import org.apache.skywalking.apm.testcase.grpc.proto.GreeterGrpc; -import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; -import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; +import org.apache.skywalking.apm.testcase.grpc.proto.*; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; @@ -52,12 +49,14 @@ public class CaseController { private ManagedChannel channel; private GreeterGrpc.GreeterStub greeterStub; private GreeterBlockingGrpc.GreeterBlockingBlockingStub greeterBlockingStub; + private GreeterBlockingErrorGrpc.GreeterBlockingErrorBlockingStub greeterBlockingErrorStub; @PostConstruct public void up() { channel = ManagedChannelBuilder.forAddress(gprcProviderHost, grpcProviderPort).usePlaintext(true).build(); greeterStub = GreeterGrpc.newStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); greeterBlockingStub = GreeterBlockingGrpc.newBlockingStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); + greeterBlockingErrorStub = GreeterBlockingErrorGrpc.newBlockingStub(ClientInterceptors.intercept(channel, new ConsumerInterceptor())); } @RequestMapping("/grpc-scenario") @@ -65,6 +64,7 @@ public class CaseController { public String testcase() { greetService(); greetBlockingService(); + greetBlockingErrorService(); return SUCCESS; } @@ -129,4 +129,9 @@ public class CaseController { HelloRequest request = HelloRequest.newBuilder().setName("Sophia").build(); greeterBlockingStub.sayHello(request); } + + private void greetBlockingErrorService() { + HelloRequest request = HelloRequest.newBuilder().setName("Tony").build(); + greeterBlockingErrorStub.sayHello(request); + } } diff --git a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java index 2058f580b..672876f8f 100644 --- a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java +++ b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/ProviderConfiguration.java @@ -22,6 +22,7 @@ import io.grpc.Server; import io.grpc.ServerBuilder; import io.grpc.ServerInterceptors; import org.apache.skywalking.apm.testcase.grpc.provider.interceptor.ProviderInterceptor; +import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterBlockingErrorServiceImpl; import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterBlockingServiceImpl; import org.apache.skywalking.apm.testcase.grpc.provider.service.GreeterServiceImpl; import org.springframework.beans.factory.annotation.Configurable; @@ -38,8 +39,9 @@ public class ProviderConfiguration { @Bean(initMethod = "start", destroyMethod = "shutdown") public Server server() { return ServerBuilder.forPort(18080) - .addService(ServerInterceptors.intercept(new GreeterServiceImpl(), new ProviderInterceptor())) - .addService(ServerInterceptors.intercept(new GreeterBlockingServiceImpl(), new ProviderInterceptor())) - .build(); + .addService(ServerInterceptors.intercept(new GreeterServiceImpl(), new ProviderInterceptor())) + .addService(ServerInterceptors.intercept(new GreeterBlockingServiceImpl(), new ProviderInterceptor())) + .addService(ServerInterceptors.intercept(new GreeterBlockingErrorServiceImpl(), new ProviderInterceptor())) + .build(); } } diff --git a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java new file mode 100644 index 000000000..7b1af584b --- /dev/null +++ b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterBlockingErrorServiceImpl.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.apache.skywalking.apm.testcase.grpc.provider.service; + +import io.grpc.stub.StreamObserver; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingErrorGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.GreeterBlockingGrpc; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloReply; +import org.apache.skywalking.apm.testcase.grpc.proto.HelloRequest; + +public class GreeterBlockingErrorServiceImpl extends GreeterBlockingErrorGrpc.GreeterBlockingErrorImplBase { + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + responseObserver.onError(new Exception()); + } +} diff --git a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java index 00a77f898..1116c477a 100644 --- a/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java +++ b/test/plugin/scenarios/grpc-scenario/src/main/java/org/apache/skywalking/apm/testcase/grpc/provider/service/GreeterServiceImpl.java @@ -33,6 +33,7 @@ public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase { @Override public StreamObserver sayHello(final StreamObserver responseObserver) { StreamObserver requestStreamObserver = new StreamObserver() { + public void onNext(HelloRequest request) { logger.info("Receive an message from client. Message: {}", request.getName()); responseObserver.onNext(HelloReply.newBuilder().setMessage("Hi," + request.getName()).build()); diff --git a/test/plugin/scenarios/grpc-scenario/src/main/proto/GreetService.proto b/test/plugin/scenarios/grpc-scenario/src/main/proto/GreetService.proto index f6c28f717..fd5ba4a8f 100644 --- a/test/plugin/scenarios/grpc-scenario/src/main/proto/GreetService.proto +++ b/test/plugin/scenarios/grpc-scenario/src/main/proto/GreetService.proto @@ -29,6 +29,10 @@ service GreeterBlocking { rpc SayHello (HelloRequest) returns (HelloReply) { } } +service GreeterBlockingError { + rpc SayHello (HelloRequest) returns (HelloReply) { + } +} message HelloRequest { string name = 1;