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