From 13cf324789f5526dd951dd999f609a5db078d3a2 Mon Sep 17 00:00:00 2001 From: IluckySi <1151262684@qq.com> Date: Sat, 14 Oct 2017 12:21:28 +0800 Subject: [PATCH] Support XMemcached V2.x --- apm-sniffer/apm-agent/pom.xml | 5 + apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../xmemcached-2.x-plugin/pom.xml | 52 +++++++ ...dConstructorWithComplexArgInterceptor.java | 64 ++++++++ ...ConstructorWithHostPortArgInterceptor.java | 32 ++++ ...orWithInetSocketAddressArgInterceptor.java | 35 +++++ ...thInetSocketAddressListArgInterceptor.java | 45 ++++++ .../v2/XMemcachedMethodInterceptor.java | 58 +++++++ .../v2/define/XMemcachedInstrumentation.java | 135 +++++++++++++++++ .../src/main/resources/skywalking-plugin.def | 1 + ...structorWithComplexArgInterceptorTest.java | 56 +++++++ ...tructorWithHostPortArgInterceptorTest.java | 50 +++++++ ...thInetSocketAddressArgInterceptorTest.java | 52 +++++++ ...etSocketAddressListArgInterceptorTest.java | 57 +++++++ .../v2/XMemcachedMethodInterceptorTest.java | 141 ++++++++++++++++++ 15 files changed, 784 insertions(+) create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java create mode 100644 apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java diff --git a/apm-sniffer/apm-agent/pom.xml b/apm-sniffer/apm-agent/pom.xml index 8047e2161..0291c0377 100644 --- a/apm-sniffer/apm-agent/pom.xml +++ b/apm-sniffer/apm-agent/pom.xml @@ -153,6 +153,11 @@ apm-sharding-jdbc-1.5.x-plugin ${project.version} + + org.skywalking + apm-xmemcached-2.x-plugin + ${project.version} + diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 84ccc2193..57ac58141 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -46,6 +46,7 @@ jetty-plugin spymemcached-2.x-plugin sharding-jdbc-1.5.x-plugin + xmemcached-2.x-plugin pom diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml new file mode 100644 index 000000000..69a4eea07 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + org.skywalking + apm-sdk-plugin + 3.2.3-2017 + + + apm-xmemcached-2.x-plugin + xmemcached-2.x-plugin + jar + + + UTF-8 + 2.0.0 + + + + + com.googlecode.xmemcached + xmemcached + ${xmemcached.version} + provided + + + org.apache.logging.log4j + log4j-core + 2.4.1 + test + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java new file mode 100644 index 000000000..6649df283 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptor.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.Map.Entry; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +public class XMemcachedConstructorWithComplexArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + StringBuilder memcachConnInfo = new StringBuilder(); + @SuppressWarnings("unchecked") + Map inetSocketAddressMap = (Map)allArguments[6]; + StringBuilder master = new StringBuilder(); + for (Entry entry : inetSocketAddressMap.entrySet()) { + if (master.length() <= 0) { + master = append(master,entry.getKey()); + } + memcachConnInfo = append(memcachConnInfo, entry.getValue()); + } + memcachConnInfo = master.append(memcachConnInfo); + int l = memcachConnInfo.length(); + if (l > 1) { + memcachConnInfo = new StringBuilder(memcachConnInfo.substring(0, l - 1)); + } + objInst.setSkyWalkingDynamicField(memcachConnInfo.toString()); + } + + /** + * Parse InetSocketAddress + * @param sb + * @param inetSocketAddress + * @return + */ + private StringBuilder append(StringBuilder sb, InetSocketAddress inetSocketAddress) { + if (inetSocketAddress != null) { + String host = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); + sb.append(host).append(":").append(port).append(";"); + } + return sb; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java new file mode 100644 index 000000000..d54e2af7f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptor.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +public class XMemcachedConstructorWithHostPortArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + Object host = allArguments[0]; + Object port = allArguments[1]; + objInst.setSkyWalkingDynamicField(host + ":" + port); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java new file mode 100644 index 000000000..d013d9d29 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptor.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.net.InetSocketAddress; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +public class XMemcachedConstructorWithInetSocketAddressArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + InetSocketAddress inetSocketAddress = (InetSocketAddress)allArguments[0]; + String host = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); + objInst.setSkyWalkingDynamicField(host + ":" + port); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java new file mode 100644 index 000000000..fb538b346 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptor.java @@ -0,0 +1,45 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.net.InetSocketAddress; +import java.util.List; + +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +public class XMemcachedConstructorWithInetSocketAddressListArgInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + StringBuilder memcachConnInfo = new StringBuilder(); + @SuppressWarnings("unchecked") + List inetSocketAddressList = (List)allArguments[0]; + for (InetSocketAddress inetSocketAddress : inetSocketAddressList) { + String host = inetSocketAddress.getAddress().getHostAddress(); + int port = inetSocketAddress.getPort(); + memcachConnInfo.append(host).append(":").append(port).append(";"); + } + int l = memcachConnInfo.length(); + if (l > 1) { + memcachConnInfo = new StringBuilder(memcachConnInfo.substring(0, l - 1)); + } + objInst.setSkyWalkingDynamicField(memcachConnInfo.toString()); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java new file mode 100644 index 000000000..c3d30d8da --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptor.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import java.lang.reflect.Method; + +import org.skywalking.apm.agent.core.context.ContextManager; +import org.skywalking.apm.agent.core.context.tag.Tags; +import org.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.skywalking.apm.network.trace.component.ComponentsDefine; + +public class XMemcachedMethodInterceptor implements InstanceMethodsAroundInterceptor { + + private static final String XMEMCACHED = "XMemcached/"; + + @Override public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, MethodInterceptResult result) throws Throwable { + String peer = String.valueOf(objInst.getSkyWalkingDynamicField()); + AbstractSpan span = ContextManager.createExitSpan(XMEMCACHED + method.getName(), peer); + span.setComponent(ComponentsDefine.MEMCACHE); + Tags.DB_TYPE.set(span, ComponentsDefine.MEMCACHE.getName()); + SpanLayer.asDB(span); + Tags.DB_STATEMENT.set(span, method.getName() + " " + allArguments[0]); + } + + @Override public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + ContextManager.stopSpan(); + return ret; + } + + @Override public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + AbstractSpan span = ContextManager.activeSpan(); + span.errorOccurred(); + span.log(t); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java new file mode 100644 index 000000000..8a6fb3ea5 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/java/org/skywalking/apm/plugin/xmemcached/v2/define/XMemcachedInstrumentation.java @@ -0,0 +1,135 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2.define; + +import java.net.InetSocketAddress; +import java.util.List; +import java.util.Map; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArgument; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * {@link MemcachedInstrumentation} presents that skywalking intercept all constructors and methods of + * {@link net.rubyeye.xmemcached.XMemcachedClient}. + * {@link XMemcachedConstructorWithHostPortArgInterceptor} intercepts the constructor with + * ip and port arguments. + * {@link XMemcachedConstructorWithInetSocketAddressArgInterceptor} intercepts the constructor with + * argument {@link java.net.InetSocketAddress}. + * {@link XMemcachedConstructorWithInetSocketAddressListArgInterceptor} intercepts the constructor with + * argument {@link java.net.InetSocketAddress}. + * {@link XMemcachedConstructorWithComplexArgInterceptor} intercepts the constructor with complex arguments. + * + * @author IluckySi + */ +public class XMemcachedInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "net.rubyeye.xmemcached.XMemcachedClient"; + private static final String CONSTRUCTOR_WITH_HOSTPORT_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithHostPortArgInterceptor"; + private static final String CONSTRUCTOR_WITH_INETSOCKETADDRESS_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithInetSocketAddressArgInterceptor"; + private static final String CONSTRUCTOR_WITH_INETSOCKETADDRESS_LIST_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithInetSocketAddressListArgInterceptor"; + private static final String CONSTRUCTOR_WITH_COMPLEX_ARG_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedConstructorWithComplexArgInterceptor"; + private static final String METHOD_INTERCEPT_CLASS = "org.skywalking.apm.plugin.xmemcached.v2.XMemcachedMethodInterceptor"; + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(String.class, int.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_HOSTPORT_ARG_INTERCEPT_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, InetSocketAddress.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_INETSOCKETADDRESS_ARG_INTERCEPT_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(0, List.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_INETSOCKETADDRESS_LIST_ARG_INTERCEPT_CLASS; + } + }, + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgument(6, Map.class); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_WITH_COMPLEX_ARG_INTERCEPT_CLASS; + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("get").or(named("set")) .or(named("add")).or(named("replace")).or(named("gets")) + .or(named("append")) .or(named("prepend")).or(named("cas")).or(named("delete")).or(named("touch")). + or(named("getAndTouch")).or(named("incr")) .or(named("decr")); + } + + @Override + public String getMethodsInterceptor() { + return METHOD_INTERCEPT_CLASS; + } + + @Override public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 000000000..c04b8817b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1 @@ +memcache-2.x=org.skywalking.apm.plugin.xmemcached.v2.define.XMemcachedInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java new file mode 100644 index 000000000..6615eee2f --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithComplexArgInterceptorTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithComplexArgInterceptorTest { + + private XMemcachedConstructorWithComplexArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithComplexArgInterceptor(); + } + + @Test + public void onConstructWithComplex() { + Map inetSocketAddressMap = new HashMap(); + inetSocketAddressMap.put(new InetSocketAddress("127.0.0.1", 11211), new InetSocketAddress("127.0.0.2", 11211)); + interceptor.onConstruct(enhancedInstance, new Object[]{null, null, null, null, null, null, inetSocketAddressMap}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211;127.0.0.2:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java new file mode 100644 index 000000000..ae8101e19 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithHostPortArgInterceptorTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithHostPortArgInterceptorTest { + + private XMemcachedConstructorWithHostPortArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithHostPortArgInterceptor(); + } + + @Test + public void onConstructWithHostPort() { + interceptor.onConstruct(enhancedInstance, new Object[]{"127.0.0.1", 11211}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java new file mode 100644 index 000000000..f83178ba9 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressArgInterceptorTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithInetSocketAddressArgInterceptorTest { + + private XMemcachedConstructorWithInetSocketAddressArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithInetSocketAddressArgInterceptor(); + } + + @Test + public void onConstructWithInetSocketAddress() { + interceptor.onConstruct(enhancedInstance, new Object[]{new InetSocketAddress("127.0.0.1", 11211)}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java new file mode 100644 index 000000000..0e4a96ca6 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest.java @@ -0,0 +1,57 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; + +@RunWith(MockitoJUnitRunner.class) +public class XMemcachedConstructorWithInetSocketAddressListArgInterceptorTest { + + private XMemcachedConstructorWithInetSocketAddressListArgInterceptor interceptor; + + @Mock + private EnhancedInstance enhancedInstance; + + @Before + public void setUp() throws Exception { + interceptor = new XMemcachedConstructorWithInetSocketAddressListArgInterceptor(); + } + + @Test + public void onConstructWithInetSocketAddressList() { + List inetSocketAddressList = new ArrayList(); + inetSocketAddressList.add(new InetSocketAddress("127.0.0.1", 11211)); + inetSocketAddressList.add(new InetSocketAddress("127.0.0.2", 11211)); + interceptor.onConstruct(enhancedInstance, new Object[]{inetSocketAddressList}); + + verify(enhancedInstance, times(1)).setSkyWalkingDynamicField("127.0.0.1:11211;127.0.0.2:11211"); + } +} \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java new file mode 100644 index 000000000..4a3ba6f26 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/xmemcached-2.x-plugin/src/test/java/org/skywalking/apm/plugin/xmemcached/v2/XMemcachedMethodInterceptorTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 2017, OpenSkywalking Organization All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Project repository: https://github.com/OpenSkywalking/skywalking + */ + +package org.skywalking.apm.plugin.xmemcached.v2; + +import static junit.framework.TestCase.assertNotNull; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Method; +import java.util.List; + +import org.hamcrest.CoreMatchers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.modules.junit4.PowerMockRunnerDelegate; +import org.skywalking.apm.agent.core.context.trace.AbstractTracingSpan; +import org.skywalking.apm.agent.core.context.trace.LogDataEntity; +import org.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.skywalking.apm.agent.core.context.trace.TraceSegment; +import org.skywalking.apm.agent.core.context.util.KeyValuePair; +import org.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.skywalking.apm.agent.test.helper.SegmentHelper; +import org.skywalking.apm.agent.test.helper.SpanHelper; +import org.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.skywalking.apm.agent.test.tools.SegmentStorage; +import org.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.skywalking.apm.agent.test.tools.TracingSegmentRunner; + +import net.rubyeye.xmemcached.XMemcachedClient; + +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class XMemcachedMethodInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Mock + private EnhancedInstance enhancedInstance; + private XMemcachedMethodInterceptor interceptor; + + private Object[] allArgument; + private Class[] argumentType; + + @Before + public void setUp() throws Exception { + allArgument = new Object[] {"OperationKey", "OperationValue"}; + argumentType = new Class[] {String.class, String.class}; + + interceptor = new XMemcachedMethodInterceptor(); + when(enhancedInstance.getSkyWalkingDynamicField()).thenReturn("127.0.0.1:11211"); + } + + @Test + public void testIntercept() throws Throwable { + interceptor.beforeMethod(enhancedInstance, getMockSetMethod(), allArgument, argumentType, null); + interceptor.afterMethod(enhancedInstance, getMockGetMethod(), allArgument, argumentType, null); + + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertThat(spans.size(), is(1)); + assertMemcacheSpan(spans.get(0)); + } + + @Test + public void testInterceptWithException() throws Throwable { + interceptor.beforeMethod(enhancedInstance, getMockSetMethod(), allArgument, argumentType, null); + interceptor.handleMethodException(enhancedInstance, getMockSetMethod(), allArgument, argumentType, new RuntimeException()); + interceptor.afterMethod(enhancedInstance, getMockSetMethod(), allArgument, argumentType, null); + + TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0); + List spans = SegmentHelper.getSpans(traceSegment); + assertThat(spans.size(), is(1)); + assertMemcacheSpan(spans.get(0)); + + assertLogData(SpanHelper.getLogs(spans.get(0))); + } + + private void assertLogData(List logDataEntities) { + assertThat(logDataEntities.size(), is(1)); + LogDataEntity logData = logDataEntities.get(0); + Assert.assertThat(logData.getLogs().size(), is(4)); + Assert.assertThat(logData.getLogs().get(0).getValue(), CoreMatchers.is("error")); + Assert.assertThat(logData.getLogs().get(1).getValue(), CoreMatchers.is(RuntimeException.class.getName())); + Assert.assertNull(logData.getLogs().get(2).getValue()); + assertNotNull(logData.getLogs().get(3).getValue()); + } + + private void assertMemcacheSpan(AbstractTracingSpan span) { + assertThat(span.getOperationName(), is("XMemcached/set")); + assertThat(span.isExit(), is(true)); + assertThat(SpanHelper.getComponentId(span), is(20)); + List tags = SpanHelper.getTags(span); + assertThat(tags.get(0).getValue(), is("Memcache")); + assertThat(tags.get(1).getValue(), is("set OperationKey")); + assertThat(SpanHelper.getLayer(span), is(SpanLayer.DB)); + } + + private Method getMockSetMethod() { + try { + return XMemcachedClient.class.getMethod("set", String.class, int.class, Object.class); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return null; + } + } + + private Method getMockGetMethod() { + try { + return XMemcachedClient.class.getMethod("get", String.class); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return null; + } + } +} \ No newline at end of file -- GitLab