This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-java.git


The following commit(s) were added to refs/heads/main by this push:
     new 30d60b9c61 Update Jedis 4.x plugin to support Sharding and Cluster 
models. (#677)
30d60b9c61 is described below

commit 30d60b9c610845d20e44cb667e19afa2b09771e6
Author: pg.yang <pg.y...@hotmail.com>
AuthorDate: Sun Mar 31 20:13:03 2024 +0800

    Update Jedis 4.x plugin to support Sharding and Cluster models. (#677)
---
 CHANGES.md                                         |   1 +
 .../jedis/v4/AbstractConnectionInterceptor.java    |   8 +-
 .../jedis/v4/ConnectionConstructorInterceptor.java |   4 +-
 ...Interceptor.java => ConnectionInformation.java} |  15 +--
 ... ConnectionProviderConstructorInterceptor.java} |  22 +++-
 ...ConnectionProviderGetConnectionInterceptor.java |  60 +++++++++++
 .../plugin/jedis/v4/JedisMethodInterceptor.java    |   8 +-
 .../define/ConnectionProviderInstrumentation.java  |  81 +++++++++++++++
 .../src/main/resources/skywalking-plugin.def       |   3 +-
 .../jedis-4.x-scenario/config/expectedData.yaml    | 113 ++++++++++++++++++++-
 .../scenarios/jedis-4.x-scenario/configuration.yml |  19 ++++
 .../testcase/jedis/controller/CaseController.java  |  32 +++++-
 .../testcase/jedis/controller/ClusterExecutor.java |  42 ++++++++
 .../jedis/controller/ShardingExecutor.java         |  42 ++++++++
 .../jedis-4.x-scenario/support-version.list        |   4 +-
 15 files changed, 431 insertions(+), 23 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 5627ea6ad0..eef33563e1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -19,6 +19,7 @@ Release Notes.
 * Fix a bug in Spring Cloud Gateway if HttpClientFinalizer#send does not 
invoke, the span created at NettyRoutingFilterInterceptor can not stop.
 * Fix not tracing in HttpClient v5 when HttpHost(arg[0]) is null but 
`RoutingSupport#determineHost` works.
 * Support across thread tracing for SOFA-RPC.
+* Update Jedis 4.x plugin to support Sharding and Cluster models.
 
 #### Documentation
 * Update docs to describe `expired-plugins`.
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java
index 79f2f15858..a1a8a16225 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/AbstractConnectionInterceptor.java
@@ -18,6 +18,7 @@
 package org.apache.skywalking.apm.plugin.jedis.v4;
 
 import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
 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;
@@ -39,6 +40,8 @@ public abstract class AbstractConnectionInterceptor 
implements InstanceMethodsAr
 
     private static final String CACHE_TYPE = "Redis";
 
+    private static final StringTag TAG_ARGS = new StringTag("actual_target");
+
     @Override
     public void beforeMethod(EnhancedInstance objInst, Method method, Object[] 
allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws 
Throwable {
         Iterator<Rawable> iterator = getCommands(allArguments);
@@ -49,12 +52,15 @@ public abstract class AbstractConnectionInterceptor 
implements InstanceMethodsAr
         // Use lowercase to make config compatible with jedis-2.x-3.x plugin
         // Refer to `plugin.jedis.operation_mapping_read`, 
`plugin.jedis.operation_mapping_write` config item in agent.config
         String cmd = protocolCommand == null ? UNKNOWN : 
protocolCommand.toLowerCase();
-        String peer = String.valueOf(objInst.getSkyWalkingDynamicField());
+        ConnectionInformation connectionData = (ConnectionInformation) 
objInst.getSkyWalkingDynamicField();
+        // Use cluster information to adapt Virtual Cache if exists, otherwise 
use real server host
+        String peer =  StringUtil.isBlank(connectionData.getClusterNodes()) ? 
connectionData.getActualTarget() : connectionData.getClusterNodes();
         AbstractSpan span = ContextManager.createExitSpan("Jedis/" + cmd, 
peer);
         span.setComponent(ComponentsDefine.JEDIS);
         readKeyIfNecessary(iterator).ifPresent(key -> Tags.CACHE_KEY.set(span, 
key));
         Tags.CACHE_CMD.set(span, cmd);
         Tags.CACHE_TYPE.set(span, CACHE_TYPE);
+        TAG_ARGS.set(span, connectionData.getActualTarget());
         parseOperation(cmd).ifPresent(op -> Tags.CACHE_OP.set(span, op));
         SpanLayer.asCache(span);
     }
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
index 825042613d..550db0072d 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
@@ -26,6 +26,8 @@ public class ConnectionConstructorInterceptor implements 
InstanceConstructorInte
     @Override
     public void onConstruct(EnhancedInstance objInst, Object[] allArguments) 
throws Throwable {
         HostAndPort hostAndPort = ((DefaultJedisSocketFactory) 
allArguments[0]).getHostAndPort();
-        objInst.setSkyWalkingDynamicField(hostAndPort.getHost() + ":" + 
hostAndPort.getPort());
+        ConnectionInformation connectionData = new ConnectionInformation();
+        connectionData.setActualTarget(hostAndPort.toString());
+        objInst.setSkyWalkingDynamicField(connectionData);
     }
 }
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java
similarity index 56%
copy from 
apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
copy to 
apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java
index 825042613d..002deff4fc 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionInformation.java
@@ -17,15 +17,10 @@
 
 package org.apache.skywalking.apm.plugin.jedis.v4;
 
