package com.navercorp.pinpoint.plugin.dubbo.interceptor; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcInvocation; import com.navercorp.pinpoint.bootstrap.context.*; import com.navercorp.pinpoint.bootstrap.interceptor.SpanSimpleAroundInterceptor; import com.navercorp.pinpoint.bootstrap.util.NumberUtils; import com.navercorp.pinpoint.common.trace.ServiceType; import com.navercorp.pinpoint.plugin.dubbo.DubboConstants; /** * @author Jinkai.Ma */ public class DubboProviderInterceptor extends SpanSimpleAroundInterceptor { public DubboProviderInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { super(traceContext, descriptor, DubboProviderInterceptor.class); } @Override protected Trace createTrace(Object target, Object[] args) { Invoker invoker = (Invoker) target; // Ignore monitor service. if (DubboConstants.MONITOR_SERVICE_FQCN.equals(invoker.getInterface().getName())) { return traceContext.disableSampling(); } RpcInvocation invocation = (RpcInvocation) args[0]; // If this transaction is not traceable, mark as disabled. if (invocation.getAttachment(DubboConstants.META_DO_NOT_TRACE) != null) { return traceContext.disableSampling(); } String transactionId = invocation.getAttachment(DubboConstants.META_TRANSACTION_ID); // If there's no trasanction id, a new trasaction begins here. if (transactionId == null) { return traceContext.newTraceObject(); } // otherwise, continue tracing with given data. long parentSpanID = NumberUtils.parseLong(invocation.getAttachment(DubboConstants.META_PARENT_SPAN_ID), SpanId.NULL); long spanID = NumberUtils.parseLong(invocation.getAttachment(DubboConstants.META_SPAN_ID), SpanId.NULL); short flags = NumberUtils.parseShort(invocation.getAttachment(DubboConstants.META_FLAGS), (short) 0); TraceId traceId = traceContext.createTraceId(transactionId, parentSpanID, spanID, flags); return traceContext.continueTraceObject(traceId); } @Override protected void doInBeforeTrace(SpanRecorder recorder, Object target, Object[] args) { RpcInvocation invocation = (RpcInvocation) args[0]; RpcContext rpcContext = RpcContext.getContext(); // You have to record a service type within Server range. recorder.recordServiceType(DubboConstants.DUBBO_PROVIDER_SERVICE_TYPE); // Record rpc name, client address, server address. recorder.recordRpcName(invocation.getInvoker().getInterface().getSimpleName() + ":" + invocation.getMethodName()); recorder.recordEndPoint(rpcContext.getLocalAddressString()); recorder.recordRemoteAddress(rpcContext.getRemoteAddressString()); // If this transaction did not begin here, record parent(client who sent this request) information if (!recorder.isRoot()) { String parentApplicationName = invocation.getAttachment(DubboConstants.META_PARENT_APPLICATION_NAME); if (parentApplicationName != null) { short parentApplicationType = NumberUtils.parseShort(invocation.getAttachment(DubboConstants.META_PARENT_APPLICATION_TYPE), ServiceType.UNDEFINED.getCode()); recorder.recordParentApplication(parentApplicationName, parentApplicationType); // Pinpoint finds caller - callee relation by matching caller's end point and callee's acceptor host. // https://github.com/naver/pinpoint/issues/1395 recorder.recordAcceptorHost(rpcContext.getLocalAddressString()); } } } @Override protected void doInAfterTrace(SpanRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { RpcInvocation invocation = (RpcInvocation) args[0]; recorder.recordApi(methodDescriptor); recorder.recordAttribute(DubboConstants.DUBBO_ARGS_ANNOTATION_KEY, invocation.getArguments()); if (throwable == null) { recorder.recordAttribute(DubboConstants.DUBBO_RESULT_ANNOTATION_KEY, result); } else { recorder.recordException(throwable); } } }