本文主要研究一下skywalking的dubbo-2.7.x-plugin
skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/src/main/resources/skywalking-plugin.def
dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation
skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/asf/dubbo/DubboInstrumentation.java
public class DubboInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { private static final String ENHANCE_CLASS = "org.apache.dubbo.monitor.support.MonitorFilter"; private static final String INTERCEPT_CLASS = "org.apache.skywalking.apm.plugin.asf.dubbo.DubboInterceptor"; @Override protected ClassMatch enhanceClass() { return NameMatch.byName(ENHANCE_CLASS); } @Override public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { return null; } @Override public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { return new InstanceMethodsInterceptPoint[] { new InstanceMethodsInterceptPoint() { @Override public ElementMatcher<MethodDescription> getMethodsMatcher() { return named("invoke"); } @Override public String getMethodsInterceptor() { return INTERCEPT_CLASS; } @Override public boolean isOverrideArgs() { return false; } } }; } }
skywalking-6.6.0/apm-sniffer/apm-sdk-plugin/dubbo-2.7.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/asf/dubbo/DubboInterceptor.java
public class DubboInterceptor implements InstanceMethodsAroundInterceptor { /** * <h2>Consumer:</h2> The serialized trace context data will * inject to the {@link RpcContext#attachments} for transport to provider side. * <p> * <h2>Provider:</h2> The serialized trace context data will extract from * {@link RpcContext#attachments}. current trace segment will ref if the serialize context data is not null. */ @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable { Invoker invoker = (Invoker)allArguments[0]; Invocation invocation = (Invocation)allArguments[1]; RpcContext rpcContext = RpcContext.getContext(); boolean isConsumer = rpcContext.isConsumerSide(); URL requestURL = invoker.getUrl(); AbstractSpan span; final String host = requestURL.getHost(); final int port = requestURL.getPort(); if (isConsumer) { final ContextCarrier contextCarrier = new ContextCarrier(); span = ContextManager.createExitSpan(generateOperationName(requestURL, invocation), contextCarrier, host + ":" + port); //invocation.getAttachments().put("contextData", contextDataStr); //@see https://github.com/alibaba/dubbo/blob/dubbo-2.5.3/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/RpcInvocation.java#L154-L161 CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); rpcContext.getAttachments().put(next.getHeadKey(), next.getHeadValue()); } } else { ContextCarrier contextCarrier = new ContextCarrier(); CarrierItem next = contextCarrier.items(); while (next.hasNext()) { next = next.next(); next.setHeadValue(rpcContext.getAttachment(next.getHeadKey())); } span = ContextManager.createEntrySpan(generateOperationName(requestURL, invocation), contextCarrier); } Tags.URL.set(span, generateRequestURL(requestURL, invocation)); span.setComponent(ComponentsDefine.DUBBO); SpanLayer.asRPCFramework(span); } @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable { Result result = (Result)ret; if (result != null && result.getException() != null) { dealException(result.getException()); } ContextManager.stopSpan(); return ret; } @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) { dealException(t); } /** * Log the throwable, which occurs in Dubbo RPC service. */ private void dealException(Throwable throwable) { AbstractSpan span = ContextManager.activeSpan(); span.errorOccurred(); span.log(throwable); } /** * Format operation name. e.g. org.apache.skywalking.apm.plugin.test.Test.test(String) * * @return operation name. */ private String generateOperationName(URL requestURL, Invocation invocation) { StringBuilder operationName = new StringBuilder(); operationName.append(requestURL.getPath()); operationName.append("." + invocation.getMethodName() + "("); for (Class<?> classes : invocation.getParameterTypes()) { operationName.append(classes.getSimpleName() + ","); } if (invocation.getParameterTypes().length > 0) { operationName.delete(operationName.length() - 1, operationName.length()); } operationName.append(")"); return operationName.toString(); } /** * Format request url. * e.g. dubbo://127.0.0.1:20880/org.apache.skywalking.apm.plugin.test.Test.test(String). * * @return request url. */ private String generateRequestURL(URL url, Invocation invocation) { StringBuilder requestURL = new StringBuilder(); requestURL.append(url.getProtocol() + "://"); requestURL.append(url.getHost()); requestURL.append(":" + url.getPort() + "/"); requestURL.append(generateOperationName(url, invocation)); return requestURL.toString(); } }
DubboInstrumentation继承了ClassInstanceMethodsEnhancePluginDefine,它使用org.apache.skywalking.apm.plugin.asf.dubbo.DubboInterceptor来增强org.apache.dubbo.monitor.support.MonitorFilter的invoke方法