From 43b216aa923262a1234ee02aa5ae2244b1a7c0fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8E=E7=8E=89=E6=A1=94?= <769213327@qq.com> Date: Fri, 11 Jan 2019 22:32:09 +0800 Subject: [PATCH] Support redisson plugin (#2083) * plugin support redisson --- .../trace/component/ComponentsDefine.java | 7 +- apm-sniffer/apm-sdk-plugin/pom.xml | 1 + .../redisson-3.x-plugin/pom.xml | 46 +++++++ .../v3/ConnectionManagerInterceptor.java | 107 +++++++++++++++++ .../v3/RedisClientConstructorInterceptor.java | 36 ++++++ .../v3/RedisConnectionMethodInterceptor.java | 113 ++++++++++++++++++ .../ConnectionManagerInstrumentation.java | 72 +++++++++++ .../v3/define/RedisClientInstrumentation.java | 67 +++++++++++ .../RedisConnectionInstrumentation.java | 85 +++++++++++++ .../src/main/resources/skywalking-plugin.def | 19 +++ .../RedisConnectionMethodInterceptorTest.java | 85 +++++++++++++ docker/config/component-libraries.yml | 4 + docs/en/guides/Component-library-settings.md | 1 + .../java-agent/Supported-list.md | 1 + .../test/resources/component-libraries.yml | 4 + .../main/resources/component-libraries.yml | 4 + 16 files changed, 650 insertions(+), 2 deletions(-) create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisClientConstructorInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/ConnectionManagerInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisClientInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def create mode 100644 apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptorTest.java diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java index adc249c6a7..2c0c566aec 100644 --- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java +++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java @@ -105,8 +105,10 @@ public class ComponentsDefine { public static final OfficialComponent RABBITMQ_CONSUMER = new OfficialComponent(53,"rabbitmq-consumer"); public static final OfficialComponent CANAL = new OfficialComponent(54,"Canal"); - + public static final OfficialComponent GSON = new OfficialComponent(55,"Gson"); + + public static final OfficialComponent REDISSON = new OfficialComponent(56, "Redisson"); private static ComponentsDefine INSTANCE = new ComponentsDefine(); @@ -117,7 +119,7 @@ public class ComponentsDefine { } public ComponentsDefine() { - components = new String[56]; + components = new String[57]; addComponent(TOMCAT); addComponent(HTTPCLIENT); addComponent(DUBBO); @@ -158,6 +160,7 @@ public class ComponentsDefine { addComponent(RABBITMQ_CONSUMER); addComponent(CANAL); addComponent(GSON); + addComponent(REDISSON); } private void addComponent(OfficialComponent component) { diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 02ab4fa77d..20fd8bd7bd 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -32,6 +32,7 @@ jdbc-commons httpClient-4.x-plugin jedis-2.x-plugin + redisson-3.x-plugin tomcat-7.x-8.x-plugin motan-plugin mongodb-3.x-plugin diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml new file mode 100644 index 0000000000..935b633eb3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/pom.xml @@ -0,0 +1,46 @@ + + + + + 4.0.0 + + org.apache.skywalking + apm-sdk-plugin + 6.0.0-GA-SNAPSHOT + + + apm-redisson-3.x-plugin + jar + + redisson-3.x-plugin + http://maven.apache.org + + 3.6.0 + + + + + org.redisson + redisson + ${redisson.version} + provided + + + + \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java new file mode 100644 index 0000000000..6ff4cec537 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/ConnectionManagerInterceptor.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.redisson.v3; + +import org.apache.skywalking.apm.agent.core.logging.api.ILog; +import org.apache.skywalking.apm.agent.core.logging.api.LogManager; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.redisson.config.*; +import org.redisson.connection.ConnectionManager; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Collection; + +/** + * @author zhaoyuguang + */ +public class ConnectionManagerInterceptor implements InstanceMethodsAroundInterceptor { + + private static final ILog logger = LogManager.getLogger(ConnectionManagerInterceptor.class); + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + } + + @Override + public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Object ret) throws Throwable { + try { + ConnectionManager connectionManager = (ConnectionManager) objInst; + Config config = connectionManager.getCfg(); + + SentinelServersConfig sentinelServersConfig = (SentinelServersConfig) getServersConfig(config, "sentinelServersConfig"); + MasterSlaveServersConfig masterSlaveServersConfig = (MasterSlaveServersConfig) getServersConfig(config, "masterSlaveServersConfig"); + ClusterServersConfig clusterServersConfig = (ClusterServersConfig) getServersConfig(config, "clusterServersConfig"); + ReplicatedServersConfig replicatedServersConfig = (ReplicatedServersConfig) getServersConfig(config, "replicatedServersConfig"); + + StringBuilder peer = new StringBuilder(); + EnhancedInstance retInst = (EnhancedInstance) ret; + + if (sentinelServersConfig != null) { + appendAddresses(peer, sentinelServersConfig.getSentinelAddresses()); + retInst.setSkyWalkingDynamicField(peer.toString()); + return ret; + } + if (masterSlaveServersConfig != null) { + URI masterAddress = masterSlaveServersConfig.getMasterAddress(); + peer.append(masterAddress.getHost()).append(":").append(masterAddress.getPort()); + appendAddresses(peer, masterSlaveServersConfig.getSlaveAddresses()); + retInst.setSkyWalkingDynamicField(peer.toString()); + return ret; + } + if (clusterServersConfig != null) { + appendAddresses(peer, clusterServersConfig.getNodeAddresses()); + retInst.setSkyWalkingDynamicField(peer.toString()); + return ret; + } + if (replicatedServersConfig != null) { + appendAddresses(peer, replicatedServersConfig.getNodeAddresses()); + retInst.setSkyWalkingDynamicField(peer.toString()); + return ret; + } + } catch (Exception e) { + logger.warn("redisClient set peer error: ", e); + } + return ret; + } + + private Object getServersConfig(Config config, String fieldName) throws NoSuchFieldException, IllegalAccessException { + Field field = config.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(config); + } + + private void appendAddresses(StringBuilder peer, Collection nodeAddresses) { + if (nodeAddresses != null && !nodeAddresses.isEmpty()) { + for (URI uri : nodeAddresses) { + peer.append(uri.getHost()).append(":").append(uri.getPort()).append(";"); + } + } + } + + @Override + public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, + Class[] argumentsTypes, Throwable t) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisClientConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisClientConstructorInterceptor.java new file mode 100644 index 0000000000..233334b1d1 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisClientConstructorInterceptor.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.skywalking.apm.plugin.redisson.v3; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; + +/** + * RedisClient is the link between RedisConnection and ConnectionManager. + * to enhance RedisClient for bring peer(the cluster configuration information) in ConnectionManager to RedisConnection. + * + * @author zhaoyuguang + */ +public class RedisClientConstructorInterceptor implements InstanceConstructorInterceptor { + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + } +} diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java new file mode 100644 index 0000000000..398713d2f2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptor.java @@ -0,0 +1,113 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.skywalking.apm.plugin.redisson.v3; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.redisson.client.RedisClient; +import org.redisson.client.RedisConnection; +import org.redisson.client.protocol.CommandData; +import org.redisson.client.protocol.CommandsData; + +import java.lang.reflect.Method; +import java.net.InetSocketAddress; + +/** + * @author zhaoyuguang + */ +public class RedisConnectionMethodInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor { + + @Override + public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class[] argumentsTypes, + MethodInterceptResult result) throws Throwable { + String peer = (String) objInst.getSkyWalkingDynamicField(); + + RedisConnection connection = (RedisConnection) objInst; + Channel channel = connection.getChannel(); + InetSocketAddress remoteAddress = (InetSocketAddress) channel.remoteAddress(); + String dbInstance = remoteAddress.getAddress().getHostAddress() + ":" + remoteAddress.getPort(); + + StringBuilder dbStatement = new StringBuilder(); + String operationName = "Redisson/"; + + if (allArguments[0] instanceof CommandsData) { + operationName = operationName + "BATCH_EXECUTE"; + CommandsData commands = (CommandsData) allArguments[0]; + for (CommandData commandData : commands.getCommands()) { + addCommandData(dbStatement, commandData); + dbStatement.append(";"); + } + } else if (allArguments[0] instanceof CommandData) { + CommandData commandData = (CommandData) allArguments[0]; + String command = commandData.getCommand().getName(); + operationName = operationName + command; + addCommandData(dbStatement, commandData); + } + + AbstractSpan span = ContextManager.createExitSpan(operationName, peer); + span.setComponent(ComponentsDefine.REDISSON); + Tags.DB_TYPE.set(span, "Redis"); + Tags.DB_INSTANCE.set(span, dbInstance); + Tags.DB_STATEMENT.set(span, dbStatement.toString()); + SpanLayer.asCache(span); + } + + private void addCommandData(StringBuilder dbStatement, CommandData commandData) { + dbStatement.append(commandData.getCommand().getName()); + if (commandData.getParams() != null) { + for (Object param : commandData.getParams()) { + dbStatement.append(" ").append(param instanceof ByteBuf ? "?" : String.valueOf(param.toString())); + } + } + } + + @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); + } + + @Override + public void onConstruct(EnhancedInstance objInst, Object[] allArguments) { + String peer = (String) ((EnhancedInstance) allArguments[0]).getSkyWalkingDynamicField(); + if (peer == null) { + peer = ((RedisClient) allArguments[0]).getConfig().getAddress().getAuthority(); + } + objInst.setSkyWalkingDynamicField(peer); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/ConnectionManagerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/ConnectionManagerInstrumentation.java new file mode 100644 index 0000000000..ba89e19ad4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/ConnectionManagerInstrumentation.java @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.skywalking.apm.plugin.redisson.v3.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * @author zhaoyuguang + */ +public class ConnectionManagerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.redisson.connection.MasterSlaveConnectionManager"; + + private static final String CONNECTION_MANAGER_INTERCEPTOR = "org.apache.skywalking.apm.plugin.redisson.v3.ConnectionManagerInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[0]; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("createClient"); + } + + @Override + public String getMethodsInterceptor() { + return CONNECTION_MANAGER_INTERCEPTOR; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisClientInstrumentation.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisClientInstrumentation.java new file mode 100644 index 0000000000..3d13e5818a --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisClientInstrumentation.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.skywalking.apm.plugin.redisson.v3.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.any; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * @author zhaoyuguang + */ +public class RedisClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.redisson.client.RedisClient"; + + private static final String REDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR = "org.apache.skywalking.apm.plugin.redisson.v3.RedisClientConstructorInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return any(); + } + + @Override + public String getConstructorInterceptor() { + return REDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR; + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[0]; + } + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java new file mode 100644 index 0000000000..2e1a71f7a3 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/redisson/v3/define/RedisConnectionInstrumentation.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +package org.apache.skywalking.apm.plugin.redisson.v3.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +/** + * @author zhaoyuguang + */ +public class RedisConnectionInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + + private static final String ENHANCE_CLASS = "org.redisson.client.RedisConnection"; + + private static final String REDISSON_METHOD_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.redisson.v3.RedisConnectionMethodInterceptor"; + + @Override + protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArgumentWithType(0, "org.redisson.client.RedisClient"); + } + + @Override + public String getConstructorInterceptor() { + return REDISSON_METHOD_INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named("send"); + } + + @Override + public String getMethodsInterceptor() { + return REDISSON_METHOD_INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } + + @Override + public ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..fc7b5bf5aa --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.ConnectionManagerInstrumentation +redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.RedisConnectionInstrumentation +redisson-3.x=org.apache.skywalking.apm.plugin.redisson.v3.define.RedisClientInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptorTest.java b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptorTest.java new file mode 100644 index 0000000000..c63dba6630 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/redisson-3.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/redisson/v3/RedisConnectionMethodInterceptorTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.skywalking.apm.plugin.redisson.v3; + +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule; +import org.apache.skywalking.apm.agent.test.tools.SegmentStorage; +import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint; +import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner; +import org.hamcrest.MatcherAssert; +import org.hamcrest.core.Is; +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; + +/** + * @author zhaoyuguang + */ +@RunWith(PowerMockRunner.class) +@PowerMockRunnerDelegate(TracingSegmentRunner.class) +public class RedisConnectionMethodInterceptorTest { + + @SegmentStoragePoint + private SegmentStorage segmentStorage; + + @Rule + public AgentServiceRule serviceRule = new AgentServiceRule(); + + @Mock + private MockInstance mockRedisClientInstance; + @Mock + private MockInstance mockRedisConnectionInstance; + + private RedisConnectionMethodInterceptor interceptor; + + private class MockInstance implements EnhancedInstance { + private Object object; + + @Override + public Object getSkyWalkingDynamicField() { + return object; + } + + @Override + public void setSkyWalkingDynamicField(Object value) { + this.object = value; + } + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @Before + public void setUp() throws Exception { + mockRedisConnectionInstance = new MockInstance(); + mockRedisClientInstance = new MockInstance(); + mockRedisClientInstance.setSkyWalkingDynamicField("127.0.0.1:6379;127.0.0.1:6378;"); + interceptor = new RedisConnectionMethodInterceptor(); + } + + + @Test + public void testIntercept() throws Throwable { + interceptor.onConstruct(mockRedisConnectionInstance, new Object[]{mockRedisClientInstance}); + MatcherAssert.assertThat((String) mockRedisConnectionInstance.getSkyWalkingDynamicField(), Is.is("127.0.0.1:6379;127.0.0.1:6378;")); + } +} diff --git a/docker/config/component-libraries.yml b/docker/config/component-libraries.yml index 69529aca90..5aab3401c1 100644 --- a/docker/config/component-libraries.yml +++ b/docker/config/component-libraries.yml @@ -195,6 +195,9 @@ Canal: Gson: id: 55 languages: Java +Redisson: + id: 56 + languages: Java # .NET/.NET Core components @@ -279,6 +282,7 @@ Component-Server-Mappings: h2-jdbc-driver: H2 mysql-connector-java: Mysql Jedis: Redis + Redisson: Redis StackExchange.Redis: Redis SqlClient: SqlServer Npgsql: PostgreSQL diff --git a/docs/en/guides/Component-library-settings.md b/docs/en/guides/Component-library-settings.md index 966771286d..d2f7634d37 100644 --- a/docs/en/guides/Component-library-settings.md +++ b/docs/en/guides/Component-library-settings.md @@ -55,6 +55,7 @@ Remote server will be conjectured by the local component. The mappings are based Component-Server-Mappings: Jedis: Redis StackExchange.Redis: Redis + Redisson: Redis SqlClient: SqlServer Npgsql: PostgreSQL MySqlConnector: Mysql diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index a9ff4cbec4..10c0892537 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -40,6 +40,7 @@ * NoSQL * Redis * [Jedis](https://github.com/xetorthio/jedis) 2.x + * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.2+ * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14,3.3+ * Memcached Client * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml index 5356ef2716..1bc312661d 100644 --- a/oap-server/server-core/src/test/resources/component-libraries.yml +++ b/oap-server/server-core/src/test/resources/component-libraries.yml @@ -177,6 +177,9 @@ transport-client: Undertow: id: 49 languages: Java +Redisson: + id: 56 + languages: Java # .NET/.NET Core components # [3000, 4000) for C#/.NET only @@ -258,6 +261,7 @@ Component-Server-Mappings: h2-jdbc-driver: H2 mysql-connector-java: Mysql Jedis: Redis + Redisson: Redis StackExchange.Redis: Redis SqlClient: SqlServer Npgsql: PostgreSQL diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml index 69529aca90..4fdf028c24 100644 --- a/oap-server/server-starter/src/main/resources/component-libraries.yml +++ b/oap-server/server-starter/src/main/resources/component-libraries.yml @@ -195,6 +195,9 @@ Canal: Gson: id: 55 languages: Java +Redisson: + id: 56 + languages: Java # .NET/.NET Core components @@ -280,6 +283,7 @@ Component-Server-Mappings: mysql-connector-java: Mysql Jedis: Redis StackExchange.Redis: Redis + Redisson: Redis SqlClient: SqlServer Npgsql: PostgreSQL MySqlConnector: Mysql