Merge branch 'master' into fix/kafka-plugin-issue

This commit is contained in:
Xin,Zhang 2018-02-06 22:55:02 +08:00 committed by GitHub
commit daf3c257d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 351 additions and 1917 deletions

View File

@ -16,37 +16,36 @@
*
*/
package org.apache.skywalking.apm.plugin.grpc.v1;
import io.grpc.internal.ManagedChannelImpl;
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;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link ManagedChannelInterceptor} record the IP address of the GRPC server into {@link GRPCDynamicFields} for build
* span.
* {@link AbstractServerImplBuilderInterceptor} add the {@link CallServerInterceptor} interceptor for every
* ServerService.
*
* @author zhangxin
* @author zhang xin
*/
public class ManagedChannelInterceptor implements InstanceMethodsAroundInterceptor {
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());
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)((EnhancedInstance)ret).getSkyWalkingDynamicField();
cachedObjects.setAuthority(((ManagedChannelImpl)((Object)objInst)).authority());
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
}
}

View File

@ -16,24 +16,27 @@
*
*/
package org.apache.skywalking.apm.plugin.grpc.v1;
import io.grpc.Channel;
import io.grpc.ClientInterceptors;
import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.plugin.grpc.v1.define.Constants;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
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 org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link ServerCallOnCancelInterceptor} stop the active span when the call cancelled.
* {@link AbstractStubInterceptor} add the interceptor for every ClientCall.
*
* @author zhangxin
* @author zhang xin
*/
public class ServerCallOnCancelInterceptor implements InstanceMethodsAroundInterceptor {
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()));
}
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
@ -43,15 +46,10 @@ public class ServerCallOnCancelInterceptor implements InstanceMethodsAroundInter
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
AbstractSpan abstractSpan = ContextManager.activeSpan();
abstractSpan.tag(Constants.ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount()));
ContextManager.stopSpan();
return ret;
return objInst.getSkyWalkingDynamicField();
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.skywalking.apm.plugin.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.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.OperationNameFormatUtil.formatOperationName;
/**
* @author zhang xin
*/
public class BlockingCallClientInterceptor extends ForwardingClientCall.SimpleForwardingClientCall {
private final String serviceName;
private final String remotePeer;
public BlockingCallClientInterceptor(ClientCall delegate, MethodDescriptor method, Channel channel) {
super(delegate);
this.serviceName = formatOperationName(method);
this.remotePeer = channel.authority();
}
@Override public void start(Listener responseListener, Metadata headers) {
final AbstractSpan span = ContextManager.createExitSpan(serviceName, remotePeer);
span.setComponent(ComponentsDefine.GRPC);
SpanLayer.asRPCFramework(span);
final ContextCarrier contextCarrier = new ContextCarrier();
ContextManager.inject(contextCarrier);
CarrierItem contextItem = contextCarrier.items();
while (contextItem.hasNext()) {
contextItem = contextItem.next();
Metadata.Key<String> headerKey = Metadata.Key.of(contextItem.getHeadKey(), Metadata.ASCII_STRING_MARSHALLER);
headers.put(headerKey, contextItem.getHeadValue());
}
delegate().start(new CallListener(responseListener), headers);
}
private class CallListener extends ForwardingClientCallListener.SimpleForwardingClientCallListener {
protected CallListener(Listener delegate) {
super(delegate);
}
@Override public void onReady() {
delegate().onReady();
}
@Override public void onClose(Status status, Metadata trailers) {
delegate().onClose(status, trailers);
if (status.isOk()) {
AbstractSpan activeSpan = ContextManager.activeSpan();
activeSpan.errorOccurred().log(status.getCause());
Tags.STATUS_CODE.set(activeSpan, status.getCode().name());
}
ContextManager.stopSpan();
}
@Override
public void onMessage(Object message) {
delegate().onMessage(message);
}
@Override public void onHeaders(Metadata headers) {
delegate().onHeaders(headers);
}
}
}

View File

