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 d22e51aedf Added support for Lettuce reactive Redis commands (#788)
d22e51aedf is described below
commit d22e51aedf82524a4ca3aeea3e4b7e9196c71b72
Author: wuwen <[email protected]>
AuthorDate: Tue Feb 24 14:15:47 2026 +0800
Added support for Lettuce reactive Redis commands (#788)
---
.github/workflows/plugins-jdk17-test.1.yaml | 1 +
.github/workflows/plugins-test.1.yaml | 1 +
CHANGES.md | 2 +-
...ReactiveCreatePublisherMethodInterceptorV5.java | 89 ++++++++++++++++
.../RedisReactiveCommandsInstrumentationV5.java | 89 ++++++++++++++++
.../src/main/resources/skywalking-plugin.def | 3 +-
...eactiveCreatePublisherMethodInterceptorV65.java | 93 ++++++++++++++++
.../RedisReactiveCommandsInstrumentationV65.java | 89 ++++++++++++++++
.../src/main/resources/skywalking-plugin.def | 3 +-
.../common/RedisChannelWriterInterceptor.java | 29 ++++-
.../RedisCommandCancelMethodInterceptor.java | 4 +-
...mandCompleteExceptionallyMethodInterceptor.java | 4 +-
.../RedisCommandCompleteMethodInterceptor.java | 4 +-
.../lettuce/common/RedisCommandEnhanceInfo.java | 59 +++++++++++
.../RedisSubscriptionConstructorInterceptor.java | 39 +++++++
...disSubscriptionSubscribeMethodInterceptor.java} | 47 +++++----
.../define/RedisSubscriptionInstrumentation.java | 86 +++++++++++++++
.../src/main/resources/skywalking-plugin.def | 3 +-
.../config/expectedData.yaml | 105 ++++++++++++++++++
.../lettuce/controller/LettuceController.java | 16 +++
.../lettuce-scenario/config/expectedData.yaml | 105 ++++++++++++++++++
.../lettuce/controller/LettuceController.java | 16 +++
.../lettuce-webflux-5x-scenario/bin/startup.sh | 6 +-
.../config/expectedData.yaml | 51 +++++++--
.../lettuce-webflux-5x-scenario/configuration.yml | 15 ++-
.../scenarios/lettuce-webflux-5x-scenario/pom.xml | 98 +++++++++++++++++
.../src/main/assembly/assembly.xml | 41 ++++++++
.../apm/testcase/lettuce/Application.java | 34 ++++++
.../apm/testcase/lettuce/RedisClientConfig.java | 37 +++++++
.../controller/LettuceReactiveController.java | 68 ++++++++++++
.../src/main/resources/application.properties | 18 ++++
.../src/main/resources/log4j2.xml | 30 ++++++
.../support-version.list | 4 +-
.../lettuce-webflux-6x-scenario/bin/startup.sh | 6 +-
.../config/expectedData.yaml | 68 +++++++++---
.../lettuce-webflux-6x-scenario/configuration.yml | 15 ++-
.../scenarios/lettuce-webflux-6x-scenario/pom.xml | 117 +++++++++++++++++++++
.../src/main/assembly/assembly.xml | 41 ++++++++
.../apm/testcase/lettuce/Application.java | 30 ++++++
.../apm/testcase/lettuce/RedisClientConfig.java | 37 +++++++
.../controller/LettuceReactiveController.java | 63 +++++++++++
.../src/main/resources/application.properties | 18 ++++
.../support-version.list | 5 +-
43 files changed, 1621 insertions(+), 68 deletions(-)
diff --git a/.github/workflows/plugins-jdk17-test.1.yaml
b/.github/workflows/plugins-jdk17-test.1.yaml
index 0aa6266813..939393713b 100644
--- a/.github/workflows/plugins-jdk17-test.1.yaml
+++ b/.github/workflows/plugins-jdk17-test.1.yaml
@@ -80,6 +80,7 @@ jobs:
- c3p0-0.9.2.x-0.10.x-scenario
- spring-scheduled-6.x-scenario
- caffeine-3.x-scenario
+ - lettuce-webflux-6x-scenario
steps:
- uses: actions/checkout@v2
with:
diff --git a/.github/workflows/plugins-test.1.yaml
b/.github/workflows/plugins-test.1.yaml
index 5b67f1d22d..21d5f04eab 100644
--- a/.github/workflows/plugins-test.1.yaml
+++ b/.github/workflows/plugins-test.1.yaml
@@ -88,6 +88,7 @@ jobs:
- kotlin-coroutine-scenario
- lettuce-scenario
- lettuce-6.5.x-scenario
+ - lettuce-webflux-5x-scenario
- mongodb-3.x-scenario
- mongodb-4.x-scenario
- netty-socketio-scenario
diff --git a/CHANGES.md b/CHANGES.md
index eaa28ff2c8..29acf896e1 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,7 +5,7 @@ Release Notes.
9.7.0
------------------
-
+* Added support for Lettuce reactive Redis commands.
All issues and pull requests are
[here](https://github.com/apache/skywalking/milestone/249?closed=1)
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java
new file mode 100644
index 0000000000..12ddea18f7
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisReactiveCreatePublisherMethodInterceptorV5.java
@@ -0,0 +1,89 @@
+/*
+ * 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.lettuce.v5;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+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.v2.InstanceMethodsAroundInterceptorV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import reactor.util.context.Context;
+
+import java.lang.reflect.Method;
+import java.util.function.Function;
+
+/**
+ * Intercepts reactive publisher factory methods (createMono/createFlux)
+ * to ensure the SkyWalking context snapshot is propagated via Reactor Context.
+ *
+ * <p>If the Reactor Context does not already contain a snapshot, this
interceptor
+ * captures the current active context and writes it into the subscriber
context
+ * as a fallback propagation mechanism.</p>
+ */
+public class RedisReactiveCreatePublisherMethodInterceptorV5 implements
InstanceMethodsAroundInterceptorV2 {
+
+ private static final String SNAPSHOT_KEY = "SKYWALKING_CONTEXT_SNAPSHOT";
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
+ MethodInvocationContext context) {
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret,
MethodInvocationContext context) {
+
+ if (!(ret instanceof Mono) && !(ret instanceof Flux)) {
+ return ret;
+ }
+ final AbstractSpan localSpan =
ContextManager.createLocalSpan("Lettuce/Reactive/" + method.getName());
+ localSpan.setComponent(ComponentsDefine.LETTUCE);
+ SpanLayer.asCache(localSpan);
+
+ try {
+ final ContextSnapshot snapshot = ContextManager.capture();
+
+ Function<Context, Context> contextFunction = ctx -> {
+ if (ctx.hasKey(SNAPSHOT_KEY)) {
+ return ctx;
+ }
+ return ctx.put(SNAPSHOT_KEY, snapshot);
+ };
+
+ if (ret instanceof Mono) {
+ Mono<?> original = (Mono<?>) ret;
+ return original.subscriberContext(contextFunction);
+ } else {
+ Flux<?> original = (Flux<?>) ret;
+ return original.subscriberContext(contextFunction);
+ }
+ } finally {
+ ContextManager.stopSpan();
+ }
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[]
+ argumentsTypes, Throwable t, MethodInvocationContext context) {
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java
new file mode 100644
index 0000000000..65716edd68
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisReactiveCommandsInstrumentationV5.java
@@ -0,0 +1,89 @@
+/*
+ * 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.lettuce.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.WitnessMethod;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import java.util.Collections;
+import java.util.List;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+import static
org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch;
+
+/**
+ *
+ */
+public class RedisReactiveCommandsInstrumentationV5 extends
ClassInstanceMethodsEnhancePluginDefineV2 {
+
+ private static final String ENHANCE_CLASS =
"io.lettuce.core.AbstractRedisReactiveCommands";
+
+ private static final String REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR =
"org.apache.skywalking.apm.plugin.lettuce.v5.RedisReactiveCreatePublisherMethodInterceptorV5";
+
+ @Override
+ public InstanceMethodsInterceptV2Point[]
getInstanceMethodsInterceptV2Points() {
+ return new InstanceMethodsInterceptV2Point[]{
+ new InstanceMethodsInterceptV2Point() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return namedOneOf(
+ "createMono",
+ "createFlux",
+ "createDissolvingFlux"
+ ).and(takesArguments(1));
+ }
+
+ @Override
+ public String getMethodsInterceptorV2() {
+ return REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ public ClassMatch enhanceClass() {
+ return byHierarchyMatch(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ protected List<WitnessMethod> witnessMethods() {
+ return Collections.singletonList(new WitnessMethod(
+ "reactor.core.publisher.Mono",
+ named("subscriberContext")
+ ));
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def
index 1ff563829d..006ef23680 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-5.x-6.4.x-plugin/src/main/resources/skywalking-plugin.def
@@ -14,4 +14,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentationV5
\ No newline at end of file
+lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentationV5
+lettuce-5.x-6.4.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisReactiveCommandsInstrumentationV5
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java
new file mode 100644
index 0000000000..36320b5cd1
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/RedisReactiveCreatePublisherMethodInterceptorV65.java
@@ -0,0 +1,93 @@
+/*
+ * 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.lettuce.v65;
+
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+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.v2.InstanceMethodsAroundInterceptorV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+import org.reactivestreams.Publisher;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.lang.reflect.Method;
+
+/**
+ * Intercepts reactive publisher factory methods (createMono/createFlux)
+ * to ensure the SkyWalking context snapshot is propagated via Reactor Context.
+ *
+ * <p>If the Reactor Context does not already contain a snapshot, this
interceptor
+ * captures the current active context and writes it into the subscriber
context
+ * as a fallback propagation mechanism.</p>
+ */
+public class RedisReactiveCreatePublisherMethodInterceptorV65 implements
InstanceMethodsAroundInterceptorV2 {
+
+ private static final String SNAPSHOT_KEY = "SKYWALKING_CONTEXT_SNAPSHOT";
+
+ @Override
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes,
+ MethodInvocationContext context) {
+ }
+
+ @Override
+ public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret,
MethodInvocationContext context) {
+
+ if (!(ret instanceof Mono) && !(ret instanceof Flux)) {
+ return ret;
+ }
+
+ final AbstractSpan localSpan =
ContextManager.createLocalSpan("Lettuce/Reactive/" + method.getName());
+ localSpan.setComponent(ComponentsDefine.LETTUCE);
+ SpanLayer.asCache(localSpan);
+
+ try {
+ final ContextSnapshot snapshot = ContextManager.capture();
+
+ return wrapPublisher((Publisher<?>) ret, snapshot);
+ } finally {
+ ContextManager.stopSpan();
+ }
+ }
+
+ private <T> Publisher<T> wrapPublisher(Publisher<T> original,
ContextSnapshot snapshot) {
+ if (original instanceof Mono) {
+ return Mono.deferContextual(ctxView -> {
+ if (ctxView.hasKey(SNAPSHOT_KEY)) {
+ return (Mono<T>) original;
+ }
+ return ((Mono<T>) original).contextWrite(c ->
c.put(SNAPSHOT_KEY, snapshot));
+ });
+ } else {
+ return Flux.deferContextual(ctxView -> {
+ if (ctxView.hasKey(SNAPSHOT_KEY)) {
+ return original;
+ }
+ return ((Flux<T>) original).contextWrite(c ->
c.put(SNAPSHOT_KEY, snapshot));
+ });
+ }
+ }
+
+ @Override
+ public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t,
MethodInvocationContext context) {
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java
new file mode 100644
index 0000000000..f1c22b88ee
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v65/define/RedisReactiveCommandsInstrumentationV65.java
@@ -0,0 +1,89 @@
+/*
+ * 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.lettuce.v65.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.WitnessMethod;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import java.util.Collections;
+import java.util.List;
+
+import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+import static
org.apache.skywalking.apm.agent.core.plugin.match.HierarchyMatch.byHierarchyMatch;
+
+/**
+ *
+ */
+public class RedisReactiveCommandsInstrumentationV65 extends
ClassInstanceMethodsEnhancePluginDefineV2 {
+
+ private static final String ENHANCE_CLASS =
"io.lettuce.core.AbstractRedisReactiveCommands";
+
+ private static final String REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR =
"org.apache.skywalking.apm.plugin.lettuce.v65.RedisReactiveCreatePublisherMethodInterceptorV65";
+
+ @Override
+ public InstanceMethodsInterceptV2Point[]
getInstanceMethodsInterceptV2Points() {
+ return new InstanceMethodsInterceptV2Point[]{
+ new InstanceMethodsInterceptV2Point() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return namedOneOf(
+ "createMono",
+ "createFlux",
+ "createDissolvingFlux"
+ ).and(takesArguments(1));
+ }
+
+ @Override
+ public String getMethodsInterceptorV2() {
+ return REDIS_REACTIVE_CREATEMONO_METHOD_INTERCEPTOR;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ public ClassMatch enhanceClass() {
+ return byHierarchyMatch(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[0];
+ }
+
+ @Override
+ protected List<WitnessMethod> witnessMethods() {
+ return Collections.singletonList(new WitnessMethod(
+ "reactor.core.publisher.Mono",
+ ElementMatchers.named("deferContextual")
+ ));
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
index a503891244..aac68f9479 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
@@ -14,4 +14,5 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
+lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisReactiveCommandsInstrumentationV65
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java
index f8b66f1349..9a94e186d8 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisChannelWriterInterceptor.java
@@ -57,12 +57,17 @@ public class RedisChannelWriterInterceptor implements
InstanceMethodsAroundInter
}
EnhancedInstance enhancedCommand = (EnhancedInstance)
spanCarrierCommand;
+ RedisCommandEnhanceInfo redisCommandEnhanceInfo =
(RedisCommandEnhanceInfo) enhancedCommand.getSkyWalkingDynamicField();
+
+ if (redisCommandEnhanceInfo == null) {
+ redisCommandEnhanceInfo = new RedisCommandEnhanceInfo();
+ }
+
// command has been handle by another channel writer (cluster or
sentinel case)
- if (enhancedCommand.getSkyWalkingDynamicField() != null) {
+ if (redisCommandEnhanceInfo.getSpan() != null) {
//set peer in last channel writer (delegate)
if (peer != null) {
- AbstractSpan span = (AbstractSpan)
enhancedCommand.getSkyWalkingDynamicField();
- span.setPeer(peer);
+ redisCommandEnhanceInfo.getSpan().setPeer(peer);
}
return;
}
@@ -81,7 +86,16 @@ public class RedisChannelWriterInterceptor implements
InstanceMethodsAroundInter
operationName = operationName + "BATCH_WRITE";
command = "BATCH_WRITE";
}
+
+ if (redisCommandEnhanceInfo.getSnapshot() != null) {
+ AbstractSpan localSpan =
ContextManager.createLocalSpan("RedisReactive/local");
+ localSpan.setComponent(ComponentsDefine.LETTUCE);
+ SpanLayer.asCache(localSpan);
+ ContextManager.continued(redisCommandEnhanceInfo.getSnapshot());
+ }
+
AbstractSpan span = ContextManager.createExitSpan(operationName, peer);
+
span.setComponent(ComponentsDefine.LETTUCE);
Tags.CACHE_TYPE.set(span, "Redis");
if (StringUtil.isNotEmpty(key)) {
@@ -92,7 +106,12 @@ public class RedisChannelWriterInterceptor implements
InstanceMethodsAroundInter
SpanLayer.asCache(span);
span.prepareForAsync();
ContextManager.stopSpan();
- enhancedCommand.setSkyWalkingDynamicField(span);
+
+ if (redisCommandEnhanceInfo.getSnapshot() != null) {
+ ContextManager.stopSpan();
+ }
+
+
enhancedCommand.setSkyWalkingDynamicField(redisCommandEnhanceInfo.setSpan(span));
}
private String getArgsKey(RedisCommand<?, ?, ?> redisCommand) {
@@ -124,7 +143,7 @@ public class RedisChannelWriterInterceptor implements
InstanceMethodsAroundInter
RedisCommand<?, ?, ?> redisCommand =
getSpanCarrierCommand(allArguments[0]);
if (redisCommand instanceof EnhancedInstance && ((EnhancedInstance)
redisCommand).getSkyWalkingDynamicField() != null) {
EnhancedInstance enhancedRedisCommand = (EnhancedInstance)
redisCommand;
- AbstractSpan abstractSpan = (AbstractSpan)
enhancedRedisCommand.getSkyWalkingDynamicField();
+ AbstractSpan abstractSpan = ((RedisCommandEnhanceInfo)
enhancedRedisCommand.getSkyWalkingDynamicField()).getSpan();
enhancedRedisCommand.setSkyWalkingDynamicField(null);
abstractSpan.log(t);
abstractSpan.asyncFinish();
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
index 7fb9f3c943..82f4d6e55d 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
@@ -37,7 +37,7 @@ public class RedisCommandCancelMethodInterceptor implements
InstanceMethodsAroun
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ((RedisCommandEnhanceInfo)
objInst.getSkyWalkingDynamicField()).getSpan();
span.errorOccurred();
span.tag(new StringTag(CANCEL_SIGNAL_TAG), COMMAND_CANCEL_VALUE);
span.asyncFinish();
@@ -49,7 +49,7 @@ public class RedisCommandCancelMethodInterceptor implements
InstanceMethodsAroun
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ((RedisCommandEnhanceInfo)
objInst.getSkyWalkingDynamicField()).getSpan();
span.log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java
index bdde0712df..022c2622ee 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteExceptionallyMethodInterceptor.java
@@ -35,7 +35,7 @@ public class
RedisCommandCompleteExceptionallyMethodInterceptor implements Insta
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
if (objInst.getSkyWalkingDynamicField() != null) {
Throwable t = (Throwable) allArguments[0];
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ((RedisCommandEnhanceInfo)
objInst.getSkyWalkingDynamicField()).getSpan();
span.log(t);
span.asyncFinish();
objInst.setSkyWalkingDynamicField(null);
@@ -46,7 +46,7 @@ public class
RedisCommandCompleteExceptionallyMethodInterceptor implements Insta
@Override
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ((RedisCommandEnhanceInfo)
objInst.getSkyWalkingDynamicField()).getSpan();
span.log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java
index d2ede33ba7..725f2742bd 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCompleteMethodInterceptor.java
@@ -34,7 +34,7 @@ public class RedisCommandCompleteMethodInterceptor implements
InstanceMethodsAro
@Override
public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ((RedisCommandEnhanceInfo)
objInst.getSkyWalkingDynamicField()).getSpan();
span.asyncFinish();
objInst.setSkyWalkingDynamicField(null);
}
@@ -45,7 +45,7 @@ public class RedisCommandCompleteMethodInterceptor implements
InstanceMethodsAro
public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments,
Class<?>[] argumentsTypes, Throwable t) {
if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
+ AbstractSpan span = ((RedisCommandEnhanceInfo)
objInst.getSkyWalkingDynamicField()).getSpan();
span.log(t);
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.java
new file mode 100644
index 0000000000..942d5e18f4
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandEnhanceInfo.java
@@ -0,0 +1,59 @@
+/*
+ * 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.lettuce.common;
+
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+
+/**
+ * RedisCommandEnhanceInfo holds SkyWalking tracing data for Lettuce commands
+ * executed in different asynchronous models.
+ *
+ * <p>The {@link AbstractSpan} is used for non-reactive (blocking) commands
+ * that are executed asynchronously, where the span needs to be created
+ * at command submission time and finished when the command completes.</p>
+ *
+ * <p>The {@link ContextSnapshot} is used for reactive commands, where the
+ * tracing context is captured from Reactor {@code Context} and later
+ * continued at subscription or execution time to bridge reactive
+ * boundaries.</p>
+ */
+class RedisCommandEnhanceInfo {
+
+ private AbstractSpan span;
+ private ContextSnapshot snapshot;
+
+ public AbstractSpan getSpan() {
+ return span;
+ }
+
+ public RedisCommandEnhanceInfo setSpan(AbstractSpan span) {
+ this.span = span;
+ return this;
+ }
+
+ public ContextSnapshot getSnapshot() {
+ return snapshot;
+ }
+
+ public RedisCommandEnhanceInfo setSnapshot(ContextSnapshot snapshot) {
+ this.snapshot = snapshot;
+ return this;
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java
new file mode 100644
index 0000000000..7c79ebde93
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionConstructorInterceptor.java
@@ -0,0 +1,39 @@
+/*
+ * 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.lettuce.common;
+
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * Interceptor for RedisSubscription constructor.
+ * <p>
+ * This interceptor captures the {@link io.lettuce.core.protocol.RedisCommand}
instance
+ * at subscription construction time and stores it into SkyWalking dynamic
field.
+ * </p>
+ */
+public class RedisSubscriptionConstructorInterceptor implements
InstanceConstructorInterceptor {
+
+ @Override
+ public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+ // allArguments[1] is the RedisCommand passed to the RedisSubscription
constructor
+ objInst.setSkyWalkingDynamicField(allArguments[1]);
+ }
+
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java
similarity index 53%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
copy to
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java
index 7fb9f3c943..0ea108a247 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisCommandCancelMethodInterceptor.java
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java
@@ -18,39 +18,44 @@
package org.apache.skywalking.apm.plugin.lettuce.common;
-import org.apache.skywalking.apm.agent.core.context.tag.StringTag;
-import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.ContextSnapshot;
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.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.InstanceMethodsAroundInterceptorV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.v2.MethodInvocationContext;
+import reactor.core.CoreSubscriber;
import java.lang.reflect.Method;
-public class RedisCommandCancelMethodInterceptor implements
InstanceMethodsAroundInterceptor {
- private static final String CANCEL_SIGNAL_TAG = "signalType";
- private static final String COMMAND_CANCEL_VALUE = "cancel";
+/**
+ * Interceptor for {@code
RedisPublisher.RedisSubscription#subscribe(Subscriber)} method.
+ *
+ * <p>
+ * This interceptor works together with the constructor interceptor of
+ * {@code RedisSubscription}:
+ * </p>
+ */
+public class RedisSubscriptionSubscribeMethodInterceptor implements
InstanceMethodsAroundInterceptorV2 {
@Override
- public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) {
+ public void beforeMethod(EnhancedInstance objInst, Method method, Object[]
allArguments, Class<?>[] argumentsTypes, MethodInvocationContext context) {
+ if (allArguments[0] instanceof CoreSubscriber) {
+ CoreSubscriber<?> subscriber = (CoreSubscriber<?>) allArguments[0];
+ // get ContextSnapshot from reactor context, the snapshot is set
to reactor context by any other plugin
+ // such as DispatcherHandlerHandleMethodInterceptor in
spring-webflux-5.x-plugin
+ Object skywalkingContextSnapshot =
subscriber.currentContext().getOrDefault("SKYWALKING_CONTEXT_SNAPSHOT", null);
+ if (skywalkingContextSnapshot != null) {
+ ((EnhancedInstance)
objInst.getSkyWalkingDynamicField()).setSkyWalkingDynamicField(new
RedisCommandEnhanceInfo()
+ .setSnapshot((ContextSnapshot)
skywalkingContextSnapshot));
+ }
+ }
}
@Override
- public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret) {
- if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
- span.errorOccurred();
- span.tag(new StringTag(CANCEL_SIGNAL_TAG), COMMAND_CANCEL_VALUE);
- span.asyncFinish();
- objInst.setSkyWalkingDynamicField(null);
- }
+ public Object afterMethod(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Object ret,
MethodInvocationContext context) {
return ret;
}
@Override
- public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
- if (objInst.getSkyWalkingDynamicField() != null) {
- AbstractSpan span = (AbstractSpan)
objInst.getSkyWalkingDynamicField();
- span.log(t);
- }
+ public void handleMethodException(EnhancedInstance objInst, Method method,
Object[] allArguments, Class<?>[] argumentsTypes, Throwable t,
MethodInvocationContext context) {
}
}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java
new file mode 100644
index 0000000000..7e7ccc7632
--- /dev/null
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/define/RedisSubscriptionInstrumentation.java
@@ -0,0 +1,86 @@
+/*
+ * 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.lettuce.common.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.enhance.v2.ClassInstanceMethodsEnhancePluginDefineV2;
+import
org.apache.skywalking.apm.agent.core.plugin.interceptor.v2.InstanceMethodsInterceptV2Point;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
+import static
org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ *
+ */
+public class RedisSubscriptionInstrumentation extends
ClassInstanceMethodsEnhancePluginDefineV2 {
+
+ private static final String ENHANCE_CLASS =
"io.lettuce.core.RedisPublisher$RedisSubscription";
+
+ private static final String
REDIS_SUBSCRIPTION_SUBSCRIBE_METHOD_INTERCEPTOR =
"org.apache.skywalking.apm.plugin.lettuce.common.RedisSubscriptionSubscribeMethodInterceptor";
+ private static final String REDIS_SUBSCRIPTION_CONST_METHOD_INTERCEPTOR =
"org.apache.skywalking.apm.plugin.lettuce.common.RedisSubscriptionConstructorInterceptor";
+
+ @Override
+ public InstanceMethodsInterceptV2Point[]
getInstanceMethodsInterceptV2Points() {
+ return new InstanceMethodsInterceptV2Point[]{
+ new InstanceMethodsInterceptV2Point() {
+ @Override
+ public ElementMatcher<MethodDescription>
getMethodsMatcher() {
+ return named("subscribe");
+ }
+
+ @Override
+ public String getMethodsInterceptorV2() {
+ return REDIS_SUBSCRIPTION_SUBSCRIBE_METHOD_INTERCEPTOR;
+ }
+
+ @Override
+ public boolean isOverrideArgs() {
+ return false;
+ }
+ }
+ };
+ }
+
+ @Override
+ public ClassMatch enhanceClass() {
+ return byName(ENHANCE_CLASS);
+ }
+
+ @Override
+ public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+ return new ConstructorInterceptPoint[] {
+ new ConstructorInterceptPoint() {
+ @Override
+ public ElementMatcher<MethodDescription>
getConstructorMatcher() {
+ return any().and(takesArgument(1,
named("io.lettuce.core.protocol.RedisCommand")));
+ }
+
+ @Override
+ public String getConstructorInterceptor() {
+ return REDIS_SUBSCRIPTION_CONST_METHOD_INTERCEPTOR;
+ }
+ }
+ };
+ }
+}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def
index e0521938a7..e17d02461c 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def
+++
b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/resources/skywalking-plugin.def
@@ -15,4 +15,5 @@
# limitations under the License.
lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.DefaultEndpointInstrumentation
-lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisCommandInstrumentation
\ No newline at end of file
+lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisCommandInstrumentation
+lettuce-common=org.apache.skywalking.apm.plugin.lettuce.common.define.RedisSubscriptionInstrumentation
\ No newline at end of file
diff --git
a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
b/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
index 2a938caea9..dbeb6b6138 100644
--- a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
@@ -34,6 +34,60 @@ segmentItems:
- {key: url, value:
'http://localhost:8080/lettuce-6.5.x-scenario/case/healthCheck'}
- {key: http.method, value: HEAD}
- {key: http.status_code, value: '200'}
+ - segmentId: not null
+ spans:
+ - operationName: Lettuce/SET
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Exit
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key0 }
+ - { key: cache.cmd, value: SET }
+ - { key: cache.op, value: write }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint:
GET:/lettuce-6.5.x-scenario/case/lettuce-case, networkAddress: '', refType:
CrossThread,
+ parentSpanId: 5, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
+ - operationName: Lettuce/SET
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Exit
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key1 }
+ - { key: cache.cmd, value: SET }
+ - { key: cache.op, value: write }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint:
GET:/lettuce-6.5.x-scenario/case/lettuce-case, networkAddress: '', refType:
CrossThread,
+ parentSpanId: 6, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
- segmentId: not null
spans:
- operationName: Lettuce/GET
@@ -84,6 +138,57 @@ segmentItems:
- { key: cache.key, value: key1 }
- { key: cache.cmd, value: SET }
- { key: cache.op, value: write }
+ - operationName: Lettuce/Reactive/createMono
+ parentSpanId: 0
+ spanId: 4
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Local
+ skipAnalysis: false
+ - operationName: Lettuce/Reactive/createMono
+ parentSpanId: 0
+ spanId: 5
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Local
+ skipAnalysis: false
+ - operationName: Lettuce/Reactive/createMono
+ parentSpanId: 0
+ spanId: 6
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Local
+ skipAnalysis: false
+ - operationName: Lettuce/GET
+ parentSpanId: 7
+ spanId: 8
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Exit
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key }
+ - { key: cache.cmd, value: GET }
+ - { key: cache.op, value: read }
+ - operationName: RedisReactive/local
+ parentSpanId: 0
+ spanId: 7
+ isError: false
+ spanType: Local
- operationName: GET:/lettuce-6.5.x-scenario/case/lettuce-case
parentSpanId: -1
spanId: 0
diff --git
a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
index c2f391b07c..d2cc201025 100644
---
a/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
+++
b/test/plugin/scenarios/lettuce-6.5.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
@@ -23,6 +23,7 @@ import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
+import io.lettuce.core.api.reactive.RedisReactiveCommands;
import io.lettuce.core.api.sync.RedisCommands;
import java.util.ArrayList;
import java.util.List;
@@ -32,6 +33,8 @@ import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
@Controller
@RequestMapping("/case")
@@ -58,8 +61,21 @@ public class LettuceController {
asyncCommands.flushCommands();
LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new
RedisFuture[futures.size()]));
+ StatefulRedisConnection<String, String> connection2 =
redisClient.connect();
+ RedisReactiveCommands<String, String> reactiveCommands =
connection2.reactive();
+
+ Mono<String> result = reactiveCommands.get("key")
+ .then(Flux.concat(
+ reactiveCommands.set("key0", "value0"),
+ reactiveCommands.set("key1", "value1")
+ ).then())
+ .thenReturn("Success");
+
+ result.block();
+
connection0.close();
connection1.close();
+ connection2.close();
redisClient.shutdown();
return "Success";
}
diff --git a/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml
b/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml
index 43db792872..884191cfe3 100644
--- a/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/lettuce-scenario/config/expectedData.yaml
@@ -34,6 +34,60 @@ segmentItems:
- {key: url, value:
'http://localhost:8080/lettuce-scenario/case/healthCheck'}
- {key: http.method, value: HEAD}
- {key: http.status_code, value: '200'}
+ - segmentId: not null
+ spans:
+ - operationName: Lettuce/SET
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Exit
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key0 }
+ - { key: cache.cmd, value: SET }
+ - { key: cache.op, value: write }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: GET:/lettuce-scenario/case/lettuce-case,
networkAddress: '', refType: CrossThread,
+ parentSpanId: 5, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
+ - operationName: Lettuce/SET
+ parentSpanId: 0
+ spanId: 1
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Exit
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key1 }
+ - { key: cache.cmd, value: SET }
+ - { key: cache.op, value: write }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: GET:/lettuce-scenario/case/lettuce-case,
networkAddress: '', refType: CrossThread,
+ parentSpanId: 6, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
- segmentId: not null
spans:
- operationName: Lettuce/GET
@@ -84,6 +138,57 @@ segmentItems:
- { key: cache.key, value: key1 }
- { key: cache.cmd, value: SET }
- { key: cache.op, value: write }
+ - operationName: Lettuce/Reactive/createMono
+ parentSpanId: 0
+ spanId: 4
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Local
+ skipAnalysis: false
+ - operationName: Lettuce/Reactive/createMono
+ parentSpanId: 0
+ spanId: 5
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Local
+ skipAnalysis: false
+ - operationName: Lettuce/Reactive/createMono
+ parentSpanId: 0
+ spanId: 6
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Local
+ skipAnalysis: false
+ - operationName: Lettuce/GET
+ parentSpanId: 7
+ spanId: 8
+ spanLayer: Cache
+ startTime: not null
+ endTime: not null
+ componentId: 57
+ isError: false
+ spanType: Exit
+ peer: not null
+ skipAnalysis: false
+ tags:
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key }
+ - { key: cache.cmd, value: GET }
+ - { key: cache.op, value: read }
+ - operationName: RedisReactive/local
+ parentSpanId: 0
+ spanId: 7
+ isError: false
+ spanType: Local
- operationName: GET:/lettuce-scenario/case/lettuce-case
parentSpanId: -1
spanId: 0
diff --git
a/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
b/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
index c2f391b07c..d2cc201025 100644
---
a/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
+++
b/test/plugin/scenarios/lettuce-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceController.java
@@ -23,6 +23,7 @@ import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
+import io.lettuce.core.api.reactive.RedisReactiveCommands;
import io.lettuce.core.api.sync.RedisCommands;
import java.util.ArrayList;
import java.util.List;
@@ -32,6 +33,8 @@ import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
@Controller
@RequestMapping("/case")
@@ -58,8 +61,21 @@ public class LettuceController {
asyncCommands.flushCommands();
LettuceFutures.awaitAll(5, TimeUnit.SECONDS, futures.toArray(new
RedisFuture[futures.size()]));
+ StatefulRedisConnection<String, String> connection2 =
redisClient.connect();
+ RedisReactiveCommands<String, String> reactiveCommands =
connection2.reactive();
+
+ Mono<String> result = reactiveCommands.get("key")
+ .then(Flux.concat(
+ reactiveCommands.set("key0", "value0"),
+ reactiveCommands.set("key1", "value1")
+ ).then())
+ .thenReturn("Success");
+
+ result.block();
+
connection0.close();
connection1.close();
+ connection2.close();
redisClient.shutdown();
return "Success";
}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh
similarity index 79%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
copy to test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh
index a503891244..d719f14162 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+#
# 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
@@ -14,4 +16,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -Dredis.host=${REDIS_SERVERS} -jar
-Dskywalking.plugin.lettuce.trace_redis_parameters=true ${agent_opts}
${home}/../libs/lettuce-webflux-5x-scenario.jar &
\ No newline at end of file
diff --git
a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml
similarity index 63%
copy from test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
copy to
test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml
index 2a938caea9..cdc04a6242 100644
--- a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml
@@ -14,24 +14,24 @@
# See the License for the specific language governing permissions and
# limitations under the License.
segmentItems:
- - serviceName: lettuce-6.5.x-scenario
+ - serviceName: lettuce-webflux-5x-scenario
segmentSize: nq 0
segments:
- segmentId: not null
spans:
- - operationName: HEAD:/lettuce-6.5.x-scenario/case/healthCheck
+ - operationName: /case/healthCheck
parentSpanId: -1
spanId: 0
spanLayer: Http
startTime: not null
endTime: not null
- componentId: 1
+ componentId: 67
isError: false
spanType: Entry
peer: ''
skipAnalysis: false
tags:
- - {key: url, value:
'http://localhost:8080/lettuce-6.5.x-scenario/case/healthCheck'}
+ - {key: url, value: 'http://localhost:8080/case/healthCheck'}
- {key: http.method, value: HEAD}
- {key: http.status_code, value: '200'}
- segmentId: not null
@@ -52,9 +52,20 @@ segmentItems:
- {key: cache.key, value: key}
- {key: cache.cmd, value: GET}
- {key: cache.op, value: read}
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: /case/lettuce-case, networkAddress: '',
refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
- operationName: Lettuce/SET
parentSpanId: 0
- spanId: 2
+ spanId: 1
spanLayer: Cache
startTime: not null
endTime: not null
@@ -68,9 +79,20 @@ segmentItems:
- { key: cache.key, value: key0 }
- { key: cache.cmd, value: SET }
- { key: cache.op, value: write }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: /case/lettuce-case, networkAddress: '',
refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
- operationName: Lettuce/SET
parentSpanId: 0
- spanId: 3
+ spanId: 1
spanLayer: Cache
startTime: not null
endTime: not null
@@ -84,18 +106,29 @@ segmentItems:
- { key: cache.key, value: key1 }
- { key: cache.cmd, value: SET }
- { key: cache.op, value: write }
- - operationName: GET:/lettuce-6.5.x-scenario/case/lettuce-case
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: /case/lettuce-case, networkAddress: '',
refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
+ - operationName: /case/lettuce-case
parentSpanId: -1
spanId: 0
spanLayer: Http
startTime: not null
endTime: not null
- componentId: 1
+ componentId: 67
isError: false
spanType: Entry
peer: ''
skipAnalysis: false
tags:
- - {key: url, value:
'http://localhost:8080/lettuce-6.5.x-scenario/case/lettuce-case'}
+ - {key: url, value: 'http://localhost:8080/case/lettuce-case'}
- {key: http.method, value: GET}
- {key: http.status_code, value: '200'}
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml
similarity index 67%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
copy to test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml
index a503891244..d016d55400 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml
@@ -14,4 +14,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+type: jvm
+entryService: http://localhost:8080/case/lettuce-case
+healthCheck: http://localhost:8080/case/healthCheck
+startScript: ./bin/startup.sh
+withPlugins: apm-spring-webflux-5.x-*.jar
+runningMode: with_optional
+environment:
+ - REDIS_SERVERS=redis-server:6379
+depends_on:
+ - redis-server
+dependencies:
+ redis-server:
+ image: redis:3.2.9-alpine
+ hostname: redis-server
diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml
new file mode 100644
index 0000000000..bf393539a2
--- /dev/null
+++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/pom.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ ~
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>lettuce-webflux-5x-scenario</artifactId>
+ <version>5.0.0</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <compiler.version>1.8</compiler.version>
+ <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
+ <test.framework.version>5.1.8.RELEASE</test.framework.version>
+ <docker.image.version>${test.framework.version}</docker.image.version>
+ <spring.boot.version>2.1.6.RELEASE</spring.boot.version>
+ </properties>
+
+ <name>skywalking-lettuce-webflux-5x-scenario</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.lettuce</groupId>
+ <artifactId>lettuce-core</artifactId>
+ <version>${test.framework.version}</version>
+ </dependency>
+ <!-- Spring Boot-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ <version>${spring.boot.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>lettuce-webflux-5x-scenario</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring.boot.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${compiler.version}</source>
+ <target>${compiler.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assemble</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+
<descriptor>src/main/assembly/assembly.xml</descriptor>
+ </descriptors>
+ <outputDirectory>./target/</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git
a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000000..ffc45011aa
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ ~
+ -->
+<assembly
+
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <fileSets>
+ <fileSet>
+ <directory>./bin</directory>
+ <fileMode>0775</fileMode>
+ </fileSet>
+ </fileSets>
+
+ <files>
+ <file>
+
<source>${project.build.directory}/lettuce-webflux-5x-scenario.jar</source>
+ <outputDirectory>./libs</outputDirectory>
+ <fileMode>0775</fileMode>
+ </file>
+ </files>
+</assembly>
diff --git
a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java
new file mode 100644
index 0000000000..dae1948397
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java
@@ -0,0 +1,34 @@
+/*
+ * 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.lettuce;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ try {
+ SpringApplication.run(Application.class, args);
+ } catch (Exception e) {
+ // Never do this
+ }
+ }
+}
diff --git
a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java
new file mode 100644
index 0000000000..0898d08338
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java
@@ -0,0 +1,37 @@
+/*
+ * 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.lettuce;
+
+import io.lettuce.core.RedisClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ *
+ */
+@Configuration
+public class RedisClientConfig {
+
+ @Bean(destroyMethod = "shutdown")
+ public RedisClient redisClient(@Value("${redis.servers:127.0.0.1:6379}")
String address) {
+
+ return RedisClient.create("redis://" + address);
+ }
+}
diff --git
a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java
new file mode 100644
index 0000000000..2664bd2713
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java
@@ -0,0 +1,68 @@
+/*
+ * 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.lettuce.controller;
+
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.api.reactive.RedisReactiveCommands;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.Resource;
+
+@RestController
+@RequestMapping("/case")
+@PropertySource("classpath:application.properties")
+public class LettuceReactiveController {
+
+ @Value("${redis.servers:127.0.0.1:6379}")
+ private String address;
+
+ @Resource
+ private RedisClient redisClient;
+
+ @GetMapping("/lettuce-case")
+ public Mono<String> lettuceCase() {
+
+ return Mono.usingWhen(
+ Mono.fromCallable(() -> redisClient.connect()),
+ connection -> {
+ RedisReactiveCommands<String, String> cmd =
connection.reactive();
+ return cmd.get("key")
+ .then(Flux.concat(
+ cmd.set("key0", "value0"),
+ cmd.set("key1", "value1")
+ ).then())
+ .thenReturn("Success");
+ },
+ connection -> Mono.fromFuture(connection.closeAsync()),
+ connection -> Mono.fromFuture(connection.closeAsync()),
+ connection -> Mono.fromFuture(connection.closeAsync())
+ );
+ }
+
+ @GetMapping("/healthCheck")
+ public Mono<String> healthCheck() {
+ return Mono.just("healthCheck");
+ }
+}
diff --git
a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties
new file mode 100644
index 0000000000..d3b193de12
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+#
+server.port=8080
diff --git
a/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000..9849ed5a8a
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/src/main/resources/log4j2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ ~
+ -->
+<Configuration status="WARN">
+ <Appenders>
+ <Console name="Console" target="SYSTEM_ERR">
+ <PatternLayout charset="UTF-8" pattern="[%d{yyyy-MM-dd
HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
+ </Console>
+ </Appenders>
+ <Loggers>
+ <Root level="WARN">
+ <AppenderRef ref="Console"/>
+ </Root>
+ </Loggers>
+</Configuration>
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list
similarity index 88%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
copy to test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list
index a503891244..a7e848bbbf 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list
@@ -14,4 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+5.1.8.RELEASE
+5.2.1.RELEASE
+6.1.4.RELEASE
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh
similarity index 79%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
copy to test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh
index a503891244..686b12f52a 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh
@@ -1,3 +1,5 @@
+#!/bin/bash
+#
# 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
@@ -14,4 +16,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+home="$(cd "$(dirname $0)"; pwd)"
+
+java -Dredis.host=${REDIS_SERVERS} -jar
-Dskywalking.plugin.lettuce.trace_redis_parameters=true ${agent_opts}
${home}/../libs/lettuce-webflux-6x-scenario.jar &
\ No newline at end of file
diff --git
a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml
similarity index 55%
copy from test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
copy to
test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml
index 2a938caea9..e5857aa054 100644
--- a/test/plugin/scenarios/lettuce-6.5.x-scenario/config/expectedData.yaml
+++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml
@@ -14,26 +14,26 @@
# See the License for the specific language governing permissions and
# limitations under the License.
segmentItems:
- - serviceName: lettuce-6.5.x-scenario
+ - serviceName: lettuce-webflux-6x-scenario
segmentSize: nq 0
segments:
- segmentId: not null
spans:
- - operationName: HEAD:/lettuce-6.5.x-scenario/case/healthCheck
+ - operationName: /case/healthCheck
parentSpanId: -1
spanId: 0
spanLayer: Http
startTime: not null
endTime: not null
- componentId: 1
+ componentId: 67
isError: false
spanType: Entry
peer: ''
skipAnalysis: false
tags:
- - {key: url, value:
'http://localhost:8080/lettuce-6.5.x-scenario/case/healthCheck'}
- - {key: http.method, value: HEAD}
- - {key: http.status_code, value: '200'}
+ - { key: url, value: 'http://localhost:8080/case/healthCheck' }
+ - { key: http.method, value: HEAD }
+ - { key: http.status_code, value: '200' }
- segmentId: not null
spans:
- operationName: Lettuce/GET
@@ -48,13 +48,24 @@ segmentItems:
peer: not null
skipAnalysis: false
tags:
- - {key: cache.type, value: Redis}
- - {key: cache.key, value: key}
- - {key: cache.cmd, value: GET}
- - {key: cache.op, value: read}
+ - { key: cache.type, value: Redis }
+ - { key: cache.key, value: key }
+ - { key: cache.cmd, value: GET }
+ - { key: cache.op, value: read }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: /case/lettuce-case, networkAddress: '',
refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
- operationName: Lettuce/SET
parentSpanId: 0
- spanId: 2
+ spanId: 1
spanLayer: Cache
startTime: not null
endTime: not null
@@ -68,9 +79,20 @@ segmentItems:
- { key: cache.key, value: key0 }
- { key: cache.cmd, value: SET }
- { key: cache.op, value: write }
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: /case/lettuce-case, networkAddress: '',
refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
- operationName: Lettuce/SET
parentSpanId: 0
- spanId: 3
+ spanId: 1
spanLayer: Cache
startTime: not null
endTime: not null
@@ -84,18 +106,30 @@ segmentItems:
- { key: cache.key, value: key1 }
- { key: cache.cmd, value: SET }
- { key: cache.op, value: write }
- - operationName: GET:/lettuce-6.5.x-scenario/case/lettuce-case
+ - operationName: RedisReactive/local
+ parentSpanId: -1
+ spanId: 0
+ isError: false
+ spanType: Local
+ refs:
+ - { parentEndpoint: /case/lettuce-case, networkAddress: '',
refType: CrossThread,
+ parentSpanId: 0, parentTraceSegmentId: not null,
parentServiceInstance: not
+ null, parentService: not null, traceId: not null }
+ - segmentId: not null
+ spans:
+ - operationName: /case/lettuce-case
parentSpanId: -1
spanId: 0
spanLayer: Http
startTime: not null
endTime: not null
- componentId: 1
+ componentId: 67
isError: false
spanType: Entry
peer: ''
skipAnalysis: false
tags:
- - {key: url, value:
'http://localhost:8080/lettuce-6.5.x-scenario/case/lettuce-case'}
- - {key: http.method, value: GET}
- - {key: http.status_code, value: '200'}
+ - { key: url, value: 'http://localhost:8080/case/lettuce-case' }
+ - { key: http.method, value: GET }
+ - { key: http.status_code, value: '200' }
+
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml
similarity index 67%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
copy to test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml
index a503891244..a3eecec7bb 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml
@@ -14,4 +14,17 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+type: jvm
+entryService: http://localhost:8080/case/lettuce-case
+healthCheck: http://localhost:8080/case/healthCheck
+startScript: ./bin/startup.sh
+withPlugins: apm-spring-webflux-6.x-*.jar
+runningMode: with_optional
+environment:
+ - REDIS_SERVERS=redis-server:6379
+depends_on:
+ - redis-server
+dependencies:
+ redis-server:
+ image: redis:3.2.9-alpine
+ hostname: redis-server
diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml
new file mode 100644
index 0000000000..2e05615440
--- /dev/null
+++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ ~
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>lettuce-webflux-6x-scenario</artifactId>
+ <version>5.0.0</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <compiler.version>17</compiler.version>
+ <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
+ <test.framework.version>6.4.2.RELEASE</test.framework.version>
+ <docker.image.version>${test.framework.version}</docker.image.version>
+ <spring.boot.version>3.0.13</spring.boot.version>
+ </properties>
+
+ <name>skywalking-lettuce-webflux-6x-scenario</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring.boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.lettuce</groupId>
+ <artifactId>lettuce-core</artifactId>
+ <version>${test.framework.version}</version>
+ </dependency>
+ <!-- Spring Boot-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ <version>${spring.boot.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <finalName>lettuce-webflux-6x-scenario</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring.boot.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>${maven-compiler-plugin.version}</version>
+ <configuration>
+ <source>${compiler.version}</source>
+ <target>${compiler.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>assemble</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+
<descriptor>src/main/assembly/assembly.xml</descriptor>
+ </descriptors>
+ <outputDirectory>./target/</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git
a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml
new file mode 100644
index 0000000000..87c9882cab
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/assembly/assembly.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ ~
+ -->
+<assembly
+
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <fileSets>
+ <fileSet>
+ <directory>./bin</directory>
+ <fileMode>0775</fileMode>
+ </fileSet>
+ </fileSets>
+
+ <files>
+ <file>
+
<source>${project.build.directory}/lettuce-webflux-6x-scenario.jar</source>
+ <outputDirectory>./libs</outputDirectory>
+ <fileMode>0775</fileMode>
+ </file>
+ </files>
+</assembly>
diff --git
a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java
new file mode 100644
index 0000000000..f96b624013
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/Application.java
@@ -0,0 +1,30 @@
+/*
+ * 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.lettuce;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+}
diff --git
a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java
new file mode 100644
index 0000000000..0898d08338
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/RedisClientConfig.java
@@ -0,0 +1,37 @@
+/*
+ * 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.lettuce;
+
+import io.lettuce.core.RedisClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ *
+ */
+@Configuration
+public class RedisClientConfig {
+
+ @Bean(destroyMethod = "shutdown")
+ public RedisClient redisClient(@Value("${redis.servers:127.0.0.1:6379}")
String address) {
+
+ return RedisClient.create("redis://" + address);
+ }
+}
diff --git
a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java
new file mode 100644
index 0000000000..697369fcf8
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/java/org/apache/skywalking/apm/testcase/lettuce/controller/LettuceReactiveController.java
@@ -0,0 +1,63 @@
+/*
+ * 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.lettuce.controller;
+
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.api.reactive.RedisReactiveCommands;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@RestController
+@RequestMapping("/case")
+public class LettuceReactiveController {
+
+ @Value("${redis.servers:127.0.0.1:6379}")
+ private String address;
+
+ @Autowired
+ private RedisClient redisClient;
+
+ @GetMapping("/lettuce-case")
+ public Mono<String> lettuceCase() {
+
+ return Mono.usingWhen(
+ Mono.fromCallable(() -> redisClient.connect()),
+ connection -> {
+ RedisReactiveCommands<String, String> cmd =
connection.reactive();
+ return cmd.get("key")
+ .then(Flux.concat(
+ cmd.set("key0", "value0"),
+ cmd.set("key1", "value1")
+ ).then())
+ .thenReturn("Success");
+ },
+ connection -> Mono.fromFuture(connection.closeAsync())
+ );
+ }
+
+ @GetMapping("/healthCheck")
+ public Mono<String> healthCheck() {
+ return Mono.just("healthCheck");
+ }
+}
diff --git
a/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties
new file mode 100644
index 0000000000..afdb52cef7
--- /dev/null
+++
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+#
+server.port=8080
\ No newline at end of file
diff --git
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
b/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list
similarity index 88%
copy from
apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
copy to test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list
index a503891244..2cba7f3294 100644
---
a/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-6.5.x-plugin/src/main/resources/skywalking-plugin.def
+++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list
@@ -14,4 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-lettuce-6.5.x=org.apache.skywalking.apm.plugin.lettuce.v65.define.RedisChannelWriterInstrumentationV65
\ No newline at end of file
+6.4.2.RELEASE
+6.5.5.RELEASE
+6.6.0.RELEASE
+6.7.1.RELEASE
\ No newline at end of file