diff --git a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java index c8c5a942e..5837feed1 100644 --- a/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java +++ b/skywalking-collector/skywalking-collector-cluster/src/main/java/com/a/eye/skywalking/collector/actor/AbstractWorker.java @@ -43,8 +43,8 @@ public abstract class AbstractWorker extends UntypedActor { } public void tell(AbstractWorkerProvider targetWorkerProvider, WorkerSelector selector, T message) throws Throwable { - List avaibleWorks = WorkersRefCenter.INSTANCE.availableWorks(targetWorkerProvider.roleName()); - selector.select(avaibleWorks, message).tell(message, getSelf()); + List availableWorks = WorkersRefCenter.INSTANCE.availableWorks(targetWorkerProvider.roleName()); + selector.select(availableWorks, message).tell(message, getSelf()); } void register(Member member) { diff --git a/skywalking-commons/skywalking-trace/pom.xml b/skywalking-commons/skywalking-trace/pom.xml index b6f669f50..59ed8e442 100644 --- a/skywalking-commons/skywalking-trace/pom.xml +++ b/skywalking-commons/skywalking-trace/pom.xml @@ -52,7 +52,7 @@ - src/java/generated-source/protobuf/java + ${basedir}/target/generated-sources/protobuf/java @@ -79,6 +79,8 @@ + + diff --git a/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java b/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java index 67e841e45..6f80d42c2 100644 --- a/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java +++ b/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java @@ -48,22 +48,18 @@ public final class Tags { public static final class SPAN_LAYER { private static StringTag SPAN_LAYER_TAG = new StringTag("span.layer"); - private static final String RDB_LAYER = "rdb"; + private static final String DB_LAYER = "db"; private static final String RPC_FRAMEWORK_LAYER = "rpc"; - private static final String NOSQL_LAYER = "nosql"; private static final String HTTP_LAYER = "http"; - public static void asRDB(Span span) { - SPAN_LAYER_TAG.set(span, RDB_LAYER); + public static void asDB(Span span) { + SPAN_LAYER_TAG.set(span, DB_LAYER); } public static void asRPCFramework(Span span) { SPAN_LAYER_TAG.set(span, RPC_FRAMEWORK_LAYER); } - public static void asNoSQL(Span span) { - SPAN_LAYER_TAG.set(span, NOSQL_LAYER); - } public static void asHttp(Span span) { SPAN_LAYER_TAG.set(span, HTTP_LAYER); @@ -73,18 +69,14 @@ public final class Tags { return SPAN_LAYER_TAG.get(span); } - public static boolean isRDB(Span span) { - return RDB_LAYER.equals(get(span)); + public static boolean isDB(Span span) { + return DB_LAYER.equals(get(span)); } public static boolean isRPCFramework(Span span) { return RPC_FRAMEWORK_LAYER.equals(get(span)); } - public static boolean isNoSQL(Span span) { - return NOSQL_LAYER.equals(get(span)); - } - public static boolean isHttp(Span span) { return HTTP_LAYER.equals(get(span)); } @@ -107,9 +99,24 @@ public final class Tags { public static final StringTag PEER_HOST = new StringTag("peer.host"); /** - * DB_URL records the url of the database access. + * PEER_PORT records remote port of the peer */ - public static final StringTag DB_URL = new StringTag("db.url"); + public static final IntTag PEER_PORT = new IntTag("peer.port"); + + /** + * PEERS records multiple host address and port of remote + */ + public static final StringTag PEERS = new StringTag("peers"); + + /** + * DB_TYPE records database type, such as sql, redis, cassandra and so on. + */ + public static final StringTag DB_TYPE = new StringTag("db.type"); + + /** + * DB_INSTANCE records database instance name. + */ + public static final StringTag DB_INSTANCE = new StringTag("db.instance"); /** * DB_STATEMENT records the sql statement of the database access. diff --git a/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/SpanTestCase.java b/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/SpanTestCase.java index f1b05855b..f2b07877a 100644 --- a/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/SpanTestCase.java +++ b/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/SpanTestCase.java @@ -45,11 +45,10 @@ public class SpanTestCase { Tags.ERROR.set(span1, true); Tags.STATUS_CODE.set(span1, 302); Tags.URL.set(span1, "http://127.0.0.1/serviceA"); - Tags.DB_URL.set(span1, "jdbc:127.0.0.1:user"); Tags.DB_STATEMENT.set(span1, "select * from users"); Map tags = span1.getTags(); - Assert.assertEquals(8, tags.size()); + Assert.assertEquals(7, tags.size()); Assert.assertTrue(Tags.SPAN_LAYER.isHttp(span1)); Assert.assertEquals("127.0.0.1", Tags.PEER_HOST.get(span1)); Assert.assertTrue(Tags.ERROR.get(span1)); diff --git a/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java b/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java index 46843831f..51e6947b9 100644 --- a/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java +++ b/skywalking-commons/skywalking-trace/src/test/java/com/a/eye/skywalking/trace/TraceSegmentTestCase.java @@ -96,7 +96,7 @@ public class TraceSegmentTestCase { segment.archive(span1); Span span2 = new Span(2, span1, "/db/sql"); - Tags.SPAN_LAYER.asNoSQL(span2); + Tags.SPAN_LAYER.asDB(span2); span2.log(new NullPointerException()); segment.archive(span2); diff --git a/skywalking-sniffer/skywalking-agent/src/main/java/com/a/eye/skywalking/agent/SkyWalkingAgent.java b/skywalking-sniffer/skywalking-agent/src/main/java/com/a/eye/skywalking/agent/SkyWalkingAgent.java index 21868ecc7..74a72a64b 100644 --- a/skywalking-sniffer/skywalking-agent/src/main/java/com/a/eye/skywalking/agent/SkyWalkingAgent.java +++ b/skywalking-sniffer/skywalking-agent/src/main/java/com/a/eye/skywalking/agent/SkyWalkingAgent.java @@ -1,15 +1,16 @@ package com.a.eye.skywalking.agent; import com.a.eye.skywalking.agent.junction.SkyWalkingEnhanceMatcher; -import com.a.eye.skywalking.conf.Config; +import com.a.eye.skywalking.api.conf.Config; import com.a.eye.skywalking.api.conf.SnifferConfigInitializer; -import com.a.eye.skywalking.logging.EasyLogResolver; +import com.a.eye.skywalking.api.logging.EasyLogResolver; import com.a.eye.skywalking.api.logging.api.ILog; import com.a.eye.skywalking.api.logging.api.LogManager; import com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefine; import com.a.eye.skywalking.api.plugin.PluginBootstrap; import com.a.eye.skywalking.api.plugin.PluginDefineCategory; -import com.a.eye.skywalking.plugin.PluginException; +import com.a.eye.skywalking.api.plugin.PluginException; + import net.bytebuddy.agent.builder.AgentBuilder; import net.bytebuddy.description.NamedElement; import net.bytebuddy.description.type.TypeDescription; diff --git a/skywalking-sniffer/skywalking-api/pom.xml b/skywalking-sniffer/skywalking-api/pom.xml index 5d898ca26..eff87bd7e 100644 --- a/skywalking-sniffer/skywalking-api/pom.xml +++ b/skywalking-sniffer/skywalking-api/pom.xml @@ -29,7 +29,7 @@ com.a.eye skywalking-trace - 3.0-2017 + ${project.version} com.lmax diff --git a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/EnhanceException.java b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/EnhanceException.java index dec61a839..4e3139f1b 100644 --- a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/EnhanceException.java +++ b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/EnhanceException.java @@ -1,5 +1,6 @@ package com.a.eye.skywalking.api.plugin.interceptor; + import com.a.eye.skywalking.api.plugin.PluginException; public class EnhanceException extends PluginException { diff --git a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassEnhancePluginDefine.java b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassEnhancePluginDefine.java index cd0f92858..4dfd7709e 100644 --- a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassEnhancePluginDefine.java +++ b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassEnhancePluginDefine.java @@ -10,6 +10,7 @@ import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; import com.a.eye.skywalking.api.plugin.interceptor.StaticMethodsInterceptPoint; import com.a.eye.skywalking.api.util.StringUtil; + import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.implementation.MethodDelegation; @@ -25,7 +26,7 @@ import static net.bytebuddy.matcher.ElementMatchers.not; * This class controls all enhance operations, including enhance constructors, instance methods and static methods. * All the enhances base on three types interceptor point: {@link ConstructorInterceptPoint}, {@link InstanceMethodsInterceptPoint} and {@link StaticMethodsInterceptPoint} * If plugin is going to enhance constructors, instance methods, or both, - * {@link ClassEnhancePluginDefine} will add a field of {@link EnhancedClassInstanceContext} type. + * {@link ClassEnhancePluginDefine} will add a field of {@link com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext} type. * * @author wusheng */ @@ -44,7 +45,6 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi * @param enhanceOriginClassName target class name * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. - * @throws PluginException */ @Override protected DynamicType.Builder enhance(String enhanceOriginClassName, DynamicType.Builder newClassBuilder) throws PluginException { @@ -61,7 +61,6 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi * @param enhanceOriginClassName target class name * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. - * @throws PluginException */ private DynamicType.Builder enhanceInstance(String enhanceOriginClassName, DynamicType.Builder newClassBuilder) throws PluginException { ConstructorInterceptPoint[] constructorInterceptPoints = getConstructorsInterceptPoints(); @@ -150,7 +149,6 @@ public abstract class ClassEnhancePluginDefine extends AbstractClassEnhancePlugi * @param enhanceOriginClassName target class name * @param newClassBuilder byte-buddy's builder to manipulate class bytecode. * @return new byte-buddy's builder for further manipulation. - * @throws PluginException */ private DynamicType.Builder enhanceClass(String enhanceOriginClassName, DynamicType.Builder newClassBuilder) throws PluginException { StaticMethodsInterceptPoint[] staticMethodsInterceptPoints = getStaticMethodsInterceptPoints(); diff --git a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassInstanceMethodsEnhancePluginDefine.java b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassInstanceMethodsEnhancePluginDefine.java index 9a3888775..8f5cb2a0e 100644 --- a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassInstanceMethodsEnhancePluginDefine.java +++ b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/api/plugin/interceptor/enhance/ClassInstanceMethodsEnhancePluginDefine.java @@ -1,5 +1,6 @@ package com.a.eye.skywalking.api.plugin.interceptor.enhance; + import com.a.eye.skywalking.api.plugin.interceptor.StaticMethodsInterceptPoint; /** diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/DubboBuriedPointType.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/DubboBuriedPointType.java deleted file mode 100644 index d165ae736..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/DubboBuriedPointType.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.a.eye.skywalking.api.plugin.dubbo; - -import com.a.eye.skywalking.api.IBuriedPointType; - -public enum DubboBuriedPointType implements IBuriedPointType { - INSTANCE; - - @Override - public String getTypeName() { - return "D"; - } - - @Override - public CallType getCallType() { - return CallType.SYNC; - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/DubboPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/DubboPluginDefine.java deleted file mode 100644 index 90a1eaf95..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/DubboPluginDefine.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.a.eye.skywalking.api.plugin.dubbo; - -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -public class DubboPluginDefine extends ClassInstanceMethodsEnhancePluginDefine { - @Override - protected String enhanceClassName() { - return "com.alibaba.dubbo.monitor.support.MonitorFilter"; - } - - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return null; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("invoke"); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.dubbo.MonitorFilterInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/MonitorFilterInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/MonitorFilterInterceptor.java deleted file mode 100644 index 22e01ebf6..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbo/MonitorFilterInterceptor.java +++ /dev/null @@ -1,155 +0,0 @@ -package com.a.eye.skywalking.api.plugin.dubbo; - -import com.a.eye.skywalking.api.plugin.dubbox.bugfix.below283.BugFixAcitve; -import com.a.eye.skywalking.api.plugin.dubbox.bugfix.below283.SWBaseBean; -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; -import com.a.eye.skywalking.invoke.monitor.RPCServerInvokeMonitor; -import com.a.eye.skywalking.model.ContextData; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcContext; - -public class MonitorFilterInterceptor implements InstanceMethodsAroundInterceptor { - @Override - public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - MethodInterceptResult result) { - Object[] arguments = interceptorContext.allArguments(); - Invoker invoker = (Invoker) arguments[0]; - Invocation invocation = (Invocation) arguments[1]; - - RpcContext rpcContext = RpcContext.getContext(); - boolean isConsumer = rpcContext.isConsumerSide(); - context.set("isConsumer", isConsumer); - if (isConsumer) { - ContextData contextData = - new RPCClientInvokeMonitor().beforeInvoke(createIdentification(invoker, invocation, true)); - String contextDataStr = contextData.toString(); - - //追加参数 - if (!BugFixAcitve.isActive) { - // context.setAttachment("contextData", contextDataStr); - // context的setAttachment方法在重试机制的时候并不会覆盖原有的Attachment - // 参见Dubbo源代码:“com.alibaba.dubbo.rpc.RpcInvocation” - // public void setAttachmentIfAbsent(String key, String value) { - // if (attachments == null) { - // attachments = new HashMap(); - // } - // if (! attachments.containsKey(key)) { - // attachments.put(key, value); - // } - // } - // 在Rest模式中attachment会被抹除,不会传入到服务端 - // Rest模式会将attachment存放到header里面,具体见com.alibaba.dubbo.rpc.protocol.rest.RpcContextFilter - //invocation.getAttachments().put("contextData", contextDataStr); - rpcContext.getAttachments().put("contextData", contextDataStr); - } else { - fix283SendNoAttachmentIssue(invocation, contextDataStr); - } - } else { - // 读取参数 - String contextDataStr; - - if (!BugFixAcitve.isActive) { - contextDataStr = rpcContext.getAttachment("contextData"); - } else { - contextDataStr = fix283RecvNoAttachmentIssue(invocation); - } - - ContextData contextData = null; - if (contextDataStr != null && contextDataStr.length() > 0) { - contextData = new ContextData(contextDataStr); - } - - new RPCServerInvokeMonitor().beforeInvoke(contextData, createIdentification(invoker, invocation, false)); - } - - } - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - Object ret) { - Result result = (Result) ret; - if (result != null && result.getException() != null) { - dealException(result.getException(), context); - } - - if (isConsumer(context)) { - new RPCClientInvokeMonitor().afterInvoke(); - } else { - new RPCServerInvokeMonitor().afterInvoke(); - } - - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext) { - dealException(t, context); - } - - - private boolean isConsumer(EnhancedClassInstanceContext context) { - return (Boolean) context.get("isConsumer"); - } - - private void dealException(Throwable t, EnhancedClassInstanceContext context) { - if (isConsumer(context)) { - new RPCClientInvokeMonitor().occurException(t); - } else { - new RPCServerInvokeMonitor().occurException(t); - } - } - - private static Identification createIdentification(Invoker invoker, Invocation invocation, boolean isConsumer) { - StringBuilder viewPoint = new StringBuilder(); - if (isConsumer) { - viewPoint.append("comsumer:"); - } else { - viewPoint.append("provider:"); - } - viewPoint.append(invoker.getUrl().getProtocol() + "://"); - viewPoint.append(invoker.getUrl().getHost()); - viewPoint.append(":" + invoker.getUrl().getPort()); - viewPoint.append(invoker.getUrl().getAbsolutePath()); - viewPoint.append("." + invocation.getMethodName() + "("); - for (Class classes : invocation.getParameterTypes()) { - viewPoint.append(classes.getSimpleName() + ","); - } - - if (invocation.getParameterTypes().length > 0) { - viewPoint.delete(viewPoint.length() - 1, viewPoint.length()); - } - - viewPoint.append(")"); - return Identification.newBuilder().viewPoint(viewPoint.toString()).spanType(DubboBuriedPointType.INSTANCE) - .build(); - } - - - private static void fix283SendNoAttachmentIssue(Invocation invocation, String contextDataStr) { - - for (Object parameter : invocation.getArguments()) { - if (parameter instanceof SWBaseBean) { - ((SWBaseBean) parameter).setContextData(contextDataStr); - return; - } - } - } - - private static String fix283RecvNoAttachmentIssue(Invocation invocation) { - for (Object parameter : invocation.getArguments()) { - if (parameter instanceof SWBaseBean) { - return ((SWBaseBean) parameter).getContextData(); - } - } - - return null; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbox/bugfix/below283/BugFixAcitve.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbox/bugfix/below283/BugFixAcitve.java deleted file mode 100644 index 735c6868e..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbox/bugfix/below283/BugFixAcitve.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.a.eye.skywalking.api.plugin.dubbox.bugfix.below283; - -public final class BugFixAcitve { - public static boolean isActive = false; - - public BugFixAcitve(){ - isActive = true; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbox/bugfix/below283/SWBaseBean.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbox/bugfix/below283/SWBaseBean.java deleted file mode 100644 index 42dca3074..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/api/plugin/dubbox/bugfix/below283/SWBaseBean.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.a.eye.skywalking.api.plugin.dubbox.bugfix.below283; - -import java.io.Serializable; - -public class SWBaseBean implements Serializable { - private String contextData; - - public String getContextData() { - return contextData; - } - - public void setContextData(String contextData) { - this.contextData = contextData; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbo/DubboInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbo/DubboInstrumentation.java new file mode 100644 index 000000000..402b45d93 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbo/DubboInstrumentation.java @@ -0,0 +1,49 @@ +package com.a.eye.skywalking.plugin.dubbo; + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link DubboInstrumentation} presents that skywalking intercepts {@link com.alibaba.dubbo.monitor.support.MonitorFilter#invoke(Invoker, Invocation)} + * by using {@link DubboInterceptor}. + * + * @author zhangxin + */ +public class DubboInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.alibaba.dubbo.monitor.support.MonitorFilter"; + private static final String INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.dubbo.DubboInterceptor"; + + @Override + protected String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("invoke"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbo/DubboInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbo/DubboInterceptor.java new file mode 100644 index 000000000..eea854141 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbo/DubboInterceptor.java @@ -0,0 +1,185 @@ +package com.a.eye.skywalking.plugin.dubbo; + +import com.a.eye.skywalking.api.context.ContextCarrier; +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.plugin.dubbox.BugFixActive; +import com.a.eye.skywalking.plugin.dubbox.SWBaseBean; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcContext; + +/** + * {@link DubboInterceptor} define how to enhance class {@link com.alibaba.dubbo.monitor.support.MonitorFilter#invoke(Invoker, Invocation)}. + * the trace context transport to the provider side by {@link RpcContext#attachments}.but all the version of dubbo framework below 2.8.3 + * don't support {@link RpcContext#attachments}, we support another way to support it. it is that all request parameters of dubbo service + * need to extend {@link SWBaseBean}, and {@link DubboInterceptor} will inject the trace context data to the {@link SWBaseBean} bean and + * extract the trace context data from {@link SWBaseBean}, or the trace context data will not transport to the provider side. + * + * @author zhangxin + */ +public class DubboInterceptor implements InstanceMethodsAroundInterceptor { + + public static final String ATTACHMENT_NAME_OF_CONTEXT_DATA = "contextData"; + public static final String DUBBO_COMPONENT = "Dubbo"; + + /** + *

Consumer:

+ * The serialized trace context data will inject the first param that extend {@link SWBaseBean} of dubbo service + * if the method {@link BugFixActive#active()} be called. or the serialized context data will inject to the + * {@link RpcContext#attachments} for transport to provider side. + * + *

Provider:

+ * The serialized trace context data will extract from the first param that extend {@link SWBaseBean} of dubbo service + * if the method {@link BugFixActive#active()} be called. or it will extract from {@link RpcContext#attachments}. + * current trace segment will ref if the serialize context data is not null. + */ + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + MethodInterceptResult result) { + Object[] arguments = interceptorContext.allArguments(); + Invoker invoker = (Invoker) arguments[0]; + Invocation invocation = (Invocation) arguments[1]; + RpcContext rpcContext = RpcContext.getContext(); + boolean isConsumer = rpcContext.isConsumerSide(); + URL requestURL = invoker.getUrl(); + + Span span = ContextManager.INSTANCE.createSpan(generateOperationName(requestURL, invocation)); + Tags.URL.set(span, generateRequestURL(requestURL, invocation)); + Tags.COMPONENT.set(span, DUBBO_COMPONENT); + Tags.PEER_HOST.set(span, requestURL.getHost()); + Tags.PEER_PORT.set(span, requestURL.getPort()); + Tags.SPAN_LAYER.asRPCFramework(span); + + if (isConsumer) { + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT); + ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.INSTANCE.inject(contextCarrier); + if (!BugFixActive.isActive()) { + //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 + rpcContext.getAttachments().put(ATTACHMENT_NAME_OF_CONTEXT_DATA, contextCarrier.serialize()); + } else { + fix283SendNoAttachmentIssue(invocation, contextCarrier); + } + } else { + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_SERVER); + + ContextCarrier contextCarrier; + if (!BugFixActive.isActive()) { + contextCarrier = new ContextCarrier().deserialize(rpcContext.getAttachment(ATTACHMENT_NAME_OF_CONTEXT_DATA)); + } else { + contextCarrier = fix283RecvNoAttachmentIssue(invocation); + } + + if (contextCarrier != null) { + ContextManager.INSTANCE.extract(contextCarrier); + } + } + } + + /** + * Execute after {@link com.alibaba.dubbo.monitor.support.MonitorFilter#invoke(Invoker, Invocation)}, + * when dubbo instrumentation is active。Check {@link Result#getException()} , if not NULL, + * log the exception and set tag error=true. + */ + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + Object ret) { + Result result = (Result) ret; + if (result != null && result.getException() != null) { + dealException(result.getException()); + } + + ContextManager.INSTANCE.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + dealException(t); + } + + /** + * Log the throwable, which occurs in Dubbo RPC service. + */ + private void dealException(Throwable throwable) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(throwable); + } + + /** + * Format operation name. e.g. com.a.eye.skywalking.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/com.a.eye.skywalking.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(); + } + + /** + * Set the trace context. + * + * @param contextCarrier {@link ContextCarrier}. + */ + private void fix283SendNoAttachmentIssue(Invocation invocation, ContextCarrier contextCarrier) { + for (Object parameter : invocation.getArguments()) { + if (parameter instanceof SWBaseBean) { + ((SWBaseBean) parameter).setTraceContext(contextCarrier.serialize()); + return; + } + } + } + + /** + * Fetch the trace context by using {@link Invocation#getArguments()}. + * + * @return trace context data. + */ + private ContextCarrier fix283RecvNoAttachmentIssue(Invocation invocation) { + for (Object parameter : invocation.getArguments()) { + if (parameter instanceof SWBaseBean) { + return new ContextCarrier().deserialize(((SWBaseBean) parameter).getTraceContext()); + } + } + + return null; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbox/BugFixActive.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbox/BugFixActive.java new file mode 100644 index 000000000..937f80279 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbox/BugFixActive.java @@ -0,0 +1,28 @@ +package com.a.eye.skywalking.plugin.dubbox; + +/** + * {@link BugFixActive#active} is an flag that present the dubbox version is below 2.8.3, + * The version 2.8.3 of dubbox don't support attachment. so skywalking provided another way + * to support the function that transport the serialized context data. The way is that + * all parameters of dubbo service need to extend {@link SWBaseBean}, {@link com.a.eye.skywalking.plugin.dubbo.DubboInterceptor} + * fetch the serialized context data by using {@link SWBaseBean#getTraceContext()}. + * + * @author zhangxin + */ +public final class BugFixActive { + + private static boolean active = false; + + /** + * Set active status, before startup dubbo services. + */ + public static void active() { + BugFixActive.active = true; + } + + + public static boolean isActive() { + return BugFixActive.active; + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbox/SWBaseBean.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbox/SWBaseBean.java new file mode 100644 index 000000000..6fe4bd57e --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/a/eye/skywalking/plugin/dubbox/SWBaseBean.java @@ -0,0 +1,24 @@ +package com.a.eye.skywalking.plugin.dubbox; + +import java.io.Serializable; + +/** + * All the request parameter of dubbox service need to extend {@link SWBaseBean} to transport + * the serialized trace context to the provider side if the version of dubbox is below 2.8.3. + * + * @author zhangxin + */ +public class SWBaseBean implements Serializable { + /** + * Serialized trace context. + */ + private String traceContext; + + public String getTraceContext() { + return traceContext; + } + + public void setTraceContext(String traceContext) { + this.traceContext = traceContext; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def index 15f3c8eeb..3833d6e87 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -com.a.eye.skywalking.plugin.dubbo.DubboPluginDefine +com.a.eye.skywalking.plugin.dubbo.DubboInstrumentation diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/a/eye/skywalking/plugin/dubbo/DubboInterceptorTest.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/a/eye/skywalking/plugin/dubbo/DubboInterceptorTest.java new file mode 100644 index 000000000..d964fb79a --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/a/eye/skywalking/plugin/dubbo/DubboInterceptorTest.java @@ -0,0 +1,229 @@ +package com.a.eye.skywalking.plugin.dubbo; + +import com.a.eye.skywalking.api.context.TracerContext; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.plugin.dubbox.BugFixActive; +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert; +import com.a.eye.skywalking.trace.LogData; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.TraceSegment; +import com.a.eye.skywalking.trace.TraceSegmentRef; +import com.a.eye.skywalking.trace.tag.Tags; +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcContext; + +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; + + +@RunWith(PowerMockRunner.class) +@PrepareForTest({RpcContext.class, BugFixActive.class}) +public class DubboInterceptorTest { + + private MockTracerContextListener mockTracerContextListener; + private DubboInterceptor dubboInterceptor; + private RequestParamForTestBelow283 testParam; + @Mock + private RpcContext rpcContext; + @Mock + private Invoker invoker; + @Mock + private Invocation invocation; + @Mock + private EnhancedClassInstanceContext classInstanceContext; + @Mock + private InstanceMethodInvokeContext methodInvokeContext; + @Mock + private MethodInterceptResult methodInterceptResult; + @Mock + private Result result; + + @Before + public void setUp() throws Exception { + dubboInterceptor = new DubboInterceptor(); + testParam = new RequestParamForTestBelow283(); + mockTracerContextListener = new MockTracerContextListener(); + TracerContext.ListenerManager.add(mockTracerContextListener); + + mockStatic(RpcContext.class); + mockStatic(BugFixActive.class); + when(invoker.getUrl()).thenReturn(URL.valueOf("dubbo://127.0.0.1:20880/com.a.eye.skywalking.test.TestDubboService")); + when(invocation.getMethodName()).thenReturn("test"); + when(invocation.getParameterTypes()).thenReturn(new Class[]{String.class}); + when(invocation.getArguments()).thenReturn(new Object[]{testParam}); + Mockito.when(RpcContext.getContext()).thenReturn(rpcContext); + when(rpcContext.isConsumerSide()).thenReturn(true); + when(methodInvokeContext.allArguments()).thenReturn(new Object[]{invoker, invocation}); + } + + + @Test + public void testConsumerBelow283() { + when(BugFixActive.isActive()).thenReturn(true); + + dubboInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + dubboInterceptor.afterMethod(classInstanceContext, methodInvokeContext, result); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertConsumerSpan(traceSegment.getSpans().get(0)); + testParam.assertSelf("0", "127.0.0.1"); + } + }); + } + + @Test + public void testConsumerWithAttachment() { + dubboInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + dubboInterceptor.afterMethod(classInstanceContext, methodInvokeContext, result); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertConsumerSpan(traceSegment.getSpans().get(0)); + } + }); + } + + @Test + public void testConsumerWithException() { + dubboInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + dubboInterceptor.handleMethodException(new RuntimeException(), classInstanceContext, methodInvokeContext); + dubboInterceptor.afterMethod(classInstanceContext, methodInvokeContext, result); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertConsumerTraceSegmentInErrorCase(traceSegment); + } + }); + } + + @Test + public void testConsumerWithResultHasException() { + when(result.getException()).thenReturn(new RuntimeException()); + + dubboInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + dubboInterceptor.afterMethod(classInstanceContext, methodInvokeContext, result); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertConsumerTraceSegmentInErrorCase(traceSegment); + } + }); + } + + @Test + public void testProviderWithAttachment() { + when(rpcContext.isConsumerSide()).thenReturn(false); + when(rpcContext.getAttachment(DubboInterceptor.ATTACHMENT_NAME_OF_CONTEXT_DATA)).thenReturn("302017.1487666919810.624424584.17332.1.1|1|REMOTE_APP|127.0.0.1"); + + dubboInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + dubboInterceptor.afterMethod(classInstanceContext, methodInvokeContext, result); + assertProvider(); + } + + + @Test + public void testProviderBelow283() { + when(rpcContext.isConsumerSide()).thenReturn(false); + when(BugFixActive.isActive()).thenReturn(true); + + testParam.setTraceContext("302017.1487666919810.624424584.17332.1.1|1|REMOTE_APP|127.0.0.1"); + + + dubboInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + dubboInterceptor.afterMethod(classInstanceContext, methodInvokeContext, result); + + assertProvider(); + } + + + private void assertConsumerTraceSegmentInErrorCase(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertConsumerSpan(traceSegment.getSpans().get(0)); + Span span = traceSegment.getSpans().get(0); + assertThat(span.getLogs().size(), is(1)); + assertErrorLog(span.getLogs().get(0)); + } + + private void assertErrorLog(LogData logData) { + assertThat(logData.getFields().size(), is(4)); + assertThat(logData.getFields().get("event"), CoreMatchers.is("error")); + assertThat(logData.getFields().get("error.kind"), CoreMatchers.is(RuntimeException.class.getName())); + assertNull(logData.getFields().get("message")); + } + + + private void assertProvider() { + final TraceSegmentRef expect = new TraceSegmentRef(); + expect.setSpanId(1); + expect.setTraceSegmentId("302017.1487666919810.624424584.17332.1.1"); + + mockTracerContextListener.assertSize(1); + mockTracerContextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + assertProviderSpan(traceSegment.getSpans().get(0)); + assertTraceSegmentRef(traceSegment.getPrimaryRef(), expect); + } + }); + } + + private void assertTraceSegmentRef(TraceSegmentRef actual, TraceSegmentRef expect) { + assertThat(actual.getSpanId(), is(expect.getSpanId())); + assertThat(actual.getTraceSegmentId(), is(expect.getTraceSegmentId())); + } + + + private void assertProviderSpan(Span span) { + assertCommonsAttribute(span); + assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_SERVER)); + } + + private void assertConsumerSpan(Span span) { + assertCommonsAttribute(span); + assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_CLIENT)); + } + + private void assertCommonsAttribute(Span span) { + assertThat(Tags.SPAN_LAYER.isRPCFramework(span), is(true)); + assertThat(Tags.COMPONENT.get(span), is(DubboInterceptor.DUBBO_COMPONENT)); + assertThat(Tags.URL.get(span), is("dubbo://127.0.0.1:20880/com.a.eye.skywalking.test.TestDubboService.test(String)")); + assertThat(span.getOperationName(), is("com.a.eye.skywalking.test.TestDubboService.test(String)")); + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(mockTracerContextListener); + } + +} \ No newline at end of file diff --git a/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/a/eye/skywalking/plugin/dubbo/RequestParamForTestBelow283.java b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/a/eye/skywalking/plugin/dubbo/RequestParamForTestBelow283.java new file mode 100644 index 000000000..3a0173903 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/a/eye/skywalking/plugin/dubbo/RequestParamForTestBelow283.java @@ -0,0 +1,24 @@ +package com.a.eye.skywalking.plugin.dubbo; + +import com.a.eye.skywalking.plugin.dubbox.SWBaseBean; + +import static org.hamcrest.CoreMatchers.endsWith; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; + +/** + * {@link RequestParamForTestBelow283} store context data for test. + */ +public class RequestParamForTestBelow283 extends SWBaseBean { + + /** + * This method assert that {@link SWBaseBean#getTraceContext()} if it's not null and context data + * will end with the expect span id. + * + * @param expectSpanId expect span id + */ + public void assertSelf(String expectSpanId, String expectHost) { + assertNotNull(getTraceContext()); + assertThat(getTraceContext(), endsWith(expectSpanId + "|" + expectHost)); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/HttpClientExecuteInterceptor.java deleted file mode 100644 index 514dd6151..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/HttpClientExecuteInterceptor.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4; - -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import org.apache.http.HttpHost; -import org.apache.http.HttpRequest; - -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; - -public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { - /** - * default headname of sky walking context
- */ - public static String TRACE_HEAD_NAME = "SkyWalking-TRACING-NAME"; - - private static RPCClientInvokeMonitor rpcClientInvokeMonitor = new RPCClientInvokeMonitor(); - - @Override - public void beforeMethod(EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { - Object[] allArguments = interceptorContext.allArguments(); - if (allArguments[0] == null || allArguments[1] == null) { - // illegal args, can't trace. ignore. - return; - } - HttpHost httpHost = (HttpHost) allArguments[0]; - HttpRequest httpRequest = (HttpRequest) allArguments[1]; - httpRequest - .setHeader( - TRACE_HEAD_NAME, - "ContextData=" - + rpcClientInvokeMonitor.beforeInvoke( - Identification - .newBuilder() - .viewPoint( - httpHost.toURI() - .toString()) - .spanType( - WebBuriedPointType - .INSTANCE) - .build()).toString()); - } - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext, Object ret) { - Object[] allArguments = interceptorContext.allArguments(); - if (allArguments[0] == null || allArguments[1] == null) { - // illegal args, can't trace. ignore. - return ret; - } - rpcClientInvokeMonitor.afterInvoke(); - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { - Object[] allArguments = interceptorContext.allArguments(); - if (allArguments[0] == null || allArguments[1] == null) { - // illegal args, can't trace. ignore. - return; - } - rpcClientInvokeMonitor.occurException(t); - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/WebBuriedPointType.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/WebBuriedPointType.java deleted file mode 100644 index b4e60faa7..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/WebBuriedPointType.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4; - -import com.a.eye.skywalking.api.IBuriedPointType; - -public enum WebBuriedPointType implements IBuriedPointType { - INSTANCE; - - @Override - public String getTypeName() { - return "W"; - } - - @Override - public CallType getCallType() { - return CallType.SYNC; - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/AbstractHttpClientPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/AbstractHttpClientPluginDefine.java deleted file mode 100644 index 33f7505fe..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/AbstractHttpClientPluginDefine.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4.define; - -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -public class AbstractHttpClientPluginDefine extends HttpClientPluginDefine { - - @Override - public String enhanceClassName() { - return "org.apache.http.impl.client.AbstractHttpClient"; - } - - /** - * version 4.2, intercept method: execute, intercept
- * public final HttpResponse execute(HttpHost target, HttpRequest request, - * HttpContext context)
- * - */ - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("doExecute"); - } - - @Override - public String getMethodsInterceptor() { - return getInstanceMethodsInterceptor(); - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/HttpClientPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/HttpClientPluginDefine.java deleted file mode 100644 index fd1616114..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/HttpClientPluginDefine.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4.define; - -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; - -public abstract class HttpClientPluginDefine extends ClassInstanceMethodsEnhancePluginDefine { - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return null; - } - - protected String getInstanceMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.httpClient.v4.HttpClientExecuteInterceptor"; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java new file mode 100644 index 000000000..860be92f4 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/HttpClientExecuteInterceptor.java @@ -0,0 +1,85 @@ +package com.a.eye.skywalking.plugin.httpClient.v4; + + +import com.a.eye.skywalking.api.context.ContextCarrier; +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; + +/** + * {@link HttpClientExecuteInterceptor} transport the trace context by call {@link HttpRequest#setHeader(Header)}, + * The current span tag the {@link Tags#ERROR} if {@link StatusLine#getStatusCode()} is not equals 200. + * + * @author zhangxin + */ +public class HttpClientExecuteInterceptor implements InstanceMethodsAroundInterceptor { + public static final String HEADER_NAME_OF_CONTEXT_DATA = "SKYWALKING_CONTEXT_DATA"; + + @Override + public void beforeMethod(EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { + Object[] allArguments = interceptorContext.allArguments(); + if (allArguments[0] == null || allArguments[1] == null) { + // illegal args, can't trace. ignore. + return; + } + HttpHost httpHost = (HttpHost) allArguments[0]; + HttpRequest httpRequest = (HttpRequest) allArguments[1]; + + Span span = ContextManager.INSTANCE.createSpan(httpRequest.getRequestLine().getUri()); + Tags.PEER_PORT.set(span, httpHost.getPort()); + Tags.PEER_HOST.set(span, httpHost.getHostName()); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT); + Tags.URL.set(span, generateURL(httpHost, httpRequest)); + Tags.SPAN_LAYER.asHttp(span); + + ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.INSTANCE.inject(contextCarrier); + httpRequest.setHeader(HEADER_NAME_OF_CONTEXT_DATA, contextCarrier.serialize()); + } + + /** + * Format request URL. + * + * @return request URL + */ + private String generateURL(HttpHost httpHost, HttpRequest httpRequest) { + return httpHost.getSchemeName() + "://" + httpHost.getHostName() + ":" + httpHost.getPort() + httpRequest.getRequestLine().getUri(); + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext, Object ret) { + Object[] allArguments = interceptorContext.allArguments(); + if (allArguments[0] == null || allArguments[1] == null) { + return ret; + } + + HttpResponse response = (HttpResponse) ret; + int statusCode = response.getStatusLine().getStatusCode(); + Span span = ContextManager.INSTANCE.activeSpan(); + if (statusCode != 200) { + Tags.ERROR.set(span, true); + } + + Tags.STATUS_CODE.set(span, statusCode); + ContextManager.INSTANCE.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { + ContextManager.INSTANCE.activeSpan().log(t); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/AbstractHttpClientInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/AbstractHttpClientInstrumentation.java new file mode 100644 index 000000000..2734ca906 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/AbstractHttpClientInstrumentation.java @@ -0,0 +1,50 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking intercepts + * {@link org.apache.http.impl.client.AbstractHttpClient#doExecute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class AbstractHttpClientInstrumentation extends HttpClientInstrumentation { + + private static final String ENHANCE_CLASS = "org.apache.http.impl.client.AbstractHttpClient"; + + @Override + public String enhanceClassName() { + return ENHANCE_CLASS; + } + + /** + * version 4.2, intercept method: execute, intercept
+ * public final HttpResponse execute(HttpHost target, HttpRequest request, + * HttpContext context)
+ */ + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("doExecute"); + } + + @Override + public String getMethodsInterceptor() { + return getInstanceMethodsInterceptor(); + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/DefaultRequestDirectorPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/DefaultRequestDirectorInstrumentation.java similarity index 52% rename from skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/DefaultRequestDirectorPluginDefine.java rename to skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/DefaultRequestDirectorInstrumentation.java index 540b2fbbf..4670f0b09 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/DefaultRequestDirectorPluginDefine.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/DefaultRequestDirectorInstrumentation.java @@ -1,12 +1,31 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4.define; +package com.a.eye.skywalking.plugin.httpClient.v4.define; + import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + import static net.bytebuddy.matcher.ElementMatchers.named; -public class DefaultRequestDirectorPluginDefine extends HttpClientPluginDefine { +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking intercepts + * {@link org.apache.http.impl.client.DefaultRequestDirector#execute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class DefaultRequestDirectorInstrumentation extends HttpClientInstrumentation { + + /** + * Enhance class. + */ + private static final String enhanceClass = "org.apache.http.impl.client.DefaultRequestDirector"; + /** * DefaultRequestDirector is default implement.
* usually use in version 4.0-4.2
@@ -14,12 +33,12 @@ public class DefaultRequestDirectorPluginDefine extends HttpClientPluginDefine { */ @Override public String enhanceClassName() { - return "org.apache.http.impl.client.DefaultRequestDirector"; + return enhanceClass; } @Override protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] {new InstanceMethodsInterceptPoint() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { @Override public ElementMatcher getMethodsMatcher() { return named("execute"); diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/HttpClientInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/HttpClientInstrumentation.java new file mode 100644 index 000000000..3649e8c1b --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/HttpClientInstrumentation.java @@ -0,0 +1,25 @@ +package com.a.eye.skywalking.plugin.httpClient.v4.define; + + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; + +/** + * {@link HttpClientInstrumentation} present that skywalking intercepts {@link HttpClientInstrumentation#enhanceClassName()} + * by using {@link com.a.eye.skywalking.plugin.httpClient.v4.HttpClientExecuteInterceptor} + * + * @author zhangxin + */ +public abstract class HttpClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.httpClient.v4.HttpClientExecuteInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + protected String getInstanceMethodsInterceptor() { + return INTERCEPT_CLASS; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/InternalHttpClientPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/InternalHttpClientInstrumentation.java similarity index 55% rename from skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/InternalHttpClientPluginDefine.java rename to skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/InternalHttpClientInstrumentation.java index 832c3390d..8afbc35ac 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/InternalHttpClientPluginDefine.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/InternalHttpClientInstrumentation.java @@ -1,15 +1,30 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4.define; +package com.a.eye.skywalking.plugin.httpClient.v4.define; + import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + import static net.bytebuddy.matcher.ElementMatchers.named; -public class InternalHttpClientPluginDefine extends HttpClientPluginDefine { +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking intercepts {@link org.apache.http.impl.client.InternalHttpClient#doExecute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class InternalHttpClientInstrumentation extends HttpClientInstrumentation { + + private static final String ENHANCE_CLASS = "org.apache.http.impl.client.InternalHttpClient"; + @Override public String enhanceClassName() { - return "org.apache.http.impl.client.InternalHttpClient"; + return ENHANCE_CLASS; } @Override diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/MinimalHttpClientPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/MinimalHttpClientInstrumentation.java similarity index 55% rename from skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/MinimalHttpClientPluginDefine.java rename to skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/MinimalHttpClientInstrumentation.java index 100a8a37f..dca1b29cf 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/httpClient/v4/define/MinimalHttpClientPluginDefine.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/java/com/a/eye/skywalking/plugin/httpClient/v4/define/MinimalHttpClientInstrumentation.java @@ -1,15 +1,31 @@ -package com.a.eye.skywalking.api.plugin.httpClient.v4.define; +package com.a.eye.skywalking.plugin.httpClient.v4.define; + import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; + import net.bytebuddy.description.method.MethodDescription; import net.bytebuddy.matcher.ElementMatcher; +import org.apache.http.HttpHost; +import org.apache.http.HttpRequest; +import org.apache.http.protocol.HttpContext; + import static net.bytebuddy.matcher.ElementMatchers.named; -public class MinimalHttpClientPluginDefine extends HttpClientPluginDefine { +/** + * {@link AbstractHttpClientInstrumentation} presents that skywalking + * intercepts {@link org.apache.http.impl.client.MinimalHttpClient#doExecute(HttpHost, HttpRequest, HttpContext)} + * by using {@link HttpClientInstrumentation#INTERCEPT_CLASS}. + * + * @author zhangxin + */ +public class MinimalHttpClientInstrumentation extends HttpClientInstrumentation { + + private static final String ENHANCE_CLASS = "org.apache.http.impl.client.MinimalHttpClient"; + @Override public String enhanceClassName() { - return "org.apache.http.impl.client.MinimalHttpClient"; + return ENHANCE_CLASS; } @Override diff --git a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def index 200935980..da07902ec 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def +++ b/skywalking-sniffer/skywalking-sdk-plugin/httpClient-4.x-plugin/src/main/resources/skywalking-plugin.def @@ -1,4 +1,4 @@ -com.a.eye.skywalking.plugin.httpClient.v4.define.AbstractHttpClientPluginDefine -com.a.eye.skywalking.plugin.httpClient.v4.define.InternalHttpClientPluginDefine -com.a.eye.skywalking.plugin.httpClient.v4.define.MinimalHttpClientPluginDefine -com.a.eye.skywalking.plugin.httpClient.v4.define.DefaultRequestDirectorPluginDefine +com.a.eye.skywalking.plugin.httpClient.v4.define.AbstractHttpClientInstrumentation +com.a.eye.skywalking.plugin.httpClient.v4.define.InternalHttpClientInstrumentation +com.a.eye.skywalking.plugin.httpClient.v4.define.MinimalHttpClientInstrumentation +com.a.eye.skywalking.plugin.httpClient.v4.define.DefaultRequestDirectorInstrumentation diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/pom.xml b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/pom.xml index 43e773797..db239652d 100755 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/pom.xml +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/pom.xml @@ -1,68 +1,74 @@ - - skywalking-sdk-plugin - com.a.eye - 3.0-2017 - - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + skywalking-sdk-plugin + com.a.eye + 3.0-2017 + + 4.0.0 - skywalking-jdbc-plugin - jar + skywalking-jdbc-plugin + jar - jdbc-plugin - http://maven.apache.org + jdbc-plugin + http://maven.apache.org - - UTF-8 - + + UTF-8 + - - - com.a.eye - skywalking-api - 3.0-2017 - - - mysql - mysql-connector-java - 5.1.36 - test - - - com.oracle - ojdbc14 - 10.2.0.4.0 - test - - - com.h2database - h2 - 1.4.192 - test - - + + + com.a.eye + skywalking-api + 3.0-2017 + + + mysql + mysql-connector-java + 5.1.36 + test + + + com.oracle + ojdbc14 + 10.2.0.4.0 + test + + + com.h2database + h2 + 1.4.192 + provided + + + mysql + mysql-connector-java + [2.0.14,) + provided + + - - - - org.apache.maven.plugins - maven-deploy-plugin - - - - org.apache.maven.plugins - maven-source-plugin - - - - attach-sources - - jar - - - - - - + + + + org.apache.maven.plugins + maven-deploy-plugin + + + + org.apache.maven.plugins + maven-source-plugin + + + + attach-sources + + jar + + + + + + diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/CallableStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/CallableStatementTracing.java deleted file mode 100644 index 48dc1b55e..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/CallableStatementTracing.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc; - -import com.a.eye.skywalking.api.plugin.jdbc.define.JDBCBuriedPointType; -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; -import com.a.eye.skywalking.model.Identification; - -import java.sql.SQLException; - -/** - * 连接级追踪,用于追踪用于Connection的操作追踪 - * - * @author wusheng - */ -public class CallableStatementTracing { - private static RPCClientInvokeMonitor rpcClientInvokeMonitor = new RPCClientInvokeMonitor(); - - public static R execute(java.sql.CallableStatement realStatement, - String connectInfo, String method, String sql, Executable exec) - throws SQLException { - try { - rpcClientInvokeMonitor.beforeInvoke(Identification - .newBuilder() - .viewPoint(connectInfo) - .businessKey( - "callableStatement." - + method - + (sql == null || sql.length() == 0 ? "" - : ":" + sql)).spanType(JDBCBuriedPointType.INSTANCE).build()); - return exec.exe(realStatement, sql); - } catch (SQLException e) { - rpcClientInvokeMonitor.occurException(e); - throw e; - } finally { - rpcClientInvokeMonitor.afterInvoke(); - } - } - - public interface Executable { - public R exe(java.sql.CallableStatement realConnection, String sql) - throws SQLException; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/ConnectionTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/ConnectionTracing.java deleted file mode 100755 index d100efa44..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/ConnectionTracing.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc; - -import com.a.eye.skywalking.api.plugin.jdbc.define.JDBCBuriedPointType; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; - -import java.sql.SQLException; - -/** - * 连接级追踪,用于追踪用于Connection的操作追踪 - * - * @author wusheng - */ -public class ConnectionTracing { - private static RPCClientInvokeMonitor rpcClientInvokeMonitor = new RPCClientInvokeMonitor(); - - public static R execute(java.sql.Connection realConnection, - String connectInfo, String method, String sql, Executable exec) - throws SQLException { - try { - rpcClientInvokeMonitor.beforeInvoke(Identification - .newBuilder() - .viewPoint(connectInfo) - .businessKey( - "connection." - + method - + (sql == null || sql.length() == 0 ? "" - : ":" + sql)).spanType(JDBCBuriedPointType.INSTANCE).build()); - return exec.exe(realConnection, sql); - } catch (SQLException e) { - rpcClientInvokeMonitor.occurException(e); - throw e; - } finally { - rpcClientInvokeMonitor.afterInvoke(); - } - } - - public interface Executable { - public R exe(java.sql.Connection realConnection, String sql) - throws SQLException; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/PreparedStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/PreparedStatementTracing.java deleted file mode 100644 index d20d97106..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/PreparedStatementTracing.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc; - -import com.a.eye.skywalking.api.context.ContextManager; -import com.a.eye.skywalking.trace.Span; -import com.a.eye.skywalking.trace.tag.Tags; -import java.sql.SQLException; - -/** - * 连接级追踪,用于追踪用于Connection的操作追踪 - * - * @author wusheng - */ -public class PreparedStatementTracing { - - public static R execute(java.sql.PreparedStatement realStatement, - String connectInfo, String method, String sql, Executable exec) - throws SQLException { - Span span = ContextManager.INSTANCE.createSpan("JDBC/PreparedStatement/" + method); - try { - Tags.SPAN_LAYER.asRDB(span); - Tags.DB_URL.set(span, connectInfo); - Tags.DB_STATEMENT.set(span, sql); - return exec.exe(realStatement, sql); - } catch (SQLException e) { - span.log(e); - throw e; - } finally { - ContextManager.INSTANCE.stopSpan(span); - } - } - - public interface Executable { - R exe(java.sql.PreparedStatement realConnection, String sql) - throws SQLException; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/StatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/StatementTracing.java deleted file mode 100644 index 1ee9749de..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/StatementTracing.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc; - -import com.a.eye.skywalking.api.plugin.jdbc.define.JDBCBuriedPointType; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; - -import java.sql.SQLException; - -/** - * 连接级追踪,用于追踪用于Statement的操作追踪 - * - * @author wusheng - */ -public class StatementTracing { - private static RPCClientInvokeMonitor rpcClientInvokeMonitor = new RPCClientInvokeMonitor(); - - public static R execute(java.sql.Statement realStatement, - String connectInfo, String method, String sql, Executable exec) - throws SQLException { - try { - rpcClientInvokeMonitor.beforeInvoke(Identification - .newBuilder() - .viewPoint(connectInfo) - .businessKey( - "statement." - + method - + (sql == null || sql.length() == 0 ? "" - : ":" + sql)).spanType(JDBCBuriedPointType.INSTANCE).build()); - return exec.exe(realStatement, sql); - } catch (SQLException e) { - rpcClientInvokeMonitor.occurException(e); - throw e; - } finally { - rpcClientInvokeMonitor.afterInvoke(); - } - } - - public interface Executable { - public R exe(java.sql.Statement realStatement, String sql) - throws SQLException; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/AbstractDatabasePluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/AbstractDatabasePluginDefine.java deleted file mode 100644 index e0f452d45..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/AbstractDatabasePluginDefine.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc.define; - -import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -public abstract class AbstractDatabasePluginDefine extends ClassInstanceMethodsEnhancePluginDefine { - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return null; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("connect"); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.jdbc.define.JDBCDriverInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/H2PluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/H2PluginDefine.java deleted file mode 100644 index 14c32bd17..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/H2PluginDefine.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc.define; - -public class H2PluginDefine extends AbstractDatabasePluginDefine { - @Override - protected String enhanceClassName() { - return "org.h2.Driver"; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/JDBCBuriedPointType.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/JDBCBuriedPointType.java deleted file mode 100644 index a1aa965d2..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/JDBCBuriedPointType.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc.define; - -import com.a.eye.skywalking.api.IBuriedPointType; - -public enum JDBCBuriedPointType implements IBuriedPointType { - - INSTANCE; - - @Override - public String getTypeName() { - return "J"; - } - - @Override - public CallType getCallType() { - return CallType.LOCAL; - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/MysqlPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/MysqlPluginDefine.java deleted file mode 100644 index c286ac49f..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/MysqlPluginDefine.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc.define; - -/** - * Created by xin on 16/8/4. - */ -public class MysqlPluginDefine extends AbstractDatabasePluginDefine { - @Override - protected String enhanceClassName() { - return "com.mysql.jdbc.Driver"; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/OraclePluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/OraclePluginDefine.java deleted file mode 100644 index 05fb9e3c0..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/OraclePluginDefine.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jdbc.define; - -/** - * Created by xin on 16/8/4. - */ -public class OraclePluginDefine extends AbstractDatabasePluginDefine { - @Override - protected String enhanceClassName() { - return "oracle.jdbc.OracleDriver"; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java new file mode 100644 index 000000000..c295c3676 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/CallableStatementTracing.java @@ -0,0 +1,51 @@ +package com.a.eye.skywalking.plugin.jdbc; + + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link CallableStatementTracing} create span with the {@link Span#operationName} start with + * "JDBC/CallableStatement/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class CallableStatementTracing { + + public static R execute(java.sql.CallableStatement realStatement, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/CallableStatement/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realStatement, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.CallableStatement realConnection, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionInfo.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionInfo.java new file mode 100644 index 000000000..3cf0a3d28 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionInfo.java @@ -0,0 +1,63 @@ +package com.a.eye.skywalking.plugin.jdbc; + +/** + * {@link ConnectionInfo} stored the jdbc connection info, the connection info contains db type, host, port, database name. + * The {@link #hosts} be null if {@link #host} is not null. + * + * @author zhangxin + */ +public class ConnectionInfo { + /** + * DB type, such as mysql, oracle, h2. + */ + private final String dbType; + /** + * Database host name. + */ + private String host; + /** + * Database port. + */ + private int port; + /** + * Operation database name. + */ + private final String databaseName; + /** + * Database hosts. + */ + private String hosts; + + public ConnectionInfo(String dbType, String host, int port, String databaseName) { + this.dbType = dbType; + this.host = host; + this.port = port; + this.databaseName = databaseName; + } + + public ConnectionInfo(String dbType, String hosts, String databaseName) { + this.dbType = dbType; + this.hosts = hosts; + this.databaseName = databaseName; + } + + public String getDBType() { + return dbType; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + public String getDatabaseName() { + return databaseName; + } + + public String getHosts() { + return hosts; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java new file mode 100755 index 000000000..35d7417e4 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/ConnectionTracing.java @@ -0,0 +1,51 @@ +package com.a.eye.skywalking.plugin.jdbc; + + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link ConnectionTracing} create span with the {@link Span#operationName} start with + * "JDBC/Connection/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class ConnectionTracing { + + public static R execute(java.sql.Connection realConnection, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/Connection/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realConnection, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.Connection realConnection, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java new file mode 100644 index 000000000..ed181b94a --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java @@ -0,0 +1,50 @@ +package com.a.eye.skywalking.plugin.jdbc; + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link PreparedStatementTracing} create span with the {@link Span#operationName} start with + * "JDBC/PreparedStatement/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class PreparedStatementTracing { + + public static R execute(java.sql.PreparedStatement realStatement, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/PreparedStatement/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realStatement, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.PreparedStatement realConnection, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWCallableStatement.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatement.java similarity index 99% rename from skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWCallableStatement.java rename to skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatement.java index 70141c53d..6b9fa5a6f 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWCallableStatement.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWCallableStatement.java @@ -1,4 +1,4 @@ -package com.a.eye.skywalking.api.plugin.jdbc; +package com.a.eye.skywalking.plugin.jdbc; import java.io.InputStream; import java.io.Reader; @@ -11,11 +11,11 @@ import java.util.Map; public class SWCallableStatement implements CallableStatement { private Connection realConnection; private CallableStatement realStatement; - private String connectInfo; + private ConnectionInfo connectInfo; private String sql; SWCallableStatement(Connection realConnection, - CallableStatement realStatement, String connectInfo, + CallableStatement realStatement, ConnectionInfo connectInfo, String sql) { this.realConnection = realConnection; this.realStatement = realStatement; diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWConnection.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java similarity index 92% rename from skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWConnection.java rename to skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java index d95766a2d..919927cd7 100755 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWConnection.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWConnection.java @@ -1,19 +1,33 @@ -package com.a.eye.skywalking.api.plugin.jdbc; +package com.a.eye.skywalking.plugin.jdbc; -import java.sql.*; +import com.a.eye.skywalking.plugin.jdbc.connectionurl.parser.URLParser; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; -public class SWConnection implements java.sql.Connection { - private String connectInfo; +public class SWConnection implements Connection { + private ConnectionInfo connectInfo; + private final Connection realConnection; - private final java.sql.Connection realConnection; - - public SWConnection(String url, Properties info, - java.sql.Connection realConnection) { + public SWConnection(String url, Properties info, Connection realConnection) { super(); - this.connectInfo = url + "(" + info.getProperty("user") + ")"; + this.connectInfo = URLParser.parser(url); this.realConnection = realConnection; } diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWPreparedStatement.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWPreparedStatement.java similarity index 99% rename from skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWPreparedStatement.java rename to skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWPreparedStatement.java index 12cec2459..57186d0ce 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWPreparedStatement.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWPreparedStatement.java @@ -1,4 +1,4 @@ -package com.a.eye.skywalking.api.plugin.jdbc; +package com.a.eye.skywalking.plugin.jdbc; import java.io.InputStream; import java.io.Reader; @@ -10,11 +10,11 @@ import java.util.Calendar; public class SWPreparedStatement implements PreparedStatement { private Connection realConnection; private PreparedStatement realStatement; - private String connectInfo; + private ConnectionInfo connectInfo; private String sql; SWPreparedStatement(Connection realConnection, - PreparedStatement realStatement, String connectInfo, + PreparedStatement realStatement, ConnectionInfo connectInfo, String sql) { this.realConnection = realConnection; this.realStatement = realStatement; diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWStatement.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWStatement.java similarity index 98% rename from skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWStatement.java rename to skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWStatement.java index 1a3cd2b49..2d212b7a5 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/SWStatement.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/SWStatement.java @@ -1,4 +1,4 @@ -package com.a.eye.skywalking.api.plugin.jdbc; +package com.a.eye.skywalking.plugin.jdbc; import java.sql.Connection; import java.sql.ResultSet; @@ -9,9 +9,9 @@ import java.sql.SQLWarning; public class SWStatement implements java.sql.Statement { private Connection realConnection; private java.sql.Statement realStatement; - private String connectInfo; + private ConnectionInfo connectInfo; - SWStatement(Connection realConnection, java.sql.Statement realStatement, String connectInfo) { + SWStatement(Connection realConnection, java.sql.Statement realStatement, ConnectionInfo connectInfo) { this.realConnection = realConnection; this.realStatement = realStatement; this.connectInfo = connectInfo; diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java new file mode 100644 index 000000000..4e4e4f316 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/StatementTracing.java @@ -0,0 +1,50 @@ +package com.a.eye.skywalking.plugin.jdbc; + + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import java.sql.SQLException; + +/** + * {@link StatementTracing} create span with the {@link Span#operationName} start with + * "JDBC/Statement/"and set {@link ConnectionInfo#dbType} to the {@link Tags#COMPONENT}. + * + * Notice: {@link Tags#PEERS} may be is null if database connection url don't contain multiple hosts. + * + * @author zhangxin + */ +public class StatementTracing { + public static R execute(java.sql.Statement realStatement, + ConnectionInfo connectInfo, String method, String sql, Executable exec) + throws SQLException { + try { + Span span = ContextManager.INSTANCE.createSpan("JDBC/Statement/" + method); + Tags.DB_TYPE.set(span, "sql"); + Tags.DB_INSTANCE.set(span, connectInfo.getDatabaseName()); + Tags.DB_STATEMENT.set(span, sql); + Tags.COMPONENT.set(span, connectInfo.getDBType()); + if (!StringUtil.isEmpty(connectInfo.getHosts())) { + Tags.PEERS.set(span, connectInfo.getHosts()); + } else { + Tags.PEER_PORT.set(span, connectInfo.getPort()); + Tags.PEER_HOST.set(span, connectInfo.getHost()); + } + return exec.exe(realStatement, sql); + } catch (SQLException e) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(); + } + } + + public interface Executable { + R exe(java.sql.Statement realStatement, String sql) + throws SQLException; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/AbstractURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/AbstractURLParser.java new file mode 100644 index 000000000..37afca5c4 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/AbstractURLParser.java @@ -0,0 +1,54 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +public abstract class AbstractURLParser implements ConnectionURLParser { + + protected String url; + + public AbstractURLParser(String url) { + this.url = url; + } + + /** + * Fetch the index range that database host and port from connection url. + * + * @return index range that database hosts. + */ + protected abstract int[] fetchDatabaseHostsIndexRange(); + + /** + * Fetch the index range that database name from connection url. + * + * @return index range that database name. + */ + protected abstract int[] fetchDatabaseNameIndexRange(); + + /** + * Fetch database host(s) from connection url. + * + * @return database host(s). + */ + protected String fetchDatabaseHostsFromURL() { + int[] indexRange = fetchDatabaseHostsIndexRange(); + return url.substring(indexRange[0], indexRange[1]); + } + + /** + * Fetch database name from connection url. + * + * @return database name. + */ + protected String fetchDatabaseNameFromURL() { + int[] indexRange = fetchDatabaseNameIndexRange(); + return url.substring(indexRange[0], indexRange[1]); + } + + /** + * Fetch database name from connection url. + * + * @return database name. + */ + protected String fetchDatabaseNameFromURL(int[] indexRange) { + return url.substring(indexRange[0], indexRange[1]); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/ConnectionURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/ConnectionURLParser.java new file mode 100644 index 000000000..78be61a3f --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/ConnectionURLParser.java @@ -0,0 +1,13 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + + +public interface ConnectionURLParser { + /** + * {@link ConnectionURLParser} parses database name and the database host(s) from connection url. + * + * @return connection info. + */ + ConnectionInfo parse(); +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/H2URLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/H2URLParser.java new file mode 100644 index 000000000..55b1ae115 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/H2URLParser.java @@ -0,0 +1,112 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link H2URLParser} presents that skywalking how to parse the connection url of H2 database. + * {@link ConnectionInfo#host} will return localhost and {@link ConnectionInfo#port} will return + * -1 if H2 running with memory mode or file mode, or it will return the host and the port. + * + * {@link H2URLParser} check the connection url if contains "file" or "mem". if yes. the database + * name substring the connection url from the index after "file" index or the "mem" index to the + * index of first charset ";". + * + * The {@link ConnectionInfo#host} be set the string between charset "//" and the first charset "/" after + * the charset "//", and {@link ConnectionInfo#databaseName} be set the string between the last index of "/" and + * the first charset ";". + * + * @author zhangxin + */ +public class H2URLParser extends AbstractURLParser { + + private static final String LOCALHOST = "localhost"; + private static final int DEFAULT_PORT = 8084; + /** + * Flag that H2 running with file mode. + */ + private static final String FILE_MODE_FLAG = "file"; + /** + * Flag that H2 running with memory mode. + */ + private static final String MEMORY_MODE_FLAG = "mem"; + private static final String H2_DB_TYPE = "H2"; + + public H2URLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + return new int[]{hostLabelStartIndex + 2, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf(";"); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new int[]{databaseStartTag + 1, databaseEndTag}; + } + + @Override + public ConnectionInfo parse() { + int[] databaseNameRangeIndex = fetchDatabaseNameRangeIndexFromURLForH2FileMode(); + if (databaseNameRangeIndex != null) { + return new ConnectionInfo(H2_DB_TYPE, LOCALHOST, -1, fetchDatabaseNameFromURL(databaseNameRangeIndex)); + } + + databaseNameRangeIndex = fetchDatabaseNameRangeIndexFromURLForH2MemMode(); + if (databaseNameRangeIndex != null) { + return new ConnectionInfo(H2_DB_TYPE, LOCALHOST, -1, fetchDatabaseNameFromURL(databaseNameRangeIndex)); + } + + String[] hostAndPort = fetchDatabaseHostsFromURL().split(":"); + if (hostAndPort.length == 1) { + return new ConnectionInfo(H2_DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + } else { + return new ConnectionInfo(H2_DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL()); + } + } + + /** + * Fetch range index that the database name from connection url if H2 database running with file mode. + * + * @return range index that the database name. + */ + private int[] fetchDatabaseNameRangeIndexFromURLForH2FileMode() { + int fileLabelIndex = url.indexOf(FILE_MODE_FLAG); + int parameterLabelIndex = url.indexOf(";", fileLabelIndex); + if (parameterLabelIndex == -1) { + parameterLabelIndex = url.length(); + } + + if (fileLabelIndex != -1) { + return new int[]{fileLabelIndex + FILE_MODE_FLAG.length() + 1, parameterLabelIndex}; + } else { + return null; + } + } + + /** + * Fetch range index that the database name from connection url if H2 database running with memory mode. + * + * @return range index that the database name. + */ + private int[] fetchDatabaseNameRangeIndexFromURLForH2MemMode() { + int fileLabelIndex = url.indexOf(MEMORY_MODE_FLAG); + int parameterLabelIndex = url.indexOf(";", fileLabelIndex); + if (parameterLabelIndex == -1) { + parameterLabelIndex = url.length(); + } + + if (fileLabelIndex != -1) { + return new int[]{fileLabelIndex + MEMORY_MODE_FLAG.length() + 1, parameterLabelIndex}; + } else { + return null; + } + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/MysqlURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/MysqlURLParser.java new file mode 100644 index 000000000..d03336374 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/MysqlURLParser.java @@ -0,0 +1,66 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link MysqlURLParser} parse connection url of mysql. + * + * The {@link ConnectionInfo#host} be set the string between charset "//" and the first + * charset "/" after the charset "//", and {@link ConnectionInfo#databaseName} be set the + * string between the last index of "/" and the first charset "?". but one more thing, the + * {@link ConnectionInfo#hosts} be set if the host container multiple host. + * + * @author zhangxin + */ +public class MysqlURLParser extends AbstractURLParser { + + private static final int DEFAULT_PORT = 3306; + private static final String DB_TYPE = "Mysql"; + + public MysqlURLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("//"); + int hostLabelEndIndex = url.indexOf("/", hostLabelStartIndex + 2); + return new int[]{hostLabelStartIndex + 2, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + int databaseStartTag = url.lastIndexOf("/"); + int databaseEndTag = url.indexOf("?", databaseStartTag); + if (databaseEndTag == -1) { + databaseEndTag = url.length(); + } + return new int[]{databaseStartTag + 1, databaseEndTag}; + } + + @Override + public ConnectionInfo parse() { + int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); + String hosts = url.substring(hostRangeIndex[0], hostRangeIndex[1]); + String[] hostSegment = hosts.split(","); + if (hostSegment.length > 1) { + StringBuilder sb = new StringBuilder(); + for (String host : hostSegment) { + if (host.split(":").length == 1) { + sb.append(host + ":" + DEFAULT_PORT + ","); + } else { + sb.append(host + ","); + } + } + return new ConnectionInfo(DB_TYPE, sb.toString(), fetchDatabaseNameFromURL()); + } else { + String[] hostAndPort = hostSegment[0].split(":"); + if (hostAndPort.length != 1) { + return new ConnectionInfo(DB_TYPE, hostAndPort[0], Integer.valueOf(hostAndPort[1]), fetchDatabaseNameFromURL()); + } else { + return new ConnectionInfo(DB_TYPE, hostAndPort[0], DEFAULT_PORT, fetchDatabaseNameFromURL()); + } + } + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/OracleURLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/OracleURLParser.java new file mode 100644 index 000000000..658a975e0 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/OracleURLParser.java @@ -0,0 +1,56 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link OracleURLParser} presents that how to parse oracle connection url. + * + * The {@link ConnectionInfo#host} be set the string between charset "@" and the last + * charset ":" after the charset "@", and {@link ConnectionInfo#databaseName} be set the + * string that after the last index of ":". + * + * Note: {@link OracleURLParser} can parse the commons connection url. the commons + * connection url is of the form: jdbc:oracle::@,the other + * the form of connection url cannot be parsed success. + * + * @author zhangxin + */ +public class OracleURLParser extends AbstractURLParser { + + private static final String DB_TYPE = "Oracle"; + private static final int DEFAULT_PORT = 1521; + + public OracleURLParser(String url) { + super(url); + } + + @Override + protected int[] fetchDatabaseHostsIndexRange() { + int hostLabelStartIndex = url.indexOf("@"); + int hostLabelEndIndex = url.lastIndexOf(":"); + return new int[]{hostLabelStartIndex + 1, hostLabelEndIndex}; + } + + @Override + protected int[] fetchDatabaseNameIndexRange() { + return new int[0]; + } + + @Override + public ConnectionInfo parse() { + int[] hostRangeIndex = fetchDatabaseHostsIndexRange(); + String host = fetchDatabaseHostsFromURL(); + String[] hostSegment = splitDatabaseAddress(host); + String databaseName = url.substring(hostRangeIndex[1] + 1); + if (hostSegment.length == 1) { + return new ConnectionInfo(DB_TYPE, host, DEFAULT_PORT, databaseName); + } else { + return new ConnectionInfo(DB_TYPE, hostSegment[0], Integer.valueOf(hostSegment[1]), databaseName); + } + } + + private String[] splitDatabaseAddress(String address) { + String[] hostSegment = address.split(":"); + return hostSegment; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParser.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParser.java new file mode 100644 index 000000000..c93fef6c4 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParser.java @@ -0,0 +1,28 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +/** + * {@link URLParser#parser(String)} support parse the connection url, such as Mysql, Oracle, H2 Database. + * But there are some url cannot be parsed, such as Oracle connection url with multiple host. + * + * @author zhangxin + */ +public class URLParser { + + private static final String MYSQL_JDBC_URL_PREFIX = "jdbc:mysql"; + private static final String ORACLE_JDBC_URL_PREFIX = "jdbc:oracle"; + private static final String H2_JDBC_URL_PREFIX = "jdbc:h2"; + + public static ConnectionInfo parser(String url) { + ConnectionURLParser parser = null; + if (url.startsWith(MYSQL_JDBC_URL_PREFIX)) { + parser = new MysqlURLParser(url); + } else if (url.startsWith(ORACLE_JDBC_URL_PREFIX)) { + parser = new OracleURLParser(url); + } else if (url.startsWith(H2_JDBC_URL_PREFIX)) { + parser = new H2URLParser(url); + } + return parser.parse(); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/AbstractDatabaseInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/AbstractDatabaseInstrumentation.java new file mode 100644 index 000000000..6ca54fe34 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/AbstractDatabaseInstrumentation.java @@ -0,0 +1,45 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.jdbc.SWConnection; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import java.util.Properties; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * JDBC plugin using {@link JDBCDriverInterceptor} to intercept all the class that it has extend {@link java.sql.Driver#connect(String, Properties)}, + * and change the return object to {@link com.a.eye.skywalking.plugin.jdbc.SWConnection}, All the method of {@link com.a.eye.skywalking.plugin.jdbc.SWConnection} + * is delegate to the real JDBC Driver Connection object. + * + * @author zhangxin + */ +public abstract class AbstractDatabaseInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jdbc.define.JDBCDriverInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("connect"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/H2Instrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/H2Instrumentation.java new file mode 100644 index 000000000..2e521b0cc --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/H2Instrumentation.java @@ -0,0 +1,16 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +/** + * {@link H2Instrumentation} presents that skywalking intercepts {@link org.h2.Driver}. + * + * @author zhangxin + */ +public class H2Instrumentation extends AbstractDatabaseInstrumentation { + + private static final String CLASS_OF_INTERCEPT_H2_DRIVER = "org.h2.Driver"; + + @Override + protected String enhanceClassName() { + return CLASS_OF_INTERCEPT_H2_DRIVER; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/JDBCDriverInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/JDBCDriverInterceptor.java similarity index 60% rename from skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/JDBCDriverInterceptor.java rename to skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/JDBCDriverInterceptor.java index 577e43622..41f4c09c1 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jdbc/define/JDBCDriverInterceptor.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/JDBCDriverInterceptor.java @@ -1,32 +1,38 @@ -package com.a.eye.skywalking.api.plugin.jdbc.define; +package com.a.eye.skywalking.plugin.jdbc.define; import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.jdbc.SWConnection; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.plugin.jdbc.SWConnection; import java.sql.Connection; import java.util.Properties; +/** + * {@link JDBCDriverInterceptor} return {@link SWConnection} when {@link java.sql.Driver} to create connection, + * instead of the {@link Connection} instance. + * + * @author zhangxin + */ public class JDBCDriverInterceptor implements InstanceMethodsAroundInterceptor { @Override public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - MethodInterceptResult result) { + MethodInterceptResult result) { + // do nothing } @Override public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - Object ret) { + Object ret) { return new SWConnection((String) interceptorContext.allArguments()[0], (Properties) interceptorContext.allArguments()[1], (Connection) ret); } @Override public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext) { - + InstanceMethodInvokeContext interceptorContext) { + // do nothing. } } diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/MysqlInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/MysqlInstrumentation.java new file mode 100644 index 000000000..b1d4aca8f --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/MysqlInstrumentation.java @@ -0,0 +1,13 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +/** + * {@link MysqlInstrumentation} presents that skywalking intercepts {@link com.mysql.jdbc.Driver}. + * + * @author zhangxin + */ +public class MysqlInstrumentation extends AbstractDatabaseInstrumentation { + @Override + protected String enhanceClassName() { + return "com.mysql.jdbc.Driver"; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/OracleInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/OracleInstrumentation.java new file mode 100644 index 000000000..c19bca7ba --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/define/OracleInstrumentation.java @@ -0,0 +1,14 @@ +package com.a.eye.skywalking.plugin.jdbc.define; + +/** + * {@link OracleInstrumentation} presents that skywalking intercepts the class oracle.jdbc.OracleDriver + * . + * + * @author zhangxin + */ +public class OracleInstrumentation extends AbstractDatabaseInstrumentation { + @Override + protected String enhanceClassName() { + return "oracle.jdbc.OracleDriver"; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def index 8c34d4f78..7949e2865 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/resources/skywalking-plugin.def @@ -1,3 +1,3 @@ -com.a.eye.skywalking.plugin.jdbc.define.H2PluginDefine -com.a.eye.skywalking.plugin.jdbc.define.MysqlPluginDefine -com.a.eye.skywalking.plugin.jdbc.define.OraclePluginDefine +com.a.eye.skywalking.plugin.jdbc.define.H2Instrumentation +com.a.eye.skywalking.plugin.jdbc.define.MysqlInstrumentation +com.a.eye.skywalking.plugin.jdbc.define.OracleInstrumentation diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParserTest.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParserTest.java new file mode 100644 index 000000000..39836172e --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/test/java/com/a/eye/skywalking/plugin/jdbc/connectionurl/parser/URLParserTest.java @@ -0,0 +1,107 @@ +package com.a.eye.skywalking.plugin.jdbc.connectionurl.parser; + +import com.a.eye.skywalking.plugin.jdbc.ConnectionInfo; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +public class URLParserTest { + @Test + public void testParseMysqlJDBCURLWithHost() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost/test"); + assertThat(connectionInfo.getDBType(), is("Mysql")); + assertThat(connectionInfo.getDatabaseName(), is("test")); + assertThat(connectionInfo.getHost(), is("primaryhost")); + assertThat(connectionInfo.getPort(), is(3306)); + } + + @Test + public void testParseMysqlJDBCURLWithHostAndPort() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307/test?profileSQL=true"); + assertThat(connectionInfo.getDBType(), is("Mysql")); + assertThat(connectionInfo.getDatabaseName(), is("test")); + assertThat(connectionInfo.getHost(), is("primaryhost")); + assertThat(connectionInfo.getPort(), is(3307)); + } + + @Test + public void testParseMysqlJDBCURLWithMultiHost() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql//primaryhost:3307,secondaryhost1,secondaryhost2/test?profileSQL=true"); + assertThat(connectionInfo.getDBType(), is("Mysql")); + assertThat(connectionInfo.getDatabaseName(), is("test")); + assertThat(connectionInfo.getHosts(), is("primaryhost:3307,secondaryhost1:3306,secondaryhost2:3306,")); + } + + @Test + public void testParseMysqlJDBCURLWithConnectorJs() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:mysql:replication://master,slave1,slave2,slave3/test"); + assertThat(connectionInfo.getDBType(), is("Mysql")); + assertThat(connectionInfo.getDatabaseName(), is("test")); + assertThat(connectionInfo.getHosts(), is("master:3306,slave1:3306,slave2:3306,slave3:3306,")); + } + + @Test + public void testParseOracleJDBCURLWithHost() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:orcl"); + assertThat(connectionInfo.getDBType(), is("Oracle")); + assertThat(connectionInfo.getDatabaseName(), is("orcl")); + assertThat(connectionInfo.getHost(), is("localhost")); + assertThat(connectionInfo.getPort(), is(1521)); + } + + @Test + public void testParseOracleJDBCURLWithHostAndPort() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:@localhost:1522:orcl"); + assertThat(connectionInfo.getDBType(), is("Oracle")); + assertThat(connectionInfo.getDatabaseName(), is("orcl")); + assertThat(connectionInfo.getHost(), is("localhost")); + assertThat(connectionInfo.getPort(), is(1522)); + } + + @Test + public void testParseOracleJDBCURLWithUserNameAndPassword() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:oracle:thin:scott/tiger@myhost:1521:orcl"); + assertThat(connectionInfo.getDBType(), is("Oracle")); + assertThat(connectionInfo.getDatabaseName(), is("orcl")); + assertThat(connectionInfo.getHost(), is("myhost")); + assertThat(connectionInfo.getPort(), is(1521)); + } + + @Test + public void testParseH2JDBCURLWithEmbedded() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:file:/data/sample"); + assertThat(connectionInfo.getDBType(), is("H2")); + assertThat(connectionInfo.getDatabaseName(), is("/data/sample")); + assertThat(connectionInfo.getHost(), is("localhost")); + assertThat(connectionInfo.getPort(), is(-1)); + } + + @Test + public void testParseH2JDBCURLWithEmbeddedRunningInWindows() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:file:C:/data/sample"); + assertThat(connectionInfo.getDBType(), is("H2")); + assertThat(connectionInfo.getDatabaseName(), is("C:/data/sample")); + assertThat(connectionInfo.getHost(), is("localhost")); + assertThat(connectionInfo.getPort(), is(-1)); + } + + @Test + public void testParseH2JDBCURLWithMemoryMode() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:mem:test_mem"); + assertThat(connectionInfo.getDBType(), is("H2")); + assertThat(connectionInfo.getDatabaseName(), is("test_mem")); + assertThat(connectionInfo.getHost(), is("localhost")); + assertThat(connectionInfo.getPort(), is(-1)); + } + + @Test + public void testParseH2JDBCURL() { + ConnectionInfo connectionInfo = new URLParser().parser("jdbc:h2:tcp://localhost:8084/~/sample"); + assertThat(connectionInfo.getDBType(), is("H2")); + assertThat(connectionInfo.getDatabaseName(), is("sample")); + assertThat(connectionInfo.getHost(), is("localhost")); + assertThat(connectionInfo.getPort(), is(8084)); + } +} \ No newline at end of file diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisClusterConstructorInterceptor4HostAndPortArg.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisClusterConstructorInterceptor4HostAndPortArg.java deleted file mode 100644 index 021e2ac66..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisClusterConstructorInterceptor4HostAndPortArg.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; - -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; -import redis.clients.jedis.HostAndPort; - -import static com.a.eye.skywalking.api.plugin.jedis.v2.JedisMethodInterceptor.REDIS_CONN_INFO_KEY; - -/** - * Created by xin on 16-6-12. - */ -public class JedisClusterConstructorInterceptor4HostAndPortArg implements InstanceConstructorInterceptor { - @Override - public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { - StringBuilder redisConnInfo = new StringBuilder(); - HostAndPort hostAndPort = (HostAndPort) interceptorContext.allArguments()[0]; - redisConnInfo.append(hostAndPort.toString()).append(";"); - context.set(REDIS_CONN_INFO_KEY, redisConnInfo.toString()); - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4ShardInfoArg.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4ShardInfoArg.java deleted file mode 100644 index b0f3a1580..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4ShardInfoArg.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; - -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; -import redis.clients.jedis.JedisShardInfo; - -import static com.a.eye.skywalking.api.plugin.jedis.v2.JedisMethodInterceptor.REDIS_CONN_INFO_KEY; - -/** - * Created by wusheng on 2016/12/1. - */ -public class JedisConstructorInterceptor4ShardInfoArg implements InstanceConstructorInterceptor { - - @Override - public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { - String redisConnInfo; - JedisShardInfo shardInfo = (JedisShardInfo) interceptorContext.allArguments()[0]; - redisConnInfo = shardInfo.getHost() + ":" + shardInfo.getPort(); - context.set(REDIS_CONN_INFO_KEY, redisConnInfo); - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4StringArg.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4StringArg.java deleted file mode 100644 index 9ead9a34a..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4StringArg.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; - -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; - -import static com.a.eye.skywalking.api.plugin.jedis.v2.JedisMethodInterceptor.REDIS_CONN_INFO_KEY; - -public class JedisConstructorInterceptor4StringArg implements InstanceConstructorInterceptor { - - @Override - public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { - String redisConnInfo; - redisConnInfo = (String) interceptorContext.allArguments()[0]; - if (interceptorContext.allArguments().length > 1) { - redisConnInfo += ":" + interceptorContext.allArguments()[1]; - } - context.set(REDIS_CONN_INFO_KEY, redisConnInfo); - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4UriArg.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4UriArg.java deleted file mode 100644 index 273d28075..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisConstructorInterceptor4UriArg.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; - -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; - -import java.net.URI; - -import static com.a.eye.skywalking.api.plugin.jedis.v2.JedisMethodInterceptor.REDIS_CONN_INFO_KEY; - -/** - * Created by wusheng on 2016/12/1. - */ -public class JedisConstructorInterceptor4UriArg implements InstanceConstructorInterceptor { - - @Override - public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { - String redisConnInfo; - URI uri = (URI) interceptorContext.allArguments()[0]; - redisConnInfo = uri.getHost() + ":" + uri.getPort(); - context.set(REDIS_CONN_INFO_KEY, redisConnInfo); - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisMethodInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisMethodInterceptor.java deleted file mode 100644 index 874d12a28..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisMethodInterceptor.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; - -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.assist.NoCocurrencyAceessObject; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; - -public class JedisMethodInterceptor extends NoCocurrencyAceessObject { - protected static final String REDIS_CONN_INFO_KEY = "redisClusterConnInfo"; - - - @Override - public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { - this.whenEnter(context, new Runnable() { - @Override public void run() { - /** - * redis server wouldn't process rpc context. ignore the - * return(ContextData) of sender's beforeSend - */ - Identification.IdentificationBuilder builder = Identification - .newBuilder() - .viewPoint( - context.get(REDIS_CONN_INFO_KEY, String.class) - + " " + interceptorContext.methodName()) - .spanType(RedisBuriedPointType.INSTANCE); - if (interceptorContext.allArguments().length > 0 - && interceptorContext.allArguments()[0] instanceof String) { - builder.businessKey("key=" - + interceptorContext.allArguments()[0]); - } - rpcClientInvokeMonitor.beforeInvoke(builder.build()); - } - }); - } - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) { - this.whenExist(context, new Runnable(){ - @Override public void run() { - rpcClientInvokeMonitor.afterInvoke(); - } - }); - - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { - rpcClientInvokeMonitor.occurException(t); - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/RedisBuriedPointType.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/RedisBuriedPointType.java deleted file mode 100644 index 3153d27e8..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/RedisBuriedPointType.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; - -import com.a.eye.skywalking.api.IBuriedPointType; - -public enum RedisBuriedPointType implements IBuriedPointType { - INSTANCE; - - @Override - public String getTypeName() { - return "Redis"; - } - - @Override - public CallType getCallType() { - return CallType.SYNC; - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/define/JedisClusterPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/define/JedisClusterPluginDefine.java deleted file mode 100644 index cfebfb463..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/define/JedisClusterPluginDefine.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2.define; - -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.bytebuddy.AllObjectDefaultMethodsMatch; -import com.a.eye.skywalking.plugin.bytebuddy.ArgumentTypeNameMatch; -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import java.util.Set; - -import static com.a.eye.skywalking.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; -import static net.bytebuddy.matcher.ElementMatchers.*; - -public class JedisClusterPluginDefine extends ClassInstanceMethodsEnhancePluginDefine { - - @Override - public String enhanceClassName() { - return "redis.clients.jedis.JedisCluster"; - } - - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[] {new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return takesArgument(0, Set.class); - } - - @Override - public String getConstructorInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisClusterConstructorInterceptor4SetArg"; - } - }, new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return takesArgumentWithType(0, "redis.clients.jedis.HostAndPort"); - } - - @Override - public String getConstructorInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisClusterConstructorInterceptor4HostAndPortArg"; - } - }}; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] {new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return any().and(not(AllObjectDefaultMethodsMatch.INSTANCE)); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/define/JedisPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/define/JedisPluginDefine.java deleted file mode 100644 index d4085b551..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/define/JedisPluginDefine.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2.define; - -import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.bytebuddy.AllObjectDefaultMethodsMatch; -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; -import net.bytebuddy.matcher.ElementMatchers; - -import java.net.URI; - -import static com.a.eye.skywalking.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; -import static net.bytebuddy.matcher.ElementMatchers.*; - -public class JedisPluginDefine extends ClassInstanceMethodsEnhancePluginDefine { - - @Override - public String enhanceClassName() { - return "redis.clients.jedis.Jedis"; - } - - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[] {new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return takesArgument(0, String.class); - } - - @Override - public String getConstructorInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorInterceptor4StringArg"; - } - }, new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return takesArgumentWithType(0, "redis.clients.jedis.HostAndPort"); - } - - @Override - public String getConstructorInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorInterceptor4ShardInfoArgg"; - } - }, new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return takesArgument(0, URI.class); - } - - @Override - public String getConstructorInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorInterceptor4UriArg"; - } - }}; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] {new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return not(ElementMatchers.isPrivate() - .or(AllObjectDefaultMethodsMatch.INSTANCE) - .or(named("close")) - .or(named("getDB")) - .or(named("connect")) - .or(named("setDataSource")) - .or(named("resetState")) - .or(named("clusterSlots")) - .or(named("checkIsInMultiOrPipeline"))); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisClusterConstructorWithHostAndPortArgInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisClusterConstructorWithHostAndPortArgInterceptor.java new file mode 100644 index 000000000..c3e9ea38e --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisClusterConstructorWithHostAndPortArgInterceptor.java @@ -0,0 +1,30 @@ +package com.a.eye.skywalking.plugin.jedis.v2; + +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +import redis.clients.jedis.HostAndPort; + +import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO; +import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_HOST; +import static com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor.KEY_OF_REDIS_PORT; + +/** + * {@link JedisClusterConstructorWithHostAndPortArgInterceptor} record the host and port information from {@link EnhancedClassInstanceContext#context}, + * and each host and port will spilt ;. + * + * @author zhangxin + */ +public class JedisClusterConstructorWithHostAndPortArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { + StringBuilder redisConnInfo = new StringBuilder(); + HostAndPort hostAndPort = (HostAndPort) interceptorContext.allArguments()[0]; + redisConnInfo.append(hostAndPort.toString()).append(";"); + context.set(KEY_OF_REDIS_CONN_INFO, redisConnInfo.toString()); + context.set(KEY_OF_REDIS_HOST, hostAndPort.getHost()); + context.set(KEY_OF_REDIS_PORT, hostAndPort.getPort()); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisClusterConstructorInterceptor4SetArg.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisClusterConstructorWithListHostAndPortArgInterceptor.java similarity index 51% rename from skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisClusterConstructorInterceptor4SetArg.java rename to skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisClusterConstructorWithListHostAndPortArgInterceptor.java index 17a098eb7..aa27d2867 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/jedis/v2/JedisClusterConstructorInterceptor4SetArg.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisClusterConstructorWithListHostAndPortArgInterceptor.java @@ -1,19 +1,20 @@ -package com.a.eye.skywalking.api.plugin.jedis.v2; +package com.a.eye.skywalking.plugin.jedis.v2; import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; - +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext; import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; -import redis.clients.jedis.HostAndPort; import java.util.Set; -import static com.a.eye.skywalking.api.plugin.jedis.v2.JedisMethodInterceptor.REDIS_CONN_INFO_KEY; +import redis.clients.jedis.HostAndPort; /** - * Created by xin on 16-6-12. + * {@link JedisClusterConstructorWithHostAndPortArgInterceptor} record the host and port information that fetch + * from {@link EnhancedClassInstanceContext#context}, and each host and port will spilt ;. + * + * @author zhangxin */ -public class JedisClusterConstructorInterceptor4SetArg implements InstanceConstructorInterceptor { +public class JedisClusterConstructorWithListHostAndPortArgInterceptor implements InstanceConstructorInterceptor { @Override public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { StringBuilder redisConnInfo = new StringBuilder(); @@ -21,6 +22,7 @@ public class JedisClusterConstructorInterceptor4SetArg implements InstanceConstr for (HostAndPort hostAndPort : hostAndPorts) { redisConnInfo.append(hostAndPort.toString()).append(";"); } - context.set(REDIS_CONN_INFO_KEY, redisConnInfo.toString()); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO, redisConnInfo.toString()); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_HOSTS, redisConnInfo); } } diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithShardInfoArgInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithShardInfoArgInterceptor.java new file mode 100644 index 000000000..34a9f2ecf --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithShardInfoArgInterceptor.java @@ -0,0 +1,26 @@ +package com.a.eye.skywalking.plugin.jedis.v2; + +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +import redis.clients.jedis.JedisShardInfo; + +/** + * {@link JedisClusterConstructorWithHostAndPortArgInterceptor} will record the host + * and port information from {@link EnhancedClassInstanceContext#context}. + * + * @author zhangxin + */ +public class JedisConstructorWithShardInfoArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { + String redisConnInfo; + JedisShardInfo shardInfo = (JedisShardInfo) interceptorContext.allArguments()[0]; + redisConnInfo = shardInfo.getHost() + ":" + shardInfo.getPort(); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO, redisConnInfo); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_HOST, shardInfo.getHost()); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_PORT, shardInfo.getPort()); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithStringArgInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithStringArgInterceptor.java new file mode 100644 index 000000000..d7f28d4b8 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithStringArgInterceptor.java @@ -0,0 +1,27 @@ +package com.a.eye.skywalking.plugin.jedis.v2; + +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * {@link JedisClusterConstructorWithHostAndPortArgInterceptor} record the host + * and port information from {@link EnhancedClassInstanceContext#context}. + * + * @author zhangxin + */ +public class JedisConstructorWithStringArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { + String host = (String) interceptorContext.allArguments()[0]; + int port = 6379; + if (interceptorContext.allArguments().length > 1) { + port = (Integer) interceptorContext.allArguments()[1]; + } + context.set(JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO, host + ":" + port); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_HOST, host); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_PORT, port); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithUriArgInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithUriArgInterceptor.java new file mode 100644 index 000000000..2640949a6 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisConstructorWithUriArgInterceptor.java @@ -0,0 +1,26 @@ +package com.a.eye.skywalking.plugin.jedis.v2; + +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +import java.net.URI; + +/** + * {@link JedisClusterConstructorWithHostAndPortArgInterceptor} record the host and port information that fetch + * from {@link EnhancedClassInstanceContext#context}. + * + * @author zhangxin + */ +public class JedisConstructorWithUriArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { + String redisConnInfo; + URI uri = (URI) interceptorContext.allArguments()[0]; + redisConnInfo = uri.getHost() + ":" + uri.getPort(); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_CONN_INFO, redisConnInfo); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_HOST, uri.getHost()); + context.set(JedisMethodInterceptor.KEY_OF_REDIS_PORT, uri.getPort()); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisMethodInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisMethodInterceptor.java new file mode 100644 index 000000000..33cc50744 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/JedisMethodInterceptor.java @@ -0,0 +1,91 @@ +package com.a.eye.skywalking.plugin.jedis.v2; + +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.assist.NoCocurrencyAceessObject; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +/** + * {@link JedisMethodInterceptor} intercept all method of {@link redis.clients.jedis.Jedis} + * or {@link redis.clients.jedis.JedisCluster}. {@link JedisMethodInterceptor} record + * the redis host, operation name and the key of the operation. + * + * @author zhangxin + */ +public class JedisMethodInterceptor extends NoCocurrencyAceessObject { + /** + * The key name that redis connection information in {@link EnhancedClassInstanceContext#context}. + */ + protected static final String KEY_OF_REDIS_CONN_INFO = "REDIS_CONNECTION_INFO"; + /** + * The key name that multiple redis hosts in {@link EnhancedClassInstanceContext#context}. + */ + protected static final String KEY_OF_REDIS_HOSTS = "KEY_OF_REDIS_HOSTS"; + /** + * The key name that redis host in {@link EnhancedClassInstanceContext#context}. + * it will be null if the value that fetch from {@link EnhancedClassInstanceContext#context} + * by using {@link #KEY_OF_REDIS_HOSTS} is not null. + */ + protected static final String KEY_OF_REDIS_HOST = "KEY_OF_REDIS_HOST"; + /** + * The key name that redis port in {@link EnhancedClassInstanceContext#context}. + * It can not be null if the value that fetch from {@link EnhancedClassInstanceContext#context} by + * using {@link #KEY_OF_REDIS_HOST} is not null. + */ + protected static final String KEY_OF_REDIS_PORT = "KEY_OF_REDIS_PORT"; + + private static final String REDIS_COMPONENT = "Redis"; + + + @Override + public void beforeMethod(final EnhancedClassInstanceContext context, final InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { + this.whenEnter(context, new Runnable() { + @Override + public void run() { + Span span = ContextManager.INSTANCE.createSpan(context.get(KEY_OF_REDIS_CONN_INFO, String.class) + " " + interceptorContext.methodName()); + Tags.COMPONENT.set(span, REDIS_COMPONENT); + Tags.DB_TYPE.set(span, REDIS_COMPONENT); + tagPeer(span, context); + Tags.SPAN_LAYER.asDB(span); + + if (interceptorContext.allArguments().length > 0 + && interceptorContext.allArguments()[0] instanceof String) { + Tags.DB_STATEMENT.set(span, interceptorContext.methodName() + " " + interceptorContext.allArguments()[0]); + } + } + }); + } + + /** + * set peer host information for the current active span. + */ + private void tagPeer(Span span, EnhancedClassInstanceContext context) { + String redisHosts = (String) context.get(KEY_OF_REDIS_HOSTS); + if (!StringUtil.isEmpty(redisHosts)) { + Tags.PEERS.set(span, (String) context.get(KEY_OF_REDIS_HOSTS)); + } else { + Tags.PEER_HOST.set(span, (String) context.get(KEY_OF_REDIS_HOST)); + Tags.PEER_PORT.set(span, (Integer) context.get(KEY_OF_REDIS_PORT)); + } + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) { + this.whenExist(context, new Runnable() { + @Override + public void run() { + ContextManager.INSTANCE.stopSpan(); + } + }); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { + ContextManager.INSTANCE.activeSpan().log(t); + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/define/JedisClusterInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/define/JedisClusterInstrumentation.java new file mode 100644 index 000000000..e60231f9d --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/define/JedisClusterInstrumentation.java @@ -0,0 +1,81 @@ +package com.a.eye.skywalking.plugin.jedis.v2.define; + +import com.a.eye.skywalking.api.plugin.bytebuddy.AllObjectDefaultMethodsMatch; +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.jedis.v2.JedisClusterConstructorWithListHostAndPortArgInterceptor; +import com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import java.util.Set; + +import static com.a.eye.skywalking.api.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static net.bytebuddy.matcher.ElementMatchers.any; +import static net.bytebuddy.matcher.ElementMatchers.not; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +/** + * {@link JedisClusterInstrumentation} presents that skywalking intercepts all constructors and methods of {@link redis.clients.jedis.JedisCluster}. + * {@link com.a.eye.skywalking.plugin.jedis.v2.JedisClusterConstructorWithHostAndPortArgInterceptor} intercepts all constructor with argument {@link redis.clients.jedis.HostAndPort} + * and the other constructor intercept by class {@link JedisClusterConstructorWithListHostAndPortArgInterceptor}. + * {@link JedisMethodInterceptor} intercept all methods of {@link redis.clients.jedis.JedisCluster} + * + * @author zhangxin + */ +public class JedisClusterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ARGUMENT_TYPE_NAME = "redis.clients.jedis.HostAndPort"; + private static final String ENHANCE_CLASS = "redis.clients.jedis.JedisCluster"; + private static final String CONSTRUCTOR_WITH_LIST_HOSTANDPORT_ARG_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisClusterConstructorWithListHostAndPortArgInterceptor"; + private static final String METHOD_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor"; + private static final String CONSTRUCTOR_WITH_HOSTANDPORT_ARG_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisClusterConstructorWithHostAndPortArgInterceptor"; + + + @Override + public String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, Set.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_LIST_HOSTANDPORT_ARG_INTERCEPT_CLASS; + } + }, new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, ARGUMENT_TYPE_NAME); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_HOSTANDPORT_ARG_INTERCEPT_CLASS; + } + }}; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return any().and(not(AllObjectDefaultMethodsMatch.INSTANCE)); + } + + @Override + public String getMethodsInterceptor() { + return METHOD_INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/define/JedisInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/define/JedisInstrumentation.java new file mode 100644 index 000000000..788bedc93 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/java/com/a/eye/skywalking/plugin/jedis/v2/define/JedisInstrumentation.java @@ -0,0 +1,102 @@ +package com.a.eye.skywalking.plugin.jedis.v2.define; + +import com.a.eye.skywalking.api.plugin.bytebuddy.AllObjectDefaultMethodsMatch; +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorWithShardInfoArgInterceptor; +import com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorWithUriArgInterceptor; +import com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import net.bytebuddy.matcher.ElementMatchers; + +import java.net.URI; + +import static com.a.eye.skywalking.api.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.not; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; + +/** + * {@link JedisInstrumentation} presents that skywalking intercept all constructors and methods of {@link redis.clients.jedis.Jedis}. + * {@link JedisConstructorWithShardInfoArgInterceptor} intercepts all constructor with argument {@link redis.clients.jedis.HostAndPort} + * ,{@link JedisConstructorWithUriArgInterceptor} intercepts the constructors with uri argument and + * the other constructor intercept by class {@link JedisConstructorWithShardInfoArgInterceptor}. + * {@link JedisMethodInterceptor} intercept all methods of {@link redis.clients.jedis.Jedis}. + * + * @author zhangxin + */ +public class JedisInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String HOST_AND_PROT_ARG_TYPE_NAME = "redis.clients.jedis.HostAndPort"; + private static final String ENHANCE_CLASS = "redis.clients.jedis.Jedis"; + private static final String CONSTRUCTOR_WITH_STRING_ARG_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorWithStringArgInterceptor"; + private static final String CONSTRUCTOR_WITH_SHARD_INFO_ARG_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorWithShardInfoArgInterceptor"; + private static final String CONSTRUCTOR_WITH_URI_ARG_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisConstructorWithUriArgInterceptor"; + private static final String JEDIS_METHOD_INTERCET_CLASS = "com.a.eye.skywalking.plugin.jedis.v2.JedisMethodInterceptor"; + + @Override + public String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, String.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_STRING_ARG_INTERCEPT_CLASS; + } + }, new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, HOST_AND_PROT_ARG_TYPE_NAME); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_SHARD_INFO_ARG_INTERCEPT_CLASS; + } + }, new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, URI.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_URI_ARG_INTERCEPT_CLASS; + } + }}; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return not(ElementMatchers.isPrivate() + .or(AllObjectDefaultMethodsMatch.INSTANCE) + .or(named("close")) + .or(named("getDB")) + .or(named("connect")) + .or(named("setDataSource")) + .or(named("resetState")) + .or(named("clusterSlots")) + .or(named("checkIsInMultiOrPipeline"))); + } + + @Override + public String getMethodsInterceptor() { + return JEDIS_METHOD_INTERCET_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def index de54ba9fd..9876bd990 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def +++ b/skywalking-sniffer/skywalking-sdk-plugin/jedis-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -1,2 +1,2 @@ -com.a.eye.skywalking.plugin.jedis.v2.define.JedisPluginDefine -com.a.eye.skywalking.plugin.jedis.v2.define.JedisClusterPluginDefine +com.a.eye.skywalking.plugin.jedis.v2.define.JedisClusterInstrumentation +com.a.eye.skywalking.plugin.jedis.v2.define.JedisInstrumentation diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanBuriedPointType.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanBuriedPointType.java deleted file mode 100644 index 766351815..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanBuriedPointType.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.a.eye.skywalking.api.plugin.motan; - -import com.a.eye.skywalking.api.IBuriedPointType; - -public enum MotanBuriedPointType implements IBuriedPointType { - - INSTANCE; - - @Override - public String getTypeName() { - return "MO"; - } - - @Override - public CallType getCallType() { - return CallType.SYNC; - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanClientCallInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanClientCallInterceptor.java deleted file mode 100644 index c06cb9ba6..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanClientCallInterceptor.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.a.eye.skywalking.api.plugin.motan; - -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; -import com.a.eye.skywalking.model.ContextData; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; -import com.weibo.api.motan.rpc.Request; -import com.weibo.api.motan.rpc.URL; - -/** - * Motan client interceptor - */ -public class MotanClientCallInterceptor implements InstanceMethodsAroundInterceptor{ - - private static final String REQUEST_URL = "REQUEST_URL"; - - @Override - public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - MethodInterceptResult result) { - URL url = (URL) context.get(REQUEST_URL); - Request request = (Request) interceptorContext.allArguments()[0]; - if (url != null) { - ContextData contextData = new RPCClientInvokeMonitor() - .beforeInvoke(generateIdentify(request, url)); - String contextDataStr = contextData.toString(); - request.setAttachment("contextData", contextDataStr); - } - } - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - Object ret) { - new RPCClientInvokeMonitor().afterInvoke(); - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext) { - new RPCClientInvokeMonitor().occurException(t); - } - - - private static String generateViewPoint(URL serviceURI, Request request) { - StringBuilder viewPoint = new StringBuilder(serviceURI.getUri()); - viewPoint.append("." + request.getMethodName()); - viewPoint.append("(" + request.getParamtersDesc() + ")?group=" + serviceURI.getGroup()); - return viewPoint.toString(); - } - - - public static Identification generateIdentify(Request request, URL serviceURI) { - return Identification.newBuilder().viewPoint(generateViewPoint(serviceURI, request)) - .spanType(MotanBuriedPointType.INSTANCE).build(); - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanClientFetchCallURLInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanClientFetchCallURLInterceptor.java deleted file mode 100644 index 637a56116..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanClientFetchCallURLInterceptor.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.a.eye.skywalking.api.plugin.motan; - -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; - -/** - * Created by xin on 2017/1/23. - */ -public class MotanClientFetchCallURLInterceptor implements InstanceMethodsAroundInterceptor { - - private static final String REQUEST_URL = "REQUEST_URL"; - - @Override - public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { - context.set(REQUEST_URL, interceptorContext.allArguments()[0]); - } - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) { - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { - - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanServerInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanServerInterceptor.java deleted file mode 100644 index 9a1570aee..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/MotanServerInterceptor.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.a.eye.skywalking.api.plugin.motan; - -import com.a.eye.skywalking.invoke.monitor.RPCServerInvokeMonitor; -import com.a.eye.skywalking.model.ContextData; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; -import com.weibo.api.motan.rpc.Request; -import com.weibo.api.motan.rpc.URL; - -public class MotanServerInterceptor implements InstanceConstructorInterceptor, InstanceMethodsAroundInterceptor { - @Override - public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { - context.set("serviceURI", interceptorContext.allArguments()[0]); - } - - @Override - public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - MethodInterceptResult result) { - com.weibo.api.motan.rpc.Request request = (com.weibo.api.motan.rpc.Request) interceptorContext.allArguments()[0]; - if (request != null) { - new RPCServerInvokeMonitor().beforeInvoke(new ContextData(request.getAttachments().get("contextData")), - generateIdentify(request, (com.weibo.api.motan.rpc.URL) context.get("serviceURI"))); - } - } - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, - Object ret) { - new RPCServerInvokeMonitor().afterInvoke(); - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext) { - new RPCServerInvokeMonitor().occurException(t); - } - - - private static String generateViewPoint(URL serviceURI, Request request) { - StringBuilder viewPoint = new StringBuilder(serviceURI.getUri()); - viewPoint.append("." + request.getMethodName()); - viewPoint.append("(" + request.getParamtersDesc() + ")?group=" + serviceURI.getGroup()); - return viewPoint.toString(); - } - - - public static Identification generateIdentify(Request request, URL serviceURI) { - return Identification.newBuilder().viewPoint(generateViewPoint(serviceURI, request)) - .spanType(MotanBuriedPointType.INSTANCE).build(); - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/define/MotanClientDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/define/MotanClientDefine.java deleted file mode 100644 index e838dda1e..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/define/MotanClientDefine.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.a.eye.skywalking.api.plugin.motan.define; - -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; - -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -public class MotanClientDefine extends ClassInstanceMethodsEnhancePluginDefine { - @Override - protected String enhanceClassName() { - return "com.weibo.api.motan.cluster.support.ClusterSpi"; - } - - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[0]; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("setUrl"); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.motan.MotanClientFetchCallURLInterceptor"; - } - }, new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("call"); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.motan.MotanClientCallInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/define/MotanServerDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/define/MotanServerDefine.java deleted file mode 100644 index 4649f3a40..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/api/plugin/motan/define/MotanServerDefine.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.a.eye.skywalking.api.plugin.motan.define; - -import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.any; -import static net.bytebuddy.matcher.ElementMatchers.named; - -public class MotanServerDefine extends ClassInstanceMethodsEnhancePluginDefine { - - @Override - protected String enhanceClassName() { - return "com.weibo.api.motan.rpc.AbstractProvider"; - } - - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return new ConstructorInterceptPoint[] {new ConstructorInterceptPoint() { - @Override - public ElementMatcher getConstructorMatcher() { - return any(); - } - - @Override - public String getConstructorInterceptor() { - return "com.a.eye.skywalking.plugin.motan.MotanServerInterceptor"; - } - }}; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[] {new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("call"); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.motan.MotanServerInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanConsumerFetchRequestURLInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanConsumerFetchRequestURLInterceptor.java new file mode 100644 index 000000000..a1d1b3a5d --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanConsumerFetchRequestURLInterceptor.java @@ -0,0 +1,40 @@ +package com.a.eye.skywalking.plugin.motan; + +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; + +/** + * {@link MotanConsumerFetchRequestURLInterceptor} record {@link com.weibo.api.motan.rpc.URL} to {@link EnhancedClassInstanceContext#context} + * for the operation name that create span need. + * + * @author zhangxin + */ +public class MotanConsumerFetchRequestURLInterceptor implements InstanceMethodsAroundInterceptor { + + private static final String CONTEXT_NAME_OF_REQUEST_URL = "REQUEST_URL"; + + /** + * Fetch the request url from the first param of all constructor, and put request + * url into {@link EnhancedClassInstanceContext#context}. + * + * @param context instance context, a class instance only has one {@link EnhancedClassInstanceContext} instance. + * @param interceptorContext method context, includes class name, method name, etc. + * @param result change this result, if you want to truncate the method. + */ + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { + context.set(CONTEXT_NAME_OF_REQUEST_URL, interceptorContext.allArguments()[0]); + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) { + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) { + // do nothing + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanConsumerInvokeInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanConsumerInvokeInterceptor.java new file mode 100644 index 000000000..c24b056e2 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanConsumerInvokeInterceptor.java @@ -0,0 +1,92 @@ +package com.a.eye.skywalking.plugin.motan; + +import com.a.eye.skywalking.api.context.ContextCarrier; +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; +import com.weibo.api.motan.rpc.Request; +import com.weibo.api.motan.rpc.Response; +import com.weibo.api.motan.rpc.URL; + +/** + * {@link MotanConsumerInvokeInterceptor} create span by fetch request url from + * {@link EnhancedClassInstanceContext#context} and transport serialized context + * data to provider side through {@link Request#setAttachment(String, String)}. + * + * @author zhangxin + */ +public class MotanConsumerInvokeInterceptor implements InstanceMethodsAroundInterceptor { + + /** + * Context name of request url in {@link EnhancedClassInstanceContext#context}. + */ + private static final String CONTEXT_NAME_OF_REQUEST_URL = "REQUEST_URL"; + + /** + * Attachment key of the serialized context data. + */ + private static final String ATTACHMENT_KEY_OF_CONTEXT_DATA = "contextData"; + + /** + * Motan component + */ + private static final String MOTAN_COMPONENT = "Motan"; + + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + MethodInterceptResult result) { + URL url = (URL) context.get(CONTEXT_NAME_OF_REQUEST_URL); + + if (url != null) { + Request request = (Request) interceptorContext.allArguments()[0]; + + Span span = ContextManager.INSTANCE.createSpan(generateOperationName(url, request)); + Tags.PEER_HOST.set(span, url.getHost()); + Tags.PEER_PORT.set(span, url.getPort()); + Tags.COMPONENT.set(span, MOTAN_COMPONENT); + Tags.URL.set(span, url.getIdentity()); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT); + Tags.SPAN_LAYER.asRPCFramework(span); + + ContextCarrier contextCarrier = new ContextCarrier(); + ContextManager.INSTANCE.inject(contextCarrier); + request.setAttachment(ATTACHMENT_KEY_OF_CONTEXT_DATA, contextCarrier.serialize()); + } + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + Object ret) { + Response response = (Response) ret; + if (response != null && response.getException() != null) { + Span span = ContextManager.INSTANCE.activeSpan(); + span.log(response.getException()); + Tags.ERROR.set(span, true); + } + + ContextManager.INSTANCE.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + ContextManager.INSTANCE.activeSpan().log(t); + } + + + /** + * Generate operation name. + * + * @return operation name. + */ + private static String generateOperationName(URL serviceURI, Request request) { + return new StringBuilder(serviceURI.getPath()).append(".").append(request.getMethodName()).append("(") + .append(request.getParamtersDesc()).append(")").toString(); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanProviderInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanProviderInterceptor.java new file mode 100644 index 000000000..bbc66f3a7 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/MotanProviderInterceptor.java @@ -0,0 +1,92 @@ +package com.a.eye.skywalking.plugin.motan; + +import com.a.eye.skywalking.api.context.ContextCarrier; +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; +import com.weibo.api.motan.rpc.Request; +import com.weibo.api.motan.rpc.Response; +import com.weibo.api.motan.rpc.URL; + +/** + * Current trace segment will ref the trace segment from previous level if the serialized context data that fetch + * from {@link Request#getAttachments()} is not null. + * + * {@link MotanProviderInterceptor} intercept all constructor of {@link com.weibo.api.motan.rpc.AbstractProvider} for record + * the request url from consumer side. + * + * @author zhangxin + */ +public class MotanProviderInterceptor implements InstanceConstructorInterceptor, InstanceMethodsAroundInterceptor { + + /** + * The + */ + private static final String KEY_NAME_OF_REQUEST_URL = "REQUEST_URL"; + + /** + * The {@link Request#getAttachments()} key. It maps to the serialized {@link ContextCarrier}. + */ + private static final String ATTACHMENT_KEY_OF_CONTEXT_DATA = "contextData"; + /** + * Motan component + */ + private static final String MOTAN_COMPONENT = "Motan"; + + @Override + public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) { + context.set(KEY_NAME_OF_REQUEST_URL, interceptorContext.allArguments()[0]); + } + + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + MethodInterceptResult result) { + URL url = (URL) context.get(KEY_NAME_OF_REQUEST_URL); + if (url != null) { + com.weibo.api.motan.rpc.Request request = (com.weibo.api.motan.rpc.Request) interceptorContext.allArguments()[0]; + Span span = ContextManager.INSTANCE.createSpan(generateViewPoint(url, request)); + Tags.COMPONENT.set(span, MOTAN_COMPONENT); + Tags.URL.set(span, url.getIdentity()); + Tags.PEER_PORT.set(span, url.getPort()); + Tags.PEER_HOST.set(span, url.getHost()); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_SERVER); + Tags.SPAN_LAYER.asRPCFramework(span); + + String serializedContextData = request.getAttachments().get(ATTACHMENT_KEY_OF_CONTEXT_DATA); + ContextManager.INSTANCE.extract(new ContextCarrier().deserialize(serializedContextData)); + } + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, + Object ret) { + Response response = (Response) ret; + if (response != null && response.getException() != null) { + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.ERROR.set(span, true); + span.log(response.getException()); + } + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + ContextManager.INSTANCE.activeSpan().log(t); + } + + + private static String generateViewPoint(URL serviceURI, Request request) { + StringBuilder viewPoint = new StringBuilder(serviceURI.getUri()); + viewPoint.append("." + request.getMethodName()); + viewPoint.append("(" + request.getParamtersDesc() + ")"); + return viewPoint.toString(); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/define/MotanConsumerInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/define/MotanConsumerInstrumentation.java new file mode 100644 index 000000000..b2b0d248b --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/define/MotanConsumerInstrumentation.java @@ -0,0 +1,66 @@ +package com.a.eye.skywalking.plugin.motan.define; + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.motan.MotanConsumerFetchRequestURLInterceptor; +import com.a.eye.skywalking.plugin.motan.MotanConsumerInvokeInterceptor; +import com.weibo.api.motan.rpc.Request; +import com.weibo.api.motan.rpc.URL; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link MotanConsumerInstrumentation} presents that skywalking intercept + * {@link com.weibo.api.motan.cluster.support.ClusterSpi#call(Request)} by using {@link MotanConsumerInvokeInterceptor} and + * intercept {@link com.weibo.api.motan.cluster.support.ClusterSpi#setUrl(URL)} by using + * {@link MotanConsumerFetchRequestURLInterceptor} to intercept{@link MotanConsumerFetchRequestURLInterceptor}. + * + * @author zhangxin + */ +public class MotanConsumerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "com.weibo.api.motan.cluster.support.ClusterSpi"; + + private static final String FETCH_REQUEST_URL_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.motan.MotanConsumerFetchRequestURLInterceptor"; + + private static final String INVOKE_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.motan.MotanConsumerInvokeInterceptor"; + + @Override + protected String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("setUrl"); + } + + @Override + public String getMethodsInterceptor() { + return FETCH_REQUEST_URL_INTERCEPT_CLASS; + } + }, new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("call"); + } + + @Override + public String getMethodsInterceptor() { + return INVOKE_INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/define/MotanProviderInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/define/MotanProviderInstrumentation.java new file mode 100644 index 000000000..34db6c28e --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/java/com/a/eye/skywalking/plugin/motan/define/MotanProviderInstrumentation.java @@ -0,0 +1,72 @@ +package com.a.eye.skywalking.plugin.motan.define; + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.motan.MotanProviderInterceptor; +import com.weibo.api.motan.rpc.Request; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import static net.bytebuddy.matcher.ElementMatchers.any; +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link MotanProviderInstrumentation} presents that skywalking will use + * {@link MotanProviderInterceptor} to intercept + * all constructor of {@link com.weibo.api.motan.rpc.AbstractProvider} and + * {@link com.weibo.api.motan.rpc.AbstractProvider#call(Request)}. + * + * @author zhangxin + */ +public class MotanProviderInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + /** + * Enhance class. + */ + private static final String ENHANCE_CLASS = "com.weibo.api.motan.rpc.AbstractProvider"; + /** + * Class that intercept all constructor of ${@link com.weibo.api.motan.rpc.AbstractProvider}. + */ + private static final String CONSTRUCTOR_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.motan.MotanProviderInterceptor"; + /** + * Class that intercept {@link com.weibo.api.motan.rpc.AbstractProvider#call(Request)}. + */ + private static final String PROVIDER_INVOKE_INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.motan.MotanProviderInterceptor"; + + @Override + protected String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPT_CLASS; + } + }}; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("call"); + } + + @Override + public String getMethodsInterceptor() { + return PROVIDER_INVOKE_INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def index e70bf5478..1098cb7c2 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def +++ b/skywalking-sniffer/skywalking-sdk-plugin/motan-plugin/src/main/resources/skywalking-plugin.def @@ -1,2 +1,2 @@ -com.a.eye.skywalking.plugin.motan.define.MotanClientDefine -com.a.eye.skywalking.plugin.motan.define.MotanServerDefine +com.a.eye.skywalking.plugin.motan.define.MotanConsumerInstrumentation +com.a.eye.skywalking.plugin.motan.define.MotanProviderInstrumentation diff --git a/skywalking-sniffer/skywalking-sdk-plugin/pom.xml b/skywalking-sniffer/skywalking-sdk-plugin/pom.xml index ee2399093..1ec3033ac 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/pom.xml +++ b/skywalking-sniffer/skywalking-sdk-plugin/pom.xml @@ -31,7 +31,13 @@ com.a.eye skywalking-api - 3.0-2017 + ${project.version} + + + com.a.eye + skywalking-sniffer-mock + ${project.version} + test diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/TomcatPluginInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/TomcatPluginInterceptor.java deleted file mode 100644 index e46e1b6ab..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/TomcatPluginInterceptor.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.a.eye.skywalking.api.plugin.tomcat78x; - -import com.a.eye.skywalking.api.Tracing; -import com.a.eye.skywalking.invoke.monitor.RPCServerInvokeMonitor; -import com.a.eye.skywalking.model.ContextData; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.ConstructorInvokeContext; -import com.a.eye.skywalking.plugin.interceptor.enhance.InstanceMethodInvokeContext; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; -import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -public class TomcatPluginInterceptor implements InstanceMethodsAroundInterceptor { - private final String secondKey = "ContextData"; - private String tracingName = DEFAULT_TRACE_NAME; - private static final String DEFAULT_TRACE_NAME = "SkyWalking-TRACING-NAME"; - private static final String TRACE_ID_HEADER_NAME = "SW-TraceId"; - - @Override - public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { - Object[] args = interceptorContext.allArguments(); - HttpServletRequest requests = (HttpServletRequest) args[0]; - String tracingHeaderValue = requests.getHeader(tracingName); - ContextData contextData = null; - if (tracingHeaderValue != null) { - String contextDataStr = null; - int index = tracingHeaderValue.indexOf("="); - if (index > 0) { - String key = tracingHeaderValue.substring(0, index); - if (secondKey.equals(key)) { - contextDataStr = tracingHeaderValue.substring(index + 1); - } - } - - if (contextDataStr != null && contextDataStr.length() > 0) { - contextData = new ContextData(contextDataStr); - } - } - RPCServerInvokeMonitor rpcServerInvokeMonitor = new RPCServerInvokeMonitor(); - rpcServerInvokeMonitor.beforeInvoke(contextData, generateIdentification(requests)); - } - - - private Identification generateIdentification(HttpServletRequest request) { - return Identification.newBuilder() - .viewPoint(request.getRequestURL().toString()) - .spanType(WebBuriedPointType.INSTANCE) - .build(); - } - - - @Override - public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) { - Object[] args = interceptorContext.allArguments(); - HttpServletResponse httpServletResponse = (HttpServletResponse) args[1]; - httpServletResponse.addHeader(TRACE_ID_HEADER_NAME, Tracing.getTraceId()); - new RPCServerInvokeMonitor().afterInvoke(); - return ret; - } - - @Override - public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, - InstanceMethodInvokeContext interceptorContext) { - new RPCServerInvokeMonitor().occurException(t); - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/WebBuriedPointType.java b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/WebBuriedPointType.java deleted file mode 100644 index d353c784a..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/WebBuriedPointType.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.a.eye.skywalking.api.plugin.tomcat78x; - -import com.a.eye.skywalking.api.IBuriedPointType; - -public enum WebBuriedPointType implements IBuriedPointType { - INSTANCE; - - @Override - public String getTypeName() { - return "W"; - } - - @Override - public CallType getCallType() { - return CallType.SYNC; - } - -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/define/TomcatPluginDefine.java b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/define/TomcatPluginDefine.java deleted file mode 100644 index d79b185c9..000000000 --- a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/api/plugin/tomcat78x/define/TomcatPluginDefine.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.a.eye.skywalking.api.plugin.tomcat78x.define; - -import com.a.eye.skywalking.plugin.interceptor.ConstructorInterceptPoint; -import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; -import com.a.eye.skywalking.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; -import net.bytebuddy.description.method.MethodDescription; -import net.bytebuddy.matcher.ElementMatcher; - -import static net.bytebuddy.matcher.ElementMatchers.named; - -public class TomcatPluginDefine extends ClassInstanceMethodsEnhancePluginDefine { - @Override - protected String enhanceClassName() { - return "org.apache.catalina.core.StandardEngineValve"; - } - - @Override - protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { - return null; - } - - @Override - protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { - return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { - @Override - public ElementMatcher getMethodsMatcher() { - return named("invoke"); - } - - @Override - public String getMethodsInterceptor() { - return "com.a.eye.skywalking.plugin.tomcat78x.TomcatPluginInterceptor"; - } - }}; - } -} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/plugin/tomcat78x/TomcatInterceptor.java b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/plugin/tomcat78x/TomcatInterceptor.java new file mode 100644 index 000000000..b690b3168 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/plugin/tomcat78x/TomcatInterceptor.java @@ -0,0 +1,79 @@ +package com.a.eye.skywalking.plugin.tomcat78x; + +import com.a.eye.skywalking.api.context.ContextCarrier; +import com.a.eye.skywalking.api.context.ContextManager; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.api.util.StringUtil; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * {@link TomcatInterceptor} fetch the serialized context data by using {@link HttpServletRequest#getHeader(String)}. + * The {@link com.a.eye.skywalking.trace.TraceSegment#primaryRef} of current trace segment will reference to the trace segment id + * of the previous level if the serialized context is not null. + */ +public class TomcatInterceptor implements InstanceMethodsAroundInterceptor { + /** + * Header name that the serialized context data stored in {@link HttpServletRequest#getHeader(String)}. + */ + public static final String HEADER_NAME_OF_CONTEXT_DATA = "SKYWALKING_CONTEXT_DATA"; + /** + * Tomcat component. + */ + public static final String TOMCAT_COMPONENT = "Tomcat"; + + /** + * The {@link com.a.eye.skywalking.trace.TraceSegment#primaryRef} of current trace segment will reference to the trace segment id + * of the previous level if the serialized context is not null. + * + * @param context instance context, a class instance only has one {@link EnhancedClassInstanceContext} instance. + * @param interceptorContext method context, includes class name, method name, etc. + * @param result change this result, if you want to truncate the method. + */ + @Override + public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) { + Object[] args = interceptorContext.allArguments(); + HttpServletRequest request = (HttpServletRequest) args[0]; + + Span span = ContextManager.INSTANCE.createSpan(request.getRequestURI()); + Tags.COMPONENT.set(span, TOMCAT_COMPONENT); + Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_SERVER); + Tags.URL.set(span, request.getRequestURL().toString()); + Tags.SPAN_LAYER.asHttp(span); + + String tracingHeaderValue = request.getHeader(HEADER_NAME_OF_CONTEXT_DATA); + if (!StringUtil.isEmpty(tracingHeaderValue)) { + ContextManager.INSTANCE.extract(new ContextCarrier().deserialize(tracingHeaderValue)); + } + } + + @Override + public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) { + HttpServletResponse response = (HttpServletResponse) interceptorContext.allArguments()[1]; + + Span span = ContextManager.INSTANCE.activeSpan(); + Tags.STATUS_CODE.set(span, response.getStatus()); + + if (response.getStatus() != 200) { + Tags.ERROR.set(span, true); + } + + ContextManager.INSTANCE.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, + InstanceMethodInvokeContext interceptorContext) { + Span span = ContextManager.INSTANCE.activeSpan(); + span.log(t); + Tags.ERROR.set(span, true); + } + +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/plugin/tomcat78x/define/TomcatInstrumentation.java b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/plugin/tomcat78x/define/TomcatInstrumentation.java new file mode 100644 index 000000000..36c120ac5 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/java/com/a/eye/skywalking/plugin/tomcat78x/define/TomcatInstrumentation.java @@ -0,0 +1,58 @@ +package com.a.eye.skywalking.plugin.tomcat78x.define; + +import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import com.a.eye.skywalking.plugin.tomcat78x.TomcatInterceptor; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; + +import org.apache.catalina.connector.Request; +import org.apache.catalina.connector.Response; + +import static net.bytebuddy.matcher.ElementMatchers.named; + +/** + * {@link TomcatInstrumentation} presents that skywalking using class {@link TomcatInterceptor} to + * intercept {@link org.apache.catalina.core.StandardEngineValve#invoke(Request, Response)}. + * + * @author zhangxin + */ +public class TomcatInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + /** + * Enhance class. + */ + private static final String ENHANCE_CLASS = "org.apache.catalina.core.StandardEngineValve"; + + /** + * Intercept class. + */ + private static final String INTERCEPT_CLASS = "com.a.eye.skywalking.plugin.tomcat78x.TomcatInterceptor"; + + @Override + protected String enhanceClassName() { + return ENHANCE_CLASS; + } + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return null; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("invoke"); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPT_CLASS; + } + }}; + } +} diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def index 9433b13c2..b98f1ae95 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def +++ b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/main/resources/skywalking-plugin.def @@ -1 +1 @@ -com.a.eye.skywalking.plugin.tomcat78x.define.TomcatPluginDefine +com.a.eye.skywalking.plugin.tomcat78x.define.TomcatInstrumentation diff --git a/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/com/a/eye/skywalking/plugin/tomcat78x/TomcatInterceptorTest.java b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/com/a/eye/skywalking/plugin/tomcat78x/TomcatInterceptorTest.java new file mode 100644 index 000000000..61f8501d8 --- /dev/null +++ b/skywalking-sniffer/skywalking-sdk-plugin/tomcat-7.x-8.x-plugin/src/test/java/com/a/eye/skywalking/plugin/tomcat78x/TomcatInterceptorTest.java @@ -0,0 +1,142 @@ +package com.a.eye.skywalking.plugin.tomcat78x; + +import com.a.eye.skywalking.api.context.TracerContext; +import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext; +import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult; +import com.a.eye.skywalking.sniffer.mock.context.MockTracerContextListener; +import com.a.eye.skywalking.sniffer.mock.context.SegmentAssert; +import com.a.eye.skywalking.trace.LogData; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.TraceSegment; +import com.a.eye.skywalking.trace.TraceSegmentRef; +import com.a.eye.skywalking.trace.tag.Tags; + +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class TomcatInterceptorTest { + + private TomcatInterceptor tomcatInterceptor; + private MockTracerContextListener contextListener; + + @Mock + private HttpServletRequest request; + @Mock + private HttpServletResponse response; + @Mock + private EnhancedClassInstanceContext classInstanceContext; + @Mock + private InstanceMethodInvokeContext methodInvokeContext; + @Mock + private MethodInterceptResult methodInterceptResult; + + @Before + public void setUp() throws Exception { + tomcatInterceptor = new TomcatInterceptor(); + contextListener = new MockTracerContextListener(); + + TracerContext.ListenerManager.add(contextListener); + + when(request.getRequestURI()).thenReturn("/test/testRequestURL"); + when(request.getRequestURL()).thenReturn(new StringBuffer("http://localhost:8080/test/testRequestURL")); + when(response.getStatus()).thenReturn(200); + when(methodInvokeContext.allArguments()).thenReturn(new Object[]{request, response}); + } + + @Test + public void testWithoutSerializedContextData() { + tomcatInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + tomcatInterceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + } + }); + } + + @Test + public void testWithSerializedContextData() { + when(request.getHeader(TomcatInterceptor.HEADER_NAME_OF_CONTEXT_DATA)).thenReturn("302017.1487666919810.624424584.17332.1.1|1|REMOTE_APP|127.0.0.1"); + + tomcatInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + tomcatInterceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + assertTraceSegmentRef(traceSegment.getPrimaryRef()); + } + }); + } + + @Test + public void testWithOccurException(){ + tomcatInterceptor.beforeMethod(classInstanceContext, methodInvokeContext, methodInterceptResult); + tomcatInterceptor.handleMethodException(new RuntimeException(), classInstanceContext, methodInvokeContext); + tomcatInterceptor.afterMethod(classInstanceContext, methodInvokeContext, null); + + contextListener.assertSize(1); + contextListener.assertTraceSegment(0, new SegmentAssert() { + @Override + public void call(TraceSegment traceSegment) { + assertThat(traceSegment.getSpans().size(), is(1)); + Span span = traceSegment.getSpans().get(0); + assertHttpSpan(span); + assertThat(span.getLogs().size(), is(1)); + assertSpanLog(span.getLogs().get(0)); + } + }); + } + + private void assertSpanLog(LogData logData) { + assertThat(logData.getFields().size(), is(4)); + assertThat(logData.getFields().get("event"), CoreMatchers.is("error")); + assertThat(logData.getFields().get("error.kind"), CoreMatchers.is(RuntimeException.class.getName())); + assertNull(logData.getFields().get("message")); + } + + private void assertTraceSegmentRef(TraceSegmentRef ref) { + assertThat(ref.getSpanId(), is(1)); + assertThat(ref.getTraceSegmentId(), is("302017.1487666919810.624424584.17332.1.1")); + } + + private void assertHttpSpan(Span span) { + assertThat(span.getOperationName(), is("/test/testRequestURL")); + assertThat(Tags.COMPONENT.get(span), is("Tomcat")); + assertThat(Tags.URL.get(span), is("http://localhost:8080/test/testRequestURL")); + assertThat(Tags.STATUS_CODE.get(span), is(200)); + assertThat(Tags.SPAN_KIND.get(span), is(Tags.SPAN_KIND_SERVER)); + assertTrue(Tags.SPAN_LAYER.isHttp(span)); + } + + @After + public void tearDown() throws Exception { + TracerContext.ListenerManager.remove(new MockTracerContextListener()); + } + +} \ No newline at end of file diff --git a/skywalking-sniffer/skywalking-toolkit-activation/pom.xml b/skywalking-sniffer/skywalking-toolkit-activation/pom.xml index 29b42a0d9..26ebce22f 100644 --- a/skywalking-sniffer/skywalking-toolkit-activation/pom.xml +++ b/skywalking-sniffer/skywalking-toolkit-activation/pom.xml @@ -23,7 +23,7 @@ com.a.eye skywalking-api - 3.0-2017 + ${project.version}