@ -16,41 +16,32 @@
*
*/
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 java.lang.reflect.Method;
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.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import org.apache.skywalking.apm.util.StringUtil;
import static org.apache.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_CALL_OPERATION_NAME_SUFFIX;
import static org.apache.skywalking.apm.plugin.grpc.v1.define.Constants.BLOCK_CALL_OPERATION_NAME_SUFFIX;
import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_ON_NEXT_OPERATION_NAME;
/**
* {@link ServerCallOnReadyInterceptor} create a entry span when the server side is ready for receive the message from
* the client side.
*
* @author zhangxin
* @author zhang xin
*/
public class ServerCallOnReadyInterceptor implements InstanceMethodsAroundInterceptor {
public class CallServerInterceptor implements ServerInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
Metadata headers = cachedObjects.getMetadata();
public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler handler) {
Map<String, String> headerMap = new HashMap<String, String>();
for (String key : headers.keys()) {
if (!key.endsWith(Metadata.BINARY_HEADER_SUFFIX)) {
@ -69,18 +60,51 @@ public class ServerCallOnReadyInterceptor implements InstanceMethodsAroundInterc
}
}
final AbstractSpan span = ContextManager.createEntrySpan(cachedObjects.getRequestMethodName() + (cachedObjects.getMethodType() != MethodDescriptor.MethodType.UNARY ? STREAM_CALL_OPERATION_NAME_SUFFIX : BLOCK_CALL_OPERATION_NAME_SUFFIX), contextCarrier);
final AbstractSpan span = ContextManager.createEntrySpan(OperationNameFormatUtil.formatOperationName(call.getMethodDescriptor()), contextCarrier);
span.setComponent(ComponentsDefine.GRPC);
return new ServerCallListener(handler.startCall(new ForwardingServerCall.SimpleForwardingServerCall(call) {
@Override
public void sendHeaders(Metadata responseHeaders) {
delegate().sendHeaders(responseHeaders);
}
}, headers), call.getMethodDescriptor());
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
return ret;
public class ServerCallListener extends ForwardingServerCallListener.SimpleForwardingServerCallListener {
protected ServerCallListener(ServerCall.Listener delegate, MethodDescriptor descriptor) {
super(delegate);
}
@Override public void onReady() {
delegate().onReady();
}
@Override public void onMessage(Object message) {
try {
ContextManager.createLocalSpan(STREAM_ON_NEXT_OPERATION_NAME);
delegate().onMessage(message);
} catch (Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
} finally {
ContextManager.stopSpan();
}
}
@Override public void onComplete() {
delegate().onComplete();
ContextManager.stopSpan();
}
@Override public void onCancel() {
delegate().onCancel();
ContextManager.stopSpan();
}
@Override public void onHalfClose() {
delegate().onHalfClose();
}
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -1,61 +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 java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.grpc.v1.define.Constants;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link ClientCallOnNextInterceptor} create a local span when the client stream receive an message that send from
* server stream and record the value of <code>OnNext.count</code> tag.
*
* @author zhangxin
*/
public class ClientCallOnNextInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + Constants.STREAM_OPERATION_NAME_SUFFIX);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
ContextManager.stopSpan();
// record the call count of onNext method
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
cachedObjects.incrementOnNextCount();
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -1,64 +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.Metadata;
import java.lang.reflect.Method;
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.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
public class ClientCallStartInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
final Metadata headers = (Metadata)allArguments[1];
final ContextCarrier contextCarrier = new ContextCarrier();
ContextManager.inject(contextCarrier);
CarrierItem contextItem = contextCarrier.items();
while (contextItem.hasNext()) {
contextItem = contextItem.next();
Metadata.Key<String> headerKey = Metadata.Key.of(contextItem.getHeadKey(), Metadata.ASCII_STRING_MARSHALLER);
headers.put(headerKey, contextItem.getHeadValue());
}
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
GRPCDynamicFields listenerCachedObject = new GRPCDynamicFields();
listenerCachedObject.setSnapshot(ContextManager.capture());
listenerCachedObject.setDescriptor(cachedObjects.getDescriptor());
((EnhancedInstance)allArguments[0]).setSkyWalkingDynamicField(listenerCachedObject);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
}
}

View File

@ -1,62 +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 java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
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 org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link ClientCallOnNextInterceptor} create a exist span when the grpc start call. it will stop span when the method
* type is non-unary.
*
* @author zhangxin
*/
public class ClientCallsMethodInterceptor
implements StaticMethodsAroundInterceptor {
@Override public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes,
MethodInterceptResult result) {
EnhancedInstance clientCall = (EnhancedInstance)allArguments[0];
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)clientCall.getSkyWalkingDynamicField();
final AbstractSpan span = ContextManager.createExitSpan(cachedObjects.getRequestMethodName(), cachedObjects.getAuthority());
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);
}
}

View File

@ -16,22 +16,15 @@
*
*/
package org.apache.skywalking.apm.plugin.grpc.v1.define;
package org.apache.skywalking.apm.plugin.grpc.v1;
/**
* GRPC Plugin constants variables.
* Constant variables
*
* @author zhangxin
* @author zhang xin
*/
public final class Constants {
public static final String STREAM_OPERATION_NAME_SUFFIX = "/ResponseStreamObserver/OnNext";
public static final String ON_NEXT_COUNT_TAG_KEY = "onNext.count";
public static final String STREAM_CALL_OPERATION_NAME_SUFFIX = "/StreamCall";
public static final String BLOCK_CALL_OPERATION_NAME_SUFFIX = "/BlockCall";
public class Constants {
public static final String STREAM_ON_READY_OPERATION_NAME = "RequestStreamObserver/onReady";
public static final String STREAM_ON_NEXT_OPERATION_NAME = "ResponseStreamObserver/OnNext";
}

View File

@ -16,26 +16,30 @@
*
*/
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;
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.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link ClientCallIConstructorInterceptor} pass the {@link GRPCDynamicFields} into the
* <code>io.grpc.internal.ClientCallImpl</code> instance for propagate the information of build span.
* {@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 zhangxin
* @author zhang xin
*/
public class ClientCallIConstructorInterceptor implements InstanceConstructorInterceptor {
public class GRPCClientInterceptor implements ClientInterceptor {
@Override
public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
GRPCDynamicFields dynamicFields = new GRPCDynamicFields();
dynamicFields.setDescriptor((MethodDescriptor)allArguments[0]);
objInst.setSkyWalkingDynamicField(dynamicFields);
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);
}
}

View File

