diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 418da87f35..d1c10f8734 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -65,6 +65,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 2c012792fc..4f28cfed8c 100644 --- a/.github/workflows/plugins-test.1.yaml +++ b/.github/workflows/plugins-test.1.yaml @@ -73,6 +73,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 979502ce7a..9eaae86646 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,7 @@ Release Notes. * Add `eclipse-temurin:25-jre` as another base image. * Add JDK25 plugin tests for Spring 6. * Ignore classes starting with "sun.nio.cs" in bytebuddy due to potential class loading deadlock. +* Added support for Lettuce reactive Redis commands. All issues and pull requests are [here](https://github.com/apache/skywalking/milestone/242?closed=1) 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..5dde7dfcb3 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 void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr } 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; } @@ -82,6 +87,15 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr command = "BATCH_WRITE"; } AbstractSpan span = ContextManager.createExitSpan(operationName, peer); + + if (redisCommandEnhanceInfo.getSnapshot() != null) { + if (!ContextManager.isActive()) { + AbstractSpan localSpan = ContextManager.createLocalSpan("RedisReactive/local"); + localSpan.setComponent(ComponentsDefine.LETTUCE); + } + ContextManager.continued(redisCommandEnhanceInfo.getSnapshot()); + } + span.setComponent(ComponentsDefine.LETTUCE); Tags.CACHE_TYPE.set(span, "Redis"); if (StringUtil.isNotEmpty(key)) { @@ -92,7 +106,7 @@ public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr SpanLayer.asCache(span); span.prepareForAsync(); ContextManager.stopSpan(); - enhancedCommand.setSkyWalkingDynamicField(span); + enhancedCommand.setSkyWalkingDynamicField(redisCommandEnhanceInfo.setSpan(span)); } private String getArgsKey(RedisCommand redisCommand) { @@ -124,7 +138,7 @@ public void handleMethodException(EnhancedInstance objInst, Method method, Objec 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 void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @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 Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA @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 void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr 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 Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA @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 void beforeMethod(EnhancedInstance objInst, Method method, Object[] allAr @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 Object afterMethod(EnhancedInstance objInst, Method method, Object[] allA 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..45d09599cd --- /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. + * + *

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.

+ * + *

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.

+ */ +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. + *

+ * This interceptor captures the {@link io.lettuce.core.protocol.RedisCommand} instance + * at subscription construction time and stores it into SkyWalking dynamic field. + *

+ */ +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/RedisSubscriptionSubscribeMethodInterceptor.java b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java new file mode 100644 index 0000000000..0ea108a247 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/lettuce-plugins/lettuce-common/src/main/java/org/apache/skywalking/apm/plugin/lettuce/common/RedisSubscriptionSubscribeMethodInterceptor.java @@ -0,0 +1,61 @@ +/* + * 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.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 reactor.core.CoreSubscriber; + +import java.lang.reflect.Method; + +/** + * Interceptor for {@code RedisPublisher.RedisSubscription#subscribe(Subscriber)} method. + * + *

+ * This interceptor works together with the constructor interceptor of + * {@code RedisSubscription}: + *

+ */ +public class RedisSubscriptionSubscribeMethodInterceptor implements InstanceMethodsAroundInterceptorV2 { + + @Override + 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, MethodInvocationContext context) { + return ret; + } + + @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-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 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 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-webflux-5x-scenario/bin/startup.sh b/test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh new file mode 100644 index 0000000000..d719f14162 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/bin/startup.sh @@ -0,0 +1,21 @@ +#!/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 +# 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. + +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-webflux-5x-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..3e9b59d5de --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/config/expectedData.yaml @@ -0,0 +1,119 @@ +# 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. +segmentItems: + - serviceName: lettuce-webflux-5x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /case/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {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 + parentSpanId: -1 + spanId: 0 + 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} + 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: -1 + spanId: 0 + 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 } + 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: -1 + spanId: 0 + 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 } + 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: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/case/lettuce-case'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml b/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml new file mode 100644 index 0000000000..d016d55400 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/configuration.yml @@ -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. + +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 @@ + + + + 4.0.0 + + org.apache.skywalking + lettuce-webflux-5x-scenario + 5.0.0 + + + UTF-8 + 1.8 + 3.8.1 + 5.1.8.RELEASE + ${test.framework.version} + 2.1.6.RELEASE + + + skywalking-lettuce-webflux-5x-scenario + + + + io.lettuce + lettuce-core + ${test.framework.version} + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring.boot.version} + + + + + lettuce-webflux-5x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + \ 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 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/lettuce-webflux-5x-scenario.jar + ./libs + 0775 + + + 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 lettuceCase() { + + return Mono.usingWhen( + Mono.fromCallable(() -> redisClient.connect()), + connection -> { + RedisReactiveCommands 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 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 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list b/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list new file mode 100644 index 0000000000..a7e848bbbf --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-5x-scenario/support-version.list @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +5.1.8.RELEASE +5.2.1.RELEASE +6.1.4.RELEASE \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh b/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh new file mode 100644 index 0000000000..686b12f52a --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/bin/startup.sh @@ -0,0 +1,21 @@ +#!/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 +# 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. + +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-webflux-6x-scenario/config/expectedData.yaml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..5ccd79aa70 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/config/expectedData.yaml @@ -0,0 +1,119 @@ +# 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. +segmentItems: + - serviceName: lettuce-webflux-6x-scenario + segmentSize: nq 0 + segments: + - segmentId: not null + spans: + - operationName: /case/healthCheck + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: not null + endTime: not null + componentId: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {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 + parentSpanId: -1 + spanId: 0 + 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} + 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: -1 + spanId: 0 + 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 } + 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: -1 + spanId: 0 + 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 } + 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: 67 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/case/lettuce-case'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml new file mode 100644 index 0000000000..a3eecec7bb --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/configuration.yml @@ -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. + +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..5aa92d35b1 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/pom.xml @@ -0,0 +1,105 @@ + + + + 4.0.0 + + org.apache.skywalking + lettuce-webflux-6x-scenario + 5.0.0 + + + UTF-8 + 17 + 3.8.1 + 6.4.2.RELEASE + ${test.framework.version} + 3.0.0 + + + skywalking-lettuce-webflux-6x-scenario + + + + io.lettuce + lettuce-core + ${test.framework.version} + + + + org.springframework.boot + spring-boot-starter-webflux + ${spring.boot.version} + + + ch.qos.logback + logback-classic + + + + + + + + lettuce-webflux-6x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring.boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${compiler.version} + ${compiler.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + \ 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 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/lettuce-webflux-6x-scenario.jar + ./libs + 0775 + + + 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..dae1948397 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-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-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..c10fb7d03f --- /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,65 @@ +/* + * 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.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; + +@RestController +@RequestMapping("/case") +@PropertySource("classpath:application.properties") +public class LettuceReactiveController { + + @Value("${redis.servers:127.0.0.1:6379}") + private String address; + + @Autowired + private RedisClient redisClient; + + @GetMapping("/lettuce-case") + public Mono lettuceCase() { + + return Mono.usingWhen( + Mono.fromCallable(() -> redisClient.connect()), + connection -> { + RedisReactiveCommands 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 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/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list b/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list new file mode 100644 index 0000000000..2cba7f3294 --- /dev/null +++ b/test/plugin/scenarios/lettuce-webflux-6x-scenario/support-version.list @@ -0,0 +1,20 @@ +# 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. + +6.4.2.RELEASE +6.5.5.RELEASE +6.6.0.RELEASE +6.7.1.RELEASE \ No newline at end of file