-import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import redis.clients.jedis.DefaultJedisSocketFactory;
-import redis.clients.jedis.HostAndPort;
+import lombok.Data;
 
-public class ConnectionConstructorInterceptor implements 
InstanceConstructorInterceptor {
-    @Override
-    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) 
throws Throwable {
-        HostAndPort hostAndPort = ((DefaultJedisSocketFactory) 
allArguments[0]).getHostAndPort();
-        objInst.setSkyWalkingDynamicField(hostAndPort.getHost() + ":" + 
hostAndPort.getPort());
-    }
+@Data
+public class ConnectionInformation {
+    private String clusterNodes;
+    private String actualTarget;
 }
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java
similarity index 58%
copy from 
apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
copy to 
apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java
index 825042613d..21939a62e9 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionConstructorInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderConstructorInterceptor.java
@@ -17,15 +17,27 @@
 
 package org.apache.skywalking.apm.plugin.jedis.v4;
 
+import java.util.Collection;
 import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import redis.clients.jedis.DefaultJedisSocketFactory;
+import org.apache.skywalking.apm.util.StringUtil;
 import redis.clients.jedis.HostAndPort;
 
-public class ConnectionConstructorInterceptor implements 
InstanceConstructorInterceptor {
+public class ConnectionProviderConstructorInterceptor implements 
InstanceConstructorInterceptor {
     @Override
-    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) 
throws Throwable {
-        HostAndPort hostAndPort = ((DefaultJedisSocketFactory) 
allArguments[0]).getHostAndPort();
-        objInst.setSkyWalkingDynamicField(hostAndPort.getHost() + ":" + 
hostAndPort.getPort());
+    public void onConstruct(final EnhancedInstance objInst, final Object[] 
allArguments) throws Throwable {
+        if (objInst.getSkyWalkingDynamicField() != null) {
+            return;
+        }
+        Object arg = allArguments[0];
+        if (arg instanceof Collection) {
+            Collection<?> collection = (Collection<?>) arg;
+            final String[] array = 
collection.stream().map(Object::toString).toArray(String[]::new);
+            objInst.setSkyWalkingDynamicField(StringUtil.join(',', array));
+        }
+        if (arg instanceof HostAndPort) {
+            objInst.setSkyWalkingDynamicField(arg.toString());
+        }
     }
+
 }
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java
new file mode 100644
index 0000000000..12409de61d
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/ConnectionProviderGetConnectionInterceptor.java
@@ -0,0 +1,60 @@
+/*
+ *   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.jedis.v4;
+
+import java.lang.reflect.Method;
+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;
+
+public class ConnectionProviderGetConnectionInterceptor implements 
InstanceMethodsAroundInterceptor {
+    @Override
+    public void beforeMethod(final EnhancedInstance objInst,
+                             final Method method,
+                             final Object[] allArguments,
+                             final Class<?>[] argumentsTypes,
+                             final MethodInterceptResult result) throws 
Throwable {
+
+    }
+
+    @Override
+    public Object afterMethod(final EnhancedInstance objInst,
+                              final Method method,
+                              final Object[] allArguments,
+                              final Class<?>[] argumentsTypes,
+                              final Object ret) throws Throwable {
+        if (ret instanceof EnhancedInstance) {
+            EnhancedInstance connection = (EnhancedInstance) ret;
+            if (connection.getSkyWalkingDynamicField() != null
+                && connection.getSkyWalkingDynamicField() instanceof 
ConnectionInformation) {
+                ((ConnectionInformation) 
connection.getSkyWalkingDynamicField()).setClusterNodes(
+                    (String) objInst.getSkyWalkingDynamicField());
+            }
+        }
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(final EnhancedInstance objInst,
+                                      final Method method,
+                                      final Object[] allArguments,
+                                      final Class<?>[] argumentsTypes,
+                                      final Throwable t) {
+
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java
index 26175616e0..dcf181b3e5 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/JedisMethodInterceptor.java
@@ -18,6 +18,7 @@
 package org.apache.skywalking.apm.plugin.jedis.v4;
 
 import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
 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;
@@ -27,18 +28,23 @@ import 
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInt
 import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
 
 import java.lang.reflect.Method;
+import org.apache.skywalking.apm.util.StringUtil;
 
 public class JedisMethodInterceptor implements 
InstanceMethodsAroundInterceptor {
+    private static final StringTag TAG_ARGS = new StringTag("actual_target");
 
     @Override
     public void beforeMethod(EnhancedInstance objInst, Method method, Object[] 
allArguments, Class<?>[] argumentsTypes,
                              MethodInterceptResult result) throws Throwable {
-        String peer = String.valueOf(objInst.getSkyWalkingDynamicField());
+        final ConnectionInformation connectionData = (ConnectionInformation) 
objInst.getSkyWalkingDynamicField();
+        // Use cluster information to adapt Virtual Cache if exists, otherwise 
use real server host
+        String peer =  StringUtil.isBlank(connectionData.getClusterNodes()) ? 
connectionData.getActualTarget() : connectionData.getClusterNodes();
         AbstractSpan span = ContextManager.createExitSpan("Jedis/" + 
method.getName(), peer);
         span.setComponent(ComponentsDefine.JEDIS);
         SpanLayer.asCache(span);
         Tags.CACHE_TYPE.set(span, "Redis");
         Tags.CACHE_CMD.set(span, "BATCH_EXECUTE");
+        TAG_ARGS.set(span, connectionData.getActualTarget());
     }
 
     @Override
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java
new file mode 100644
index 0000000000..d376fb3d6a
--- /dev/null
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/jedis/v4/define/ConnectionProviderInstrumentation.java
@@ -0,0 +1,81 @@
+/*
+ *   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.jedis.v4.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import net.bytebuddy.matcher.ElementMatchers;
+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.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.hasSuperType;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static 
org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch;
+
+public class ConnectionProviderInstrumentation extends 
AbstractWitnessInstrumentation {
+
+    private static final String ENHANCE_INTERFACE = 
"redis.clients.jedis.providers.ConnectionProvider";
+    private static final String 
CONNECTION_PROVIDER_CONSTRUCTION_INTERCEPT_CLASS = 
"org.apache.skywalking.apm.plugin.jedis.v4.ConnectionProviderConstructorInterceptor";
+    private static final String 
CONNECTION_PROVIDER_GET_CONNECTION_INTERCEPT_CLASS = 
"org.apache.skywalking.apm.plugin.jedis.v4.ConnectionProviderGetConnectionInterceptor";
+
+    @Override
+    protected ClassMatch enhanceClass() {
+        return byHierarchyMatch(ENHANCE_INTERFACE);
+    }
+
+    @Override
+    public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[]{
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> 
getConstructorMatcher() {
+                    return ElementMatchers.takesArgument(0, 
named("redis.clients.jedis.HostAndPort"))
+                                          .or(ElementMatchers.takesArgument(0, 
hasSuperType(named("java.util.Collection"))));
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return CONNECTION_PROVIDER_CONSTRUCTION_INTERCEPT_CLASS;
+                }
+            }
+        };
+    }
+
+    @Override
+    public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() 
{
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("getConnection");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return CONNECTION_PROVIDER_GET_CONNECTION_INTERCEPT_CLASS;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
+    }
+}
diff --git 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def
 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def
index a226a135b5..ae23cce498 100644
--- 
a/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def
+++ 
b/apm-sniffer/apm-sdk-plugin/jedis-plugins/jedis-4.x-plugin/src/main/resources/skywalking-plugin.def
@@ -16,4 +16,5 @@
 
 
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.ConnectionInstrumentation
 
jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.PipelineInstrumentation
-jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.TransactionConstructorInstrumentation
\ No newline at end of file
+jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.TransactionConstructorInstrumentation
+jedis-4.x=org.apache.skywalking.apm.plugin.jedis.v4.define.ConnectionProviderInstrumentation
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml 
b/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml
index 6be161a8b8..14e3547916 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/jedis-4.x-scenario/config/expectedData.yaml
@@ -36,6 +36,7 @@ segmentItems:
               - {key: cache.key, value: a}
               - {key: cache.cmd, value: set}
               - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
               - {key: cache.op, value: write}
           - operationName: Jedis/get
             operationId: 0
@@ -53,6 +54,7 @@ segmentItems:
               - {key: cache.key, value: a}
               - {key: cache.cmd, value: get}
               - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
               - {key: cache.op, value: read}
           - operationName: Jedis/del
             operationId: 0
@@ -70,6 +72,7 @@ segmentItems:
               - {key: cache.key, value: a}
               - {key: cache.cmd, value: del}
               - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
               - {key: cache.op, value: write}
           - operationName: Jedis/syncAndReturnAll
             operationId: 0
@@ -86,6 +89,7 @@ segmentItems:
             tags:
               - {key: cache.type, value: Redis}
               - {key: cache.cmd, value: BATCH_EXECUTE}
+              - {key: actual_target, value: 'redis-server:6379'}
           - operationName: Jedis/exec
             operationId: 0
             parentSpanId: 0
@@ -101,6 +105,7 @@ segmentItems:
             tags:
               - {key: cache.type, value: Redis}
               - {key: cache.cmd, value: BATCH_EXECUTE}
+              - {key: actual_target, value: 'redis-server:6379'}
           - operationName: Jedis/discard
             operationId: 0
             parentSpanId: 0
@@ -116,6 +121,7 @@ segmentItems:
             tags:
               - {key: cache.type, value: Redis}
               - {key: cache.cmd, value: BATCH_EXECUTE}
+              - {key: actual_target, value: 'redis-server:6379'}
           - operationName: Jedis/xadd
             operationId: 0
             parentSpanId: 0
@@ -132,6 +138,7 @@ segmentItems:
               - {key: cache.key, value: abc}
               - {key: cache.cmd, value: xadd}
               - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
               - {key: cache.op, value: write}
           - operationName: Jedis/xread
             operationId: 0
@@ -148,6 +155,7 @@ segmentItems:
             tags:
             - {key: cache.cmd, value: xread}
             - {key: cache.type, value: Redis}
+            - {key: actual_target, value: 'redis-server:6379'}
             - {key: cache.op, value: read}
           - operationName: Jedis/xdel
             operationId: 0
@@ -165,6 +173,109 @@ segmentItems:
               - {key: cache.key, value: abc}
               - {key: cache.cmd, value: xdel}
               - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
+              - {key: cache.op, value: write}
+          - operationName: Jedis/set
+            parentSpanId: 0
+            spanId: 10
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 30
+            isError: false
+            spanType: Exit
+            peer: redis-server:6379,redis-server:6379
+            skipAnalysis: false
+            tags:
+              - {key: cache.key, value: x}
+              - {key: cache.cmd, value: set}
+              - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
+              - {key: cache.op, value: write}
+          - operationName: Jedis/get
+            parentSpanId: 0
+            spanId: 11
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 30
+            isError: false
+            spanType: Exit
+            peer: redis-server:6379,redis-server:6379
+            skipAnalysis: false
+            tags:
+              - {key: cache.key, value: x}
+              - {key: cache.cmd, value: get}
+              - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
+              - {key: cache.op, value: read}
+          - operationName: Jedis/del
+            parentSpanId: 0
+            spanId: 12
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 30
+            isError: false
+            spanType: Exit
+            peer: redis-server:6379,redis-server:6379
+            skipAnalysis: false
+            tags:
+              - {key: cache.key, value: x}
+              - {key: cache.cmd, value: del}
+              - {key: cache.type, value: Redis}
+              - {key: actual_target, value: 'redis-server:6379'}
+              - {key: cache.op, value: write}
+          - operationName: Jedis/set
+            parentSpanId: 0
+            spanId: 13
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 30
+            isError: false
+            spanType: Exit
+            peer: 
redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379
+            skipAnalysis: false
+            tags:
+              - {key: cache.key, value: x}
+              - {key: cache.cmd, value: set}
+              - {key: cache.type, value: Redis}
+              - {key: actual_target, value: not blank }
+              - {key: cache.op, value: write}
+          - operationName: Jedis/get
+            parentSpanId: 0
+            spanId: 14
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 30
+            isError: false
+            spanType: Exit
+            peer: 
redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379
+            skipAnalysis: false
+            tags:
+              - {key: cache.key, value: x}
+              - {key: cache.cmd, value: get}
+              - {key: cache.type, value: Redis}
+              - {key: actual_target, value: not blank}
+              - {key: cache.op, value: read}
+          - operationName: Jedis/del
+            parentSpanId: 0
+            spanId: 15
+            spanLayer: Cache
+            startTime: gt 0
+            endTime: gt 0
+            componentId: 30
+            isError: false
+            spanType: Exit
+            peer: 
redis-cluster-m3:6379,redis-cluster-m2:6379,redis-cluster-m1:6379
+            skipAnalysis: false
+            tags:
+              - {key: cache.key, value: x}
+              - {key: cache.cmd, value: del}
+              - {key: cache.type, value: Redis}
+              - {key: actual_target, value: not blank }
               - {key: cache.op, value: write}
           - operationName: GET:/jedis-scenario/case/jedis-scenario
             operationId: 0
@@ -181,4 +292,4 @@ segmentItems:
             tags:
               - {key: url, value: 
'http://localhost:8080/jedis-scenario/case/jedis-scenario'}
               - {key: http.method, value: GET}
-              - {key: http.status_code, value: '200'}
\ No newline at end of file
+              - {key: http.status_code, value: '200'}
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml 
b/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml
index 79dfda5c0b..e340adec0d 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml
+++ b/test/plugin/scenarios/jedis-4.x-scenario/configuration.yml
@@ -21,8 +21,27 @@ startScript: ./bin/startup.sh
 environment:
   - REDIS_HOST=redis-server
   - REDIS_PORT=6379
+  - REDIS_CLUSTER_M1_HOST=redis-cluster-m1
+  - REDIS_CLUSTER_M1_PORT=6379
+  - REDIS_CLUSTER_M2_HOST=redis-cluster-m2
+  - REDIS_CLUSTER_M2_PORT=6379
+  - REDIS_CLUSTER_M3_HOST=redis-cluster-m3
+  - REDIS_CLUSTER_M3_PORT=6379
+
 dependencies:
   redis-server:
     image: redis:7.0.4
     hostname: redis-server
 
+  redis-cluster-m1:
+    image: redis:7.2.4
+    hostname: redis-cluster-m1
+    command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf 
'%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 
'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup 
redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh  && 
printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create 
redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 
--cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh & [...]
+  redis-cluster-m2:
+    image: redis:7.2.4
+    hostname: redis-cluster-m2
+    command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf 
'%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 
'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup 
redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh  && 
printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create 
redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 
--cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh & [...]
+  redis-cluster-m3:
+    image: redis:7.2.4
+    hostname: redis-cluster-m3
+    command: sh -c " printf '%s\\n' 'port 6379'>> /etc/redis.conf && printf 
'%s\\n' 'cluster-enabled yes'>> /etc/redis.conf && printf '%s\\n' 
'cluster-config-file nodes.conf'>> /etc/redis.conf && printf '%s\\n' 'nohup 
redis-server /etc/redis.conf>>/tmp/redis.log &' >> /tmp/start-redis.sh  && 
printf '%s\\n' 'while true; do printf yes | redis-cli --cluster create 
redis-cluster-m1:6379 redis-cluster-m2:6379 redis-cluster-m3:6379 
--cluster-replicas 0 && break; done ' >> /tmp/start-redis.sh & [...]
diff --git 
a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java
 
b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java
index a7f570960a..fd7999060a 100644
--- 
a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java
+++ 
b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/CaseController.java
@@ -18,10 +18,13 @@
 
 package org.apache.skywalking.apm.testcase.jedis.controller;
 
+import java.util.Arrays;
+import java.util.HashSet;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
+import redis.clients.jedis.HostAndPort;
 
 @RestController
 @RequestMapping("/case")
@@ -35,6 +38,21 @@ public class CaseController {
     @Value("${redis.port:6379}")
     private Integer redisPort;
 
+    @Value("${redis.cluster.m1.host:127.0.0.1}")
+    private String redisClusterM1Host;
+    @Value("${redis.cluster.m1.port:6379}")
+    private Integer redisClusterM1Port;
+
+    @Value("${redis.cluster.m2.host:127.0.0.1}")
+    private String redisClusterM2Host;
+    @Value("${redis.cluster.m2.port:6379}")
+    private Integer redisClusterM2Port;
+
+    @Value("${redis.cluster.m3.host:127.0.0.1}")
+    private String redisClusterM3Host;
+    @Value("${redis.cluster.m3.port:6379}")
+    private Integer redisClusterM3Port;
+
     @RequestMapping("/jedis-scenario")
     @ResponseBody
     public String testcase() throws Exception {
@@ -43,7 +61,6 @@ public class CaseController {
             command.get("a");
             command.del("a");
         }
-
         try (RedisPipelineCommandExecutor command = new 
RedisPipelineCommandExecutor(redisHost, redisPort)) {
             command.pipelineExecute();
         }
@@ -55,7 +72,18 @@ public class CaseController {
         try (RedisStreamCommandExecutor executor = new 
RedisStreamCommandExecutor(redisHost, redisPort)) {
             executor.exec();
         }
-
+        try (ShardingExecutor shardingExecutor = new ShardingExecutor(
+            Arrays.asList(new HostAndPort(redisHost, redisPort), new 
HostAndPort(redisHost, redisPort)))) {
+            shardingExecutor.exec();
+        }
+        try (ClusterExecutor clusterExecutor = new ClusterExecutor(new 
HashSet<>(
+            Arrays.asList(
+                new HostAndPort(redisClusterM1Host, redisClusterM1Port),
+                new HostAndPort(redisClusterM2Host, redisClusterM2Port),
+                new HostAndPort(redisClusterM3Host, redisClusterM3Port)
+            )))) {
+            clusterExecutor.exec();
+        }
         return SUCCESS;
     }
 
diff --git 
a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java
 
b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java
new file mode 100644
index 0000000000..8e9293e04e
--- /dev/null
+++ 
b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ClusterExecutor.java
@@ -0,0 +1,42 @@
+/*
+ * 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.testcase.jedis.controller;
+
+import java.util.Set;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisCluster;
+
+public class ClusterExecutor implements AutoCloseable {
+
+    private final JedisCluster jedisCluster;
+
+    public ClusterExecutor(Set<HostAndPort> jedisClusterNodes) {
+        this.jedisCluster = new JedisCluster(jedisClusterNodes);
+    }
+
+    public void exec() {
+        jedisCluster.set("x", "1");
+        jedisCluster.get("x");
+        jedisCluster.del("x");
+    }
+
+    public void close() {
+        this.jedisCluster.close();
+    }
+}
diff --git 
a/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java
 
b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java
new file mode 100644
index 0000000000..482d942837
--- /dev/null
+++ 
b/test/plugin/scenarios/jedis-4.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/jedis/controller/ShardingExecutor.java
@@ -0,0 +1,42 @@
+/*
+ * 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.testcase.jedis.controller;
+
+import java.util.List;
+import redis.clients.jedis.HostAndPort;
+import redis.clients.jedis.JedisSharding;
+
+public class ShardingExecutor implements AutoCloseable {
+    private JedisSharding jedisSharding;
+
+    public ShardingExecutor(List<HostAndPort> hostAndPorts) {
+        this.jedisSharding = new JedisSharding(hostAndPorts);
+    }
+
+    public void exec() {
+        jedisSharding.set("x", "1");
+        jedisSharding.get("x");
+        jedisSharding.del("x");
+    }
+
+    public void close() {
+        jedisSharding.close();
+    }
+
+}
diff --git a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list 
b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
index 209481d5b8..31258966c3 100644
--- a/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
+++ b/test/plugin/scenarios/jedis-4.x-scenario/support-version.list
@@ -14,6 +14,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+4.4.6
+4.3.2
 4.2.3
 4.1.1
-4.0.1
\ No newline at end of file
+4.0.1


Reply via email to