@ -16,44 +16,31 @@
*
*/
package org.apache.skywalking.apm.plugin.grpc.v1.vo;
package org.apache.skywalking.apm.plugin.grpc.v1;
import io.grpc.MethodDescriptor;
/**
* {@link ServiceDescriptor} indicate the descriptor of an grpc service. it contains {@link #methodType} and
* {@link #serviceName}.
* Operation Name utility
*
* @author zhangxin
*/
public class ServiceDescriptor {
private MethodDescriptor.MethodType methodType;
private String serviceName;
public class OperationNameFormatUtil {
public ServiceDescriptor(MethodDescriptor descriptor) {
this.methodType = descriptor.getType();
String fullMethodName = descriptor.getFullMethodName();
this.serviceName = formatServiceName(fullMethodName) + "." + formatMethodName(fullMethodName);
public static String formatOperationName(MethodDescriptor methodDescriptor) {
String fullMethodName = methodDescriptor.getFullMethodName();
return formatServiceName(fullMethodName) + "." + formatMethodName(fullMethodName);
}
private String formatServiceName(String requestMethodName) {
private static String formatServiceName(String requestMethodName) {
int splitIndex = requestMethodName.lastIndexOf("/");
return requestMethodName.substring(0, splitIndex);
}
private String formatMethodName(String requestMethodName) {
private static String formatMethodName(String requestMethodName) {
int splitIndex = requestMethodName.lastIndexOf("/");
String methodName = requestMethodName.substring(splitIndex + 1);
methodName = methodName.substring(0, 1).toLowerCase() + methodName.substring(1);
return methodName;
}
public MethodDescriptor.MethodType getMethodType() {
return methodType;
}
public String getServiceName() {
return serviceName;
}
}

View File

@ -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.Metadata;
import io.grpc.ServerCall;
import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.ContextCarrier;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
/**
* {@link ServerCallHandlerInterceptor} record the {@link Metadata} argument into {@link GRPCDynamicFields} for
* propagate {@link ContextCarrier} and also record the {@link
* io.grpc.MethodDescriptor} into {@link GRPCDynamicFields} for building span.
*
* @author zhangxin
*/
public class ServerCallHandlerInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
GRPCDynamicFields cachedObjects = new GRPCDynamicFields();
cachedObjects.setMetadata((Metadata)allArguments[1]);
cachedObjects.setDescriptor(((ServerCall)allArguments[0]).getMethodDescriptor());
((EnhancedInstance)ret).setSkyWalkingDynamicField(cachedObjects);
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
}
}

View File

@ -1,58 +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 java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
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.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import static org.apache.skywalking.apm.plugin.grpc.v1.define.Constants.ON_NEXT_COUNT_TAG_KEY;
/**
* {@link ServerCallOnCloseInterceptor} stop the active span when the call end.
*
* @author zhangxin
*/
public class ServerCallOnCloseInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
AbstractSpan abstractSpan = ContextManager.activeSpan();
abstractSpan.tag(ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount()));
ContextManager.stopSpan();
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -1,62 +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 java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import static org.apache.skywalking.apm.plugin.grpc.v1.define.Constants.STREAM_OPERATION_NAME_SUFFIX;
/**
* {@link ServerCallOnMessageInterceptor} create a local span when the server stream receive a message that send by the
* client.
*
* @author zhangxin
*/
public class ServerCallOnMessageInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + STREAM_OPERATION_NAME_SUFFIX);
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
ContextManager.stopSpan();
// record the call count of onNext method
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
cachedObjects.incrementOnNextCount();
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -0,0 +1,115 @@
/*
* 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.STREAM_ON_NEXT_OPERATION_NAME;
import static org.apache.skywalking.apm.plugin.grpc.v1.Constants.STREAM_ON_READY_OPERATION_NAME;
import static org.apache.skywalking.apm.plugin.grpc.v1.OperationNameFormatUtil.formatOperationName;
/**
* @author zhangxin
*/
public class StreamCallClientInterceptor extends ForwardingClientCall.SimpleForwardingClientCall {
private final String serviceName;
private final String remotePeer;
protected StreamCallClientInterceptor(ClientCall delegate, MethodDescriptor method, Channel channel) {
super(delegate);
this.serviceName = formatOperationName(method);
this.remotePeer = channel.authority();
}
@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<String> 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();
}
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() {
final AbstractSpan span = ContextManager.createLocalSpan(STREAM_ON_READY_OPERATION_NAME);
span.setComponent(ComponentsDefine.GRPC);
SpanLayer.asRPCFramework(span);
ContextManager.continued(contextSnapshot);
delegate().onReady();
}
@Override public void onHeaders(Metadata headers) {
delegate().onHeaders(headers);
}
@Override public void onMessage(Object message) {
try {
ContextManager.createLocalSpan(STREAM_ON_NEXT_OPERATION_NAME);
delegate().onMessage(message);
} catch (Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
} finally {
ContextManager.stopSpan();
}
}
@Override public void onClose(Status status, Metadata trailers) {
delegate().onClose(status, trailers);
if (!status.isOk()) {
AbstractSpan activeSpan = ContextManager.activeSpan();
activeSpan.errorOccurred().log(status.getCause());
Tags.STATUS_CODE.set(activeSpan, status.getCode().name());
}
ContextManager.stopSpan();
}
}
}

View File

@ -1,77 +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.Metadata;
import io.grpc.Status;
import java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.tag.Tags;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.grpc.v1.define.Constants;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link StreamClientOnCloseInterceptor} stop the active span when the call end.
*
* @author zhangxin
*/
public class StreamClientOnCloseInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
Status status = (Status)allArguments[0];
if (status.getCode() == Status.Code.UNAVAILABLE) {
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
AbstractSpan span = ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + Constants.STREAM_CALL_OPERATION_NAME_SUFFIX);
span.setComponent(ComponentsDefine.GRPC);
span.setLayer(SpanLayer.RPC_FRAMEWORK);
ContextManager.continued(cachedObjects.getSnapshot());
}
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
AbstractSpan activeSpan = ContextManager.activeSpan();
activeSpan.tag(Constants.ON_NEXT_COUNT_TAG_KEY, String.valueOf(((GRPCDynamicFields)objInst.getSkyWalkingDynamicField()).getOnNextCount()));
Status status = (Status)allArguments[0];
if (status != Status.OK) {
activeSpan.errorOccurred().log(status.asRuntimeException((Metadata)allArguments[1]));
Tags.STATUS_CODE.set(activeSpan, status.getCode().toString());
}
ContextManager.stopSpan();
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -1,62 +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 java.lang.reflect.Method;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.grpc.v1.define.Constants;
import org.apache.skywalking.apm.agent.core.context.ContextManager;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
/**
* {@link ServerCallOnReadyInterceptor} create a local span when the client side is ready for send the message to the
* server side.
*
* @author zhangxin
*/
public class StreamClientOnReadyInterceptor implements InstanceMethodsAroundInterceptor {
@Override
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
MethodInterceptResult result) throws Throwable {
GRPCDynamicFields cachedObjects = (GRPCDynamicFields)objInst.getSkyWalkingDynamicField();
AbstractSpan span = ContextManager.createLocalSpan(cachedObjects.getRequestMethodName() + Constants.STREAM_CALL_OPERATION_NAME_SUFFIX);
span.setComponent(ComponentsDefine.GRPC);
span.setLayer(SpanLayer.RPC_FRAMEWORK);
ContextManager.continued(cachedObjects.getSnapshot());
}
@Override
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
Object ret) throws Throwable {
return ret;
}
@Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
ContextManager.activeSpan().errorOccurred().log(t);
}
}

View File

@ -1,35 +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 org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
/**
* {@link UnaryStreamToFutureConstructorInterceptor} stop the active span when the call end.
*
* @author zhangxin
*/
public class UnaryStreamToFutureConstructorInterceptor implements InstanceConstructorInterceptor {
@Override public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
}
}

View File

@ -16,29 +16,32 @@
*
*/
package org.apache.skywalking.apm.plugin.grpc.v1.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* {@link ManagedChannelInstrumentation} presents that skywalking intercept the <code>newCall</code> method in
* <code>io.grpc.internal.ManagedChannelImpl</code> class by <code>ManagedChannelInterceptor</code>
* {@link AbstractServerImplBuilderInstrumentation} present that the GRPC plugin intercept the method
* <code>addService</code> in the {@link io.grpc.internal.AbstractServerImplBuilder} class by using the {@link
* org.apache.skywalking.apm.plugin.grpc.v1.AbstractServerImplBuilderInterceptor} class.
*
* @author zhangxin
* @author zhang xin
*/
public class ManagedChannelInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.internal.ManagedChannelImpl";
private static final String ENHANCE_METHOD = "newCall";
public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ManagedChannelInterceptor";
public class AbstractServerImplBuilderInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
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 ARGUMENT_TYPE = "io.grpc.ServerServiceDefinition";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
@ -48,7 +51,7 @@ public class ManagedChannelInstrumentation extends ClassInstanceMethodsEnhancePl
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ENHANCE_METHOD);
return named(ENHANCE_METHOD).and(takesArgumentWithType(0, ARGUMENT_TYPE));
}
@Override public String getMethodsInterceptor() {
@ -56,7 +59,7 @@ public class ManagedChannelInstrumentation extends ClassInstanceMethodsEnhancePl
}
@Override public boolean isOverrideArgs() {
return false;
return true;
}
}
};

View File

@ -16,32 +16,45 @@
*
*/
package org.apache.skywalking.apm.plugin.grpc.v1.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* {@link UnaryServerCallHandlerInstrumentation} indicates that skywalking enhance the <code>startCall</code> in
* <code>io.grpc.stub.ServerCalls$StreamingServerCallHandler</code> class by <code>ServerCallHandlerInterceptor</code>.
* {@link AbstractStubInstrumentation} present that the GRPC plugin intercept the method <code>getChannel</code> in the
* {@link io.grpc.stub.AbstractStub} class by using the {@link org.apache.skywalking.apm.plugin.grpc.v1.AbstractStubInterceptor}
* class.
*
* @author zhangxin
* @author zhang xin
*/
public class UnaryServerCallHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$StreamingServerCallHandler";
private static final String ENHANCE_METHOD = "startCall";
public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor";
public class AbstractStubInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.AbstractStubInterceptor";
public static final String ENHANCE_METHOD = "getChannel";
public static final String ENHANCE_CLASS = "io.grpc.stub.AbstractStub";
@Override
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getConstructorMatcher() {
return takesArguments(2);
}
@Override public String getConstructorInterceptor() {
return INTERCEPT_CLASS;
}
}
};
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {

View File

@ -1,81 +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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import static net.bytebuddy.matcher.ElementMatchers.any;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* {@link ClientCallInstrumentation} presents that skywalking intercept the <code>start</code> method in
* <code>io.grpc.internal.ClientCallImpl</code> class by <code>ClientCallsMethodInterceptor</code>
* and the constructor in <code>io.grpc.internal.ClientCallImpl</code> by <code>ClientCallIConstructorInterceptor</code>
*
* @author zhangxin
*/
public class ClientCallInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.internal.ClientCallImpl";
private static final String ENHANCE_METHOD = "start";
public static final String CONSTRUCTOR_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ClientCallIConstructorInterceptor";
public static final String START_METHOD_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ClientCallStartInterceptor";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getConstructorMatcher() {
return any();
}
@Override public String getConstructorInterceptor() {
return CONSTRUCTOR_CLASS;
}
}
};
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ENHANCE_METHOD);
}
@Override public String getMethodsInterceptor() {
return START_METHOD_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return true;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
}

View File

@ -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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
public class ClientCallsInstrumentation extends ClassStaticMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls";
@Override protected StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
return new StaticMethodsInterceptPoint[] {
new StaticMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return (named("asyncUnaryRequestCall").and(takesArgumentWithType(2,"io.grpc.ClientCall$Listener")))
.or(named("asyncStreamingRequestCall"))
.or(named("blockingUnaryCall"))
.or(named("futureUnaryCall"));
}
@Override public String getMethodsInterceptor() {
return "org.apache.skywalking.apm.plugin.grpc.v1.ClientCallsMethodInterceptor";
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
}

View File

@ -1,101 +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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the <code>onReady</code> method
* by <code>ServerCallOnReadyInterceptor</code>, the <code>onHalfClose</code> method
* by <code>ServerCallOnCloseInterceptor</code> and the <code>onMessage</code> method
* by <code>ServerCallOnMessageInterceptor</code> in
* <code>io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener</code> class
*
* @author zhangxin
*/
public class StreamObserverToCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter";
public static final String ON_READY_METHOD = "onReady";
public static final String ON_READY_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.StreamClientOnReadyInterceptor";
public static final String ON_CLASS_METHOD = "onClose";
public static final String ON_CLOSE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.StreamClientOnCloseInterceptor";
public static final String ON_MESSAGE_METHOD = "onMessage";
public static final String ON_MESSAGE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ClientCallOnNextInterceptor";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_READY_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_READY_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_CLASS_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_CLOSE_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_MESSAGE_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_MESSAGE_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return byName(ENHANCE_CLASS);
}
}

View File

@ -1,69 +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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the <code>startCall</code>
* method in <code>io.grpc.stub.ServerCalls$UnaryServerCallHandler</code> class by
* <code>ServerCallHandlerInterceptor</code>
*
* @author zhangxin
*/
public class StreamingServerCallHandlerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$UnaryServerCallHandler";
private static final String ENHANCE_METHOD = "startCall";
public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallHandlerInterceptor";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ENHANCE_METHOD);
}
@Override public String getMethodsInterceptor() {
return INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
}

View File

@ -1,117 +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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the <code>onReady</code> method
* by <code>ServerCallOnReadyInterceptor</code>, the <code>onHalfClose</code> method
* by <code>ServerCallOnCloseInterceptor</code>, the <code>onMessage</code> method by
* <code>ServerCallOnMessageInterceptor</code> and the <code>onCancel</code> method by
* <code>ServerCallOnCancelInterceptor</code> in
* <code>io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener</code> class
*
* @author zhangxin
*/
public class StreamingServerCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$StreamingServerCallHandler$StreamingServerCallListener";
public static final String ON_READY_METHOD = "onReady";
public static final String ON_READ_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor";
public static final String ON_HALF_CLOSE_METHOD = "onHalfClose";
public static final String ON_HALF_CLOSE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor";
public static final String ON_MESSAGE_METHOD = "onMessage";
public static final String ON_MESSAGE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnMessageInterceptor";
public static final String ON_CANCEL_METHOD = "onCancel";
public static final String ON_CANCEL_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_READY_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_READ_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_HALF_CLOSE_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_HALF_CLOSE_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_MESSAGE_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_MESSAGE_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_CANCEL_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_CANCEL_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return byName(ENHANCE_CLASS);
}
}

View File

@ -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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.match.NameMatch;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.any;
/**
* {@link UnaryClientCallListenerInstrumentation} indicates that skywalking enhance the <code>onClose</code> method in
* <code>io.grpc.stub.ClientCalls$UnaryStreamToFuture</code> class by <code>UnaryStreamToFutureConstructorInterceptor</code>
*
* @author zhangxin
*/
public class UnaryClientCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ClientCalls$UnaryStreamToFuture";
public static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.UnaryStreamToFutureConstructorInterceptor";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[] {
new ConstructorInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getConstructorMatcher() {
return any();
}
@Override public String getConstructorInterceptor() {
return INTERCEPT_CLASS;
}
}
};
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[0];
}
@Override protected ClassMatch enhanceClass() {
return NameMatch.byName(ENHANCE_CLASS);
}
}

View File

@ -1,102 +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.define;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
/**
* {@link StreamingServerCallHandlerInstrumentation} presents that skywalking intercept the <code>onReady</code> method
* by <code>ServerCallOnReadyInterceptor</code>, the <code>onHalfClose</code> method
* by <code>ServerCallOnCloseInterceptor</code>, the <code>onMessage</code> method by
* <code>ServerCallOnMessageInterceptor</code> and the <code>onCancel</code> method by
* <code>ServerCallOnCancelInterceptor</code> in
* <code>io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener</code> class
*
* @author zhangxin
*/
public class UnaryServerCallListenerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
private static final String ENHANCE_CLASS = "io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener";
public static final String ON_CLOSE_METHOD = "onHalfClose";
public static final String ON_CLOSE_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnCloseInterceptor";
public static final String ON_READY_METHOD = "onReady";
public static final String ON_READY_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnReadyInterceptor";
public static final String ON_CANCEL_METHOD = "onCancel";
public static final String ON_CANCEL_INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.grpc.v1.ServerCallOnCancelInterceptor";
@Override protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[0];
}
@Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[] {
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_CLOSE_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_CLOSE_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_READY_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_READY_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
},
new InstanceMethodsInterceptPoint() {
@Override public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(ON_CANCEL_METHOD);
}
@Override public String getMethodsInterceptor() {
return ON_CANCEL_INTERCEPT_CLASS;
}
@Override public boolean isOverrideArgs() {
return false;
}
}
};
}
@Override protected ClassMatch enhanceClass() {
return byName(ENHANCE_CLASS);
}
}

View File

@ -1,89 +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.vo;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
/**
* {@link GRPCDynamicFields} contain the require information of span.
*
* @author zhangxin
*/
public class GRPCDynamicFields {
private ServiceDescriptor descriptor;
private Metadata metadata;
private String authority;
private ContextSnapshot snapshot;
private int onNextCount;
public Metadata getMetadata() {
return metadata;
}
public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}
public String getAuthority() {
return authority;
}
public void setAuthority(String authority) {
this.authority = authority;
}
public String getRequestMethodName() {
return descriptor.getServiceName();
}
public void setDescriptor(MethodDescriptor methodDescriptor) {
this.descriptor = new ServiceDescriptor(methodDescriptor);
}
public void setDescriptor(ServiceDescriptor methodDescriptor) {
this.descriptor = methodDescriptor;
}
public ServiceDescriptor getDescriptor() {
return descriptor;
}
public ContextSnapshot getSnapshot() {
return snapshot;
}
public void setSnapshot(ContextSnapshot snapshot) {
this.snapshot = snapshot;
}
public MethodDescriptor.MethodType getMethodType() {
return descriptor.getMethodType();
}
public void incrementOnNextCount() {
onNextCount++;
}
public int getOnNextCount() {
return onNextCount;
}
}

View File

@ -1,9 +1,2 @@
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.ClientCallInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.UnaryClientCallListenerInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.UnaryServerCallListenerInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.UnaryServerCallHandlerInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.ClientCallsInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.ManagedChannelInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.StreamingServerCallHandlerInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.StreamingServerCallListenerInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.StreamObserverToCallListenerInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.AbstractStubInstrumentation
grpc-1.x=org.apache.skywalking.apm.plugin.grpc.v1.define.AbstractServerImplBuilderInstrumentation

View File

@ -1,65 +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.MethodDescriptor;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(MethodDescriptor.class)
public class ClientCallIConstructorInterceptorTest {
private ClientCallIConstructorInterceptor constructorInterceptor;
@Mock
private EnhancedInstance enhancedInstance;
private Object[] arguments;
@Before
public void setUp() {
constructorInterceptor = new ClientCallIConstructorInterceptor();
MethodDescriptor methodDescriptor = mock(MethodDescriptor.class);
when(methodDescriptor.getType()).thenReturn(MethodDescriptor.MethodType.UNARY);
when(methodDescriptor.getFullMethodName()).thenReturn("test/testMethod");
arguments = new Object[] {methodDescriptor};
}
@Test
public void testOnConstructor() {
constructorInterceptor.onConstruct(enhancedInstance, arguments);
verify(enhancedInstance, times(1)).setSkyWalkingDynamicField(Matchers.any());
}
}

View File

@ -1,85 +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 org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(TracingSegmentRunner.class)
public class ClientCallOnNextInterceptorTest {
@SegmentStoragePoint
private SegmentStorage segmentStorage;
@Rule
public AgentServiceRule agentServiceRule = new AgentServiceRule();
@Mock
private EnhancedInstance clientCall;
@Mock
private GRPCDynamicFields cachedObjects;
private ClientCallOnNextInterceptor callOnNextInterceptor;
@Before
public void setUp() {
when(cachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
when(clientCall.getSkyWalkingDynamicField()).thenReturn(cachedObjects);
callOnNextInterceptor = new ClientCallOnNextInterceptor();
}
@Test
public void testCallOnNext() throws Throwable {
callOnNextInterceptor.beforeMethod(clientCall, null, null, null, null);
callOnNextInterceptor.afterMethod(clientCall, null, null, null, null);
verify(cachedObjects, times(1)).incrementOnNextCount();
assertThat(segmentStorage.getTraceSegments().size(), is(1));
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
AbstractTracingSpan span = SegmentHelper.getSpans(traceSegment).get(0);
assertThat(span.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
assertThat(span.isEntry(), is(false));
assertThat(span.isExit(), is(false));
}
}

View File

@ -1,122 +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.MethodDescriptor;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
import org.apache.skywalking.apm.agent.test.tools.SpanAssert;
import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(TracingSegmentRunner.class)
public class ClientCallsMethodInterceptorTest {
@SegmentStoragePoint
private SegmentStorage segmentStorage;
@Rule
public AgentServiceRule agentServiceRule = new AgentServiceRule();
private ClientCallsMethodInterceptor clientCallStartInterceptor;
@Mock
private EnhancedInstance clientCallImpl;
@Mock
private EnhancedInstance clientCallListener;
@Mock
private GRPCDynamicFields unaryCachedObjects;
@Mock
private GRPCDynamicFields streamCachedObjects;
private Object[] arguments;
private Class[] argumentTypes;
@Before
public void setUp() {
when(unaryCachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
when(unaryCachedObjects.getAuthority()).thenReturn("localhost:500051");
when(unaryCachedObjects.getMethodType()).thenReturn(MethodDescriptor.MethodType.UNARY);
when(streamCachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
when(streamCachedObjects.getAuthority()).thenReturn("localhost:500051");
when(streamCachedObjects.getMethodType()).thenReturn(MethodDescriptor.MethodType.SERVER_STREAMING);
arguments = new Object[] {clientCallImpl, clientCallListener};
argumentTypes = new Class[] {clientCallImpl.getClass(), clientCallListener.getClass()};
clientCallStartInterceptor = new ClientCallsMethodInterceptor();
}
@Test
public void testNormalUnaryCallStart() throws Throwable {
when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(unaryCachedObjects);
clientCallStartInterceptor.beforeMethod(null, null, arguments, argumentTypes, null);
clientCallStartInterceptor.afterMethod(null, null, arguments, argumentTypes, null);
assertThat(segmentStorage.getTraceSegments().size(), is(1));
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0);
SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC);
SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK);
SpanAssert.assertOccurException(abstractTracingSpan, false);
}
@Test
public void testNormalStreamCallStart() throws Throwable {
when(clientCallImpl.getSkyWalkingDynamicField()).thenReturn(streamCachedObjects);
clientCallStartInterceptor.beforeMethod(null, null, arguments, argumentTypes, null);
clientCallStartInterceptor.afterMethod(null, null, arguments, argumentTypes, null);
assertThat(segmentStorage.getTraceSegments().size(), is(1));
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(traceSegment).get(0);
SpanAssert.assertComponent(abstractTracingSpan, ComponentsDefine.GRPC);
SpanAssert.assertLayer(abstractTracingSpan, SpanLayer.RPC_FRAMEWORK);
SpanAssert.assertOccurException(abstractTracingSpan, false);
}
}

View File

@ -1,72 +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.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.ServerCall;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PrepareForTest(MethodDescriptor.class)
public class ServerCallHandlerInterceptorTest {
@Mock
private EnhancedInstance enhancedInstance;
private ServerCallHandlerInterceptor callHandlerInterceptor;
@Mock
private ServerCall serverCall;
@Mock
private MethodDescriptor methodDescriptor;
private Metadata metadata;
private Object[] arguments;
private Class[] argumentTypes;
@Before
public void setUp() {
when(methodDescriptor.getFullMethodName()).thenReturn("org.skywalking.test.GreetService/SayHello");
when(serverCall.getMethodDescriptor()).thenReturn(methodDescriptor);
callHandlerInterceptor = new ServerCallHandlerInterceptor();
metadata = new Metadata();
arguments = new Object[] {serverCall, metadata};
argumentTypes = new Class[] {serverCall.getClass(), metadata.getClass()};
}
@Test
public void testSetCachedObjects() throws Throwable {
callHandlerInterceptor.afterMethod(null, null, arguments, argumentTypes, enhancedInstance);
verify(enhancedInstance, times(1)).setSkyWalkingDynamicField(Matchers.any());
}
}

View File

@ -1,86 +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 org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(TracingSegmentRunner.class)
public class ServerCallOnMessageInterceptorTest {
@SegmentStoragePoint
private SegmentStorage segmentStorage;
@Rule
public AgentServiceRule agentServiceRule = new AgentServiceRule();
@Mock
private EnhancedInstance clientCall;
@Mock
private GRPCDynamicFields cachedObjects;
private ServerCallOnMessageInterceptor serverCallOnMessageInterceptor;
@Before
public void setUp() {
when(cachedObjects.getRequestMethodName()).thenReturn("org.skywalking.test.grpc.GreetService.sayHello");
when(clientCall.getSkyWalkingDynamicField()).thenReturn(cachedObjects);
serverCallOnMessageInterceptor = new ServerCallOnMessageInterceptor();
}
@Test
public void testCallOnNext() throws Throwable {
serverCallOnMessageInterceptor.beforeMethod(clientCall, null, null, null, null);
serverCallOnMessageInterceptor.afterMethod(clientCall, null, null, null, null);
verify(cachedObjects, times(1)).incrementOnNextCount();
assertThat(segmentStorage.getTraceSegments().size(), is(1));
TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
assertThat(SegmentHelper.getSpans(traceSegment).size(), is(1));
AbstractTracingSpan span = SegmentHelper.getSpans(traceSegment).get(0);
assertThat(span.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
assertThat(span.isEntry(), is(false));
assertThat(span.isExit(), is(false));
}
}

View File

@ -1,139 +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.Metadata;
import io.grpc.MethodDescriptor;
import org.apache.skywalking.apm.agent.test.tools.SegmentRefAssert;
import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
import org.apache.skywalking.apm.agent.test.helper.SpanHelper;
import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
import org.apache.skywalking.apm.plugin.grpc.v1.vo.GRPCDynamicFields;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.powermock.api.mockito.PowerMockito.when;
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(TracingSegmentRunner.class)
public class ServerCallOnReadyInterceptorTest {
@SegmentStoragePoint
private SegmentStorage segmentStorage;
@Rule
public AgentServiceRule agentServiceRule = new AgentServiceRule();
@Mock
private EnhancedInstance enhancedInstance;
private GRPCDynamicFields cachedObjects;
@Mock
private MethodDescriptor.Marshaller requestMarshaller;
@Mock
private MethodDescriptor.Marshaller responseMarshaller;
private ServerCallOnReadyInterceptor serverCallOnReadyInterceptor;
private ServerCallOnCloseInterceptor serverCallOnCloseInterceptor;
private ServerCallOnMessageInterceptor serverCallOnMessageInterceptor;
@Before
public void setUp() {
cachedObjects = new GRPCDynamicFields();
cachedObjects.setDescriptor(MethodDescriptor.create(MethodDescriptor.MethodType.SERVER_STREAMING, "org.skywalking.test.grpc.GreetService/SayHello", requestMarshaller, responseMarshaller));
when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn(cachedObjects);
serverCallOnReadyInterceptor = new ServerCallOnReadyInterceptor();
serverCallOnCloseInterceptor = new ServerCallOnCloseInterceptor();
serverCallOnMessageInterceptor = new ServerCallOnMessageInterceptor();
}
@Test
public void testOnReadyWithoutContextCarrier() throws Throwable {
cachedObjects.setMetadata(new Metadata());
serverCallOnReadyInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
serverCallOnMessageInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
serverCallOnMessageInterceptor.afterMethod(enhancedInstance, null, null, null, null);
serverCallOnCloseInterceptor.afterMethod(enhancedInstance, null, null, null, null);
assertThat(segmentStorage.getTraceSegments().size(), is(1));
TraceSegment segment = segmentStorage.getTraceSegments().get(0);
assertThat(segment.getRefs() == null, is(true));
assertThat(SegmentHelper.getSpans(segment).size(), is(2));
AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(segment).get(0);
assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
abstractTracingSpan = SegmentHelper.getSpans(segment).get(1);
assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/StreamCall"));
assertThat(abstractTracingSpan.isEntry(), is(true));
assertThat(SpanHelper.getTags(abstractTracingSpan).size(), is(1));
assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getKey(), is("onNext.count"));
assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getValue(), is("1"));
}
@Test
public void testOnReadyWithContextCarrier() throws Throwable {
Metadata metadata = new Metadata();
metadata.put(Metadata.Key.of("sw3", Metadata.ASCII_STRING_MARSHALLER), "1.234.111|3|1|1|#192.168.1.100:50051|#/portal/|#/testEntrySpan|#AQA*#AQA*Et0We0tQNQA*");
cachedObjects.setMetadata(metadata);
serverCallOnReadyInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
serverCallOnMessageInterceptor.beforeMethod(enhancedInstance, null, null, null, null);
serverCallOnMessageInterceptor.afterMethod(enhancedInstance, null, null, null, null);
serverCallOnCloseInterceptor.afterMethod(enhancedInstance, null, null, null, null);
assertThat(segmentStorage.getTraceSegments().size(), is(1));
TraceSegment segment = segmentStorage.getTraceSegments().get(0);
assertThat(segment.getRefs() != null, is(true));
SegmentRefAssert.assertPeerHost(segment.getRefs().get(0), "192.168.1.100:50051");
SegmentRefAssert.assertEntryApplicationInstanceId(segment.getRefs().get(0), 1);
SegmentRefAssert.assertSpanId(segment.getRefs().get(0), 3);
SegmentRefAssert.assertSegmentId(segment.getRefs().get(0), "1.234.111");
assertThat(SegmentHelper.getSpans(segment).size(), is(2));
AbstractTracingSpan abstractTracingSpan = SegmentHelper.getSpans(segment).get(0);
assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/ResponseStreamObserver/OnNext"));
abstractTracingSpan = SegmentHelper.getSpans(segment).get(1);
assertThat(abstractTracingSpan.getOperationName(), is("org.skywalking.test.grpc.GreetService.sayHello/StreamCall"));
assertThat(abstractTracingSpan.isEntry(), is(true));
assertThat(SpanHelper.getTags(abstractTracingSpan).size(), is(1));
assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getKey(), is("onNext.count"));
assertThat(SpanHelper.getTags(abstractTracingSpan).get(0).getValue(), is("1"));
}
}