You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2019/01/26 05:09:08 UTC

[incubator-skywalking] branch master updated: Support lettuce plugin (#2152)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new a36394d  Support lettuce plugin (#2152)
a36394d is described below

commit a36394d9bc2d66de37a50a01ea7fb0edecd5db3e
Author: 于玉桔 <76...@qq.com>
AuthorDate: Sat Jan 26 13:09:03 2019 +0800

    Support lettuce plugin (#2152)
    
    * Support lettuce plugin
    
    * lettuce plugin bugfix
    
    * lettuce plugin fix license issue
    
    * lettuce plugin fix cluster and config issue
    
    * plugin lettuce compatible with low 5.0.x version
    
    * lettuce plugin support version accurately describes on Supported-list.md
    
    * plugin lettuce compatible with low 5.0.2 version
    
    * lettuce plugin fix wrong batch method intercept point
    
    * move lettuce to optional plugins
    
    * fix ci issue
    
    * fix ci issue
    
    * Modify the description file
    
    * Pom code optimization
    
    * Optimization operation name
    
    * Optimization operation name2
---
 .../network/trace/component/ComponentsDefine.java  |   5 +-
 .../optional-plugins/lettuce-5.x-plugin/pom.xml    |  46 +++++++++
 .../lettuce/v5/AsyncCommandMethodInterceptor.java  |  60 +++++++++++
 .../v5/ClientOptionsConstructorInterceptor.java    |  37 +++++++
 .../lettuce/v5/RedisChannelWriterInterceptor.java  |  89 ++++++++++++++++
 .../v5/RedisClientConstructorInterceptor.java      |  39 +++++++
 .../RedisClusterClientConstructorInterceptor.java  |  44 ++++++++
 .../apm/plugin/lettuce/v5/SWConsumer.java          |  56 +++++++++++
 .../v5/define/AsyncCommandInstrumentation.java     |  72 +++++++++++++
 .../v5/define/ClientOptionsInstrumentation.java    |  67 ++++++++++++
 .../define/RedisChannelWriterInstrumentation.java  |  87 ++++++++++++++++
 .../v5/define/RedisClientInstrumentation.java      |  67 ++++++++++++
 .../define/RedisClusterClientInstrumentation.java  |  67 ++++++++++++
 .../src/main/resources/skywalking-plugin.def       |  21 ++++
 .../v5/RedisChannelWriterInterceptorTest.java      | 112 +++++++++++++++++++++
 apm-sniffer/optional-plugins/pom.xml               |   1 +
 docker/config/component-libraries.yml              |   4 +
 docs/en/guides/Component-library-settings.md       |   1 +
 docs/en/setup/service-agent/java-agent/README.md   |   1 +
 .../service-agent/java-agent/Supported-list.md     |   1 +
 .../others/cn/guides/Component-library-settings.md |   2 +
 .../cn/guides/Java-Plugin-Development-Guide.md     |   2 +-
 .../src/test/resources/component-libraries.yml     |   4 +
 .../src/main/resources/component-libraries.yml     |   4 +
 24 files changed, 887 insertions(+), 2 deletions(-)

diff --git a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
index 2c0c566..c0784d1 100644
--- a/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
+++ b/apm-protocol/apm-network/src/main/java/org/apache/skywalking/apm/network/trace/component/ComponentsDefine.java
@@ -110,6 +110,8 @@ public class ComponentsDefine {
   
     public static final OfficialComponent REDISSON =  new OfficialComponent(56, "Redisson");
 
+    public static final OfficialComponent LETTUCE =  new OfficialComponent(57, "Lettuce");
+
     private static ComponentsDefine INSTANCE = new ComponentsDefine();
 
     private String[] components;
@@ -119,7 +121,7 @@ public class ComponentsDefine {
     }
 
     public ComponentsDefine() {
-        components = new String[57];
+        components = new String[58];
         addComponent(TOMCAT);
         addComponent(HTTPCLIENT);
         addComponent(DUBBO);
@@ -161,6 +163,7 @@ public class ComponentsDefine {
         addComponent(CANAL);
         addComponent(GSON);
         addComponent(REDISSON);
+        addComponent(LETTUCE);
     }
 
     private void addComponent(OfficialComponent component) {
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/pom.xml b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/pom.xml
new file mode 100644
index 0000000..1ad9451
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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>
+    <parent>
+        <groupId>org.apache.skywalking</groupId>
+        <artifactId>optional-plugins</artifactId>
+        <version>6.1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>apm-lettuce-5.x-plugin</artifactId>
+    <packaging>jar</packaging>
+
+    <name>lettuce-5.x-plugin</name>
+    <url>http://maven.apache.org</url>
+    <properties>
+        <lettuce-core.version>5.1.3.RELEASE</lettuce-core.version>
+        <compiler.version>1.8</compiler.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>io.lettuce</groupId>
+            <artifactId>lettuce-core</artifactId>
+            <version>${lettuce-core.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/AsyncCommandMethodInterceptor.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/AsyncCommandMethodInterceptor.java
new file mode 100644
index 0000000..b713e64
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/AsyncCommandMethodInterceptor.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.skywalking.apm.plugin.lettuce.v5;
+
+import io.lettuce.core.protocol.AsyncCommand;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+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.network.trace.component.ComponentsDefine;
+
+import java.lang.reflect.Method;
+import java.util.function.Consumer;
+
+/**
+ * @author zhaoyuguang
+ */
+public class AsyncCommandMethodInterceptor implements InstanceMethodsAroundInterceptor {
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) throws Throwable {
+        AsyncCommand asyncCommand = (AsyncCommand) objInst;
+        String operationName = "Lettuce/" + asyncCommand.getType().name();
+        AbstractSpan span = ContextManager.createLocalSpan(operationName + "/onComplete");
+        span.setComponent(ComponentsDefine.LETTUCE);
+        allArguments[0] = new SWConsumer((Consumer) allArguments[0], ContextManager.capture(), operationName);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+                              Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        ContextManager.stopSpan();
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+        ContextManager.activeSpan().errorOccurred().log(t);
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/ClientOptionsConstructorInterceptor.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/ClientOptionsConstructorInterceptor.java
new file mode 100644
index 0000000..7918e2c
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/ClientOptionsConstructorInterceptor.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.plugin.lettuce.v5;
+
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * ClientOptions is the link between RedisChannelWriter and AbstractRedisClient.
+ * to enhance ClientOptions for bring peer(the cluster configuration information)
+ * in AbstractRedisClient to RedisChannelWriter.
+ *
+ * @author zhaoyuguang
+ */
+public class ClientOptionsConstructorInterceptor implements InstanceConstructorInterceptor {
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptor.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptor.java
new file mode 100644
index 0000000..b44715d
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptor.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 io.lettuce.core.protocol.RedisCommand;
+import org.apache.skywalking.apm.agent.core.context.ContextManager;
+import org.apache.skywalking.apm.agent.core.context.tag.Tags;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
+import org.apache.skywalking.apm.network.trace.component.ComponentsDefine;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+/**
+ * @author zhaoyuguang
+ */
+public class RedisChannelWriterInterceptor implements InstanceMethodsAroundInterceptor, InstanceConstructorInterceptor {
+
+    @Override
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
+                             MethodInterceptResult result) throws Throwable {
+        String peer = (String) objInst.getSkyWalkingDynamicField();
+
+        StringBuilder dbStatement = new StringBuilder();
+        String operationName = "Lettuce/";
+
+        if (allArguments[0] instanceof RedisCommand) {
+            RedisCommand redisCommand = (RedisCommand) allArguments[0];
+            String command = redisCommand.getType().name();
+            operationName = operationName + command;
+            dbStatement.append(command);
+        } else if (allArguments[0] instanceof Collection) {
+            @SuppressWarnings("unchecked")
+            Collection<RedisCommand> redisCommands = (Collection<RedisCommand>) allArguments[0];
+            operationName = operationName + "BATCH_WRITE";
+            for (RedisCommand redisCommand : redisCommands) {
+                dbStatement.append(redisCommand.getType().name()).append(";");
+            }
+        }
+
+        AbstractSpan span = ContextManager.createExitSpan(operationName, peer);
+        span.setComponent(ComponentsDefine.LETTUCE);
+        Tags.DB_TYPE.set(span, "Redis");
+        Tags.DB_STATEMENT.set(span, dbStatement.toString());
+        SpanLayer.asCache(span);
+    }
+
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments,
+                              Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        ContextManager.stopSpan();
+        return ret;
+    }
+
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments,
+                                      Class<?>[] argumentsTypes, Throwable t) {
+        AbstractSpan span = ContextManager.activeSpan();
+        span.errorOccurred();
+        span.log(t);
+    }
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+        EnhancedInstance optionsInst = (EnhancedInstance) allArguments[0];
+        objInst.setSkyWalkingDynamicField(optionsInst.getSkyWalkingDynamicField());
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisClientConstructorInterceptor.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisClientConstructorInterceptor.java
new file mode 100644
index 0000000..21ecb14
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisClientConstructorInterceptor.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.v5;
+
+import io.lettuce.core.RedisClient;
+import io.lettuce.core.RedisURI;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * @author zhaoyuguang
+ */
+public class RedisClientConstructorInterceptor implements InstanceConstructorInterceptor {
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+        RedisURI redisURI = (RedisURI) allArguments[1];
+        RedisClient redisClient = (RedisClient) objInst;
+        EnhancedInstance optionsInst = (EnhancedInstance) redisClient.getOptions();
+        optionsInst.setSkyWalkingDynamicField(redisURI.getHost() + ":" + redisURI.getPort());
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisClusterClientConstructorInterceptor.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisClusterClientConstructorInterceptor.java
new file mode 100644
index 0000000..a8f7165
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisClusterClientConstructorInterceptor.java
@@ -0,0 +1,44 @@
+/*
+ * 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 io.lettuce.core.RedisURI;
+import io.lettuce.core.cluster.RedisClusterClient;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
+
+/**
+ * @author zhaoyuguang
+ */
+public class RedisClusterClientConstructorInterceptor implements InstanceConstructorInterceptor {
+
+    @Override
+    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
+        @SuppressWarnings("unchecked")
+        Iterable<RedisURI> redisURIs = (Iterable<RedisURI>) allArguments[1];
+        RedisClusterClient redisClusterClient = (RedisClusterClient) objInst;
+        StringBuilder peer = new StringBuilder();
+        for (RedisURI redisURI : redisURIs) {
+            peer.append(redisURI.getHost()).append(":").append(redisURI.getPort()).append(";");
+        }
+        EnhancedInstance optionsInst = (EnhancedInstance) redisClusterClient.getOptions();
+        optionsInst.setSkyWalkingDynamicField(peer.toString());
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/SWConsumer.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/SWConsumer.java
new file mode 100644
index 0000000..dbb27e0
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/SWConsumer.java
@@ -0,0 +1,56 @@
+/*
+ * 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.network.trace.component.ComponentsDefine;
+
+import java.util.function.Consumer;
+
+/**
+ * @author zhaoyuguang
+ */
+public class SWConsumer<T> implements Consumer<T> {
+
+    private Consumer<T> consumer;
+    private ContextSnapshot snapshot;
+    private String operationName;
+
+    SWConsumer(Consumer<T> consumer, ContextSnapshot snapshot, String operationName) {
+        this.consumer = consumer;
+        this.snapshot = snapshot;
+        this.operationName = operationName;
+    }
+
+    @Override
+    public void accept(T t) {
+        AbstractSpan span = ContextManager.createLocalSpan(operationName + "/accept");
+        span.setComponent(ComponentsDefine.LETTUCE);
+        try {
+            ContextManager.continued(snapshot);
+            consumer.accept(t);
+        } catch (Throwable th) {
+            ContextManager.activeSpan().errorOccurred().log(th);
+        } finally {
+            ContextManager.stopSpan();
+        }
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/AsyncCommandInstrumentation.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/AsyncCommandInstrumentation.java
new file mode 100644
index 0000000..8f74450
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/AsyncCommandInstrumentation.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.skywalking.apm.plugin.lettuce.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * @author zhaoyuguang
+ */
+public class AsyncCommandInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "io.lettuce.core.protocol.AsyncCommand";
+
+    private static final String ASYNC_COMMAND_METHOD_INTERCEPTOR = "org.apache.skywalking.apm.plugin.lettuce.v5.AsyncCommandMethodInterceptor";
+
+    @Override
+    protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[0];
+    }
+
+    @Override
+    protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("onComplete");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return ASYNC_COMMAND_METHOD_INTERCEPTOR;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return true;
+                }
+            }
+        };
+    }
+
+    @Override
+    public ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/ClientOptionsInstrumentation.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/ClientOptionsInstrumentation.java
new file mode 100644
index 0000000..238907c
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/ClientOptionsInstrumentation.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.skywalking.apm.plugin.lettuce.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.any;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * @author zhaoyuguang
+ */
+public class ClientOptionsInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "io.lettuce.core.ClientOptions";
+
+    private static final String CLIENT_OPTIONS_CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v5.ClientOptionsConstructorInterceptor";
+
+    @Override
+    protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[]{
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getConstructorMatcher() {
+                    return any();
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return CLIENT_OPTIONS_CONSTRUCTOR_INTERCEPTOR_CLASS;
+                }
+            }
+        };
+    }
+
+    @Override
+    protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[0];
+    }
+
+    @Override
+    public ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java
new file mode 100644
index 0000000..74ac433
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisChannelWriterInstrumentation.java
@@ -0,0 +1,87 @@
+/*
+ * 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.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * The writeAndFlush method is used in versions lower than 5.0.2.RELEASE
+ *
+ * @author zhaoyuguang
+ */
+public class RedisChannelWriterInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "io.lettuce.core.protocol.DefaultEndpoint";
+
+    private static final String REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisChannelWriterInterceptor";
+
+    @Override
+    protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[] {
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getConstructorMatcher() {
+                    return takesArgumentWithType(0, "io.lettuce.core.ClientOptions");
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS;
+                }
+            }
+        };
+    }
+
+    @Override
+    protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[]{
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("writeToChannelAndFlush").or(named("writeAndFlush"));
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return REDIS_CHANNEL_WRITER_INTERCEPTOR_CLASS;
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
+    }
+
+    @Override
+    public ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisClientInstrumentation.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisClientInstrumentation.java
new file mode 100644
index 0000000..7609666
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisClientInstrumentation.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.skywalking.apm.plugin.lettuce.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * @author zhaoyuguang
+ */
+public class RedisClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "io.lettuce.core.RedisClient";
+
+    private static final String REDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisClientConstructorInterceptor";
+
+    @Override
+    protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[]{
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getConstructorMatcher() {
+                    return takesArgumentWithType(1, "io.lettuce.core.RedisURI");
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return REDIS_CLIENT_CONSTRUCTOR_INTERCEPTOR_CLASS;
+                }
+            }
+        };
+    }
+
+    @Override
+    protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[0];
+    }
+
+    @Override
+    public ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisClusterClientInstrumentation.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisClusterClientInstrumentation.java
new file mode 100644
index 0000000..c4877b3
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/lettuce/v5/define/RedisClusterClientInstrumentation.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+package org.apache.skywalking.apm.plugin.lettuce.v5.define;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatcher;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
+import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
+
+import static org.apache.skywalking.apm.agent.core.plugin.bytebuddy.ArgumentTypeNameMatch.takesArgumentWithType;
+import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
+
+/**
+ * @author zhaoyuguang
+ */
+public class RedisClusterClientInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
+
+    private static final String ENHANCE_CLASS = "io.lettuce.core.cluster.RedisClusterClient";
+
+    private static final String REDIS_CLUSTER_CLIENT_CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.lettuce.v5.RedisClusterClientConstructorInterceptor";
+
+    @Override
+    protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
+        return new ConstructorInterceptPoint[]{
+            new ConstructorInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getConstructorMatcher() {
+                    return takesArgumentWithType(1, "java.lang.Iterable");
+                }
+
+                @Override
+                public String getConstructorInterceptor() {
+                    return REDIS_CLUSTER_CLIENT_CONSTRUCTOR_INTERCEPTOR_CLASS;
+                }
+            }
+        };
+    }
+
+    @Override
+    protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
+        return new InstanceMethodsInterceptPoint[0];
+    }
+
+    @Override
+    public ClassMatch enhanceClass() {
+        return byName(ENHANCE_CLASS);
+    }
+}
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 0000000..95739fb
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1,21 @@
+# 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.
+
+lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.AsyncCommandInstrumentation
+lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.ClientOptionsInstrumentation
+lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisChannelWriterInstrumentation
+lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisClientInstrumentation
+lettuce-5.x=org.apache.skywalking.apm.plugin.lettuce.v5.define.RedisClusterClientInstrumentation
\ No newline at end of file
diff --git a/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java
new file mode 100644
index 0000000..28f8b47
--- /dev/null
+++ b/apm-sniffer/optional-plugins/lettuce-5.x-plugin/src/test/java/org/apache/skywalking/apm/plugin/lettuce/v5/RedisChannelWriterInterceptorTest.java
@@ -0,0 +1,112 @@
+/*
+ * 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 io.lettuce.core.protocol.Command;
+import io.lettuce.core.protocol.CommandType;
+import io.lettuce.core.protocol.RedisCommand;
+import org.apache.skywalking.apm.agent.core.context.trace.AbstractTracingSpan;
+import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer;
+import org.apache.skywalking.apm.agent.core.context.trace.TraceSegment;
+import org.apache.skywalking.apm.agent.core.context.util.TagValuePair;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
+import org.apache.skywalking.apm.agent.test.helper.SegmentHelper;
+import org.apache.skywalking.apm.agent.test.helper.SpanHelper;
+import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStorage;
+import org.apache.skywalking.apm.agent.test.tools.SegmentStoragePoint;
+import org.apache.skywalking.apm.agent.test.tools.TracingSegmentRunner;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.MatcherAssert;
+import org.hamcrest.core.Is;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+/**
+ * @author zhaoyuguang
+ */
+@RunWith(PowerMockRunner.class)
+@PowerMockRunnerDelegate(TracingSegmentRunner.class)
+public class RedisChannelWriterInterceptorTest {
+
+    @SegmentStoragePoint
+    private SegmentStorage segmentStorage;
+
+    @Rule
+    public AgentServiceRule serviceRule = new AgentServiceRule();
+
+    @Mock
+    private MockInstance mockClientOptionsInstance;
+    @Mock
+    private MockInstance mockRedisChannelWriterInstance;
+
+    private RedisChannelWriterInterceptor interceptor;
+
+    private class MockInstance implements EnhancedInstance {
+        private Object object;
+
+        @Override
+        public Object getSkyWalkingDynamicField() {
+            return object;
+        }
+
+        @Override
+        public void setSkyWalkingDynamicField(Object value) {
+            this.object = value;
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Before
+    public void setUp() throws Exception {
+        mockRedisChannelWriterInstance = new MockInstance();
+        mockClientOptionsInstance = new MockInstance();
+        mockClientOptionsInstance.setSkyWalkingDynamicField("127.0.0.1:6379;127.0.0.1:6378;");
+        interceptor = new RedisChannelWriterInterceptor();
+    }
+
+
+    @Test
+    public void testInterceptor() throws Throwable {
+        interceptor.onConstruct(mockRedisChannelWriterInstance, new Object[]{mockClientOptionsInstance});
+        RedisCommand redisCommand = new Command(CommandType.SET, null);
+        interceptor.beforeMethod(mockRedisChannelWriterInstance, null, new Object[]{redisCommand}, null, null);
+        interceptor.afterMethod(mockRedisChannelWriterInstance, null, null, null, null);
+        MatcherAssert.assertThat((String) mockRedisChannelWriterInstance.getSkyWalkingDynamicField(), Is.is("127.0.0.1:6379;127.0.0.1:6378;"));
+        TraceSegment traceSegment = segmentStorage.getTraceSegments().get(0);
+        List<AbstractTracingSpan> spans = SegmentHelper.getSpans(traceSegment);
+        assertThat(spans.size(), is(1));
+        assertThat(spans.get(0).getOperationName(), is("Lettuce/SET"));
+        assertThat(spans.get(0).isExit(), is(true));
+        assertThat(SpanHelper.getComponentId(spans.get(0)), is(57));
+        List<TagValuePair> tags = SpanHelper.getTags(spans.get(0));
+        assertThat(tags.get(0).getValue(), is("Redis"));
+        assertThat(SpanHelper.getLayer(spans.get(0)), CoreMatchers.is(SpanLayer.CACHE));
+    }
+}
diff --git a/apm-sniffer/optional-plugins/pom.xml b/apm-sniffer/optional-plugins/pom.xml
index 22af18d..e462a2c 100644
--- a/apm-sniffer/optional-plugins/pom.xml
+++ b/apm-sniffer/optional-plugins/pom.xml
@@ -44,6 +44,7 @@
         <module>optional-spring-plugins</module>
         <module>trace-ignore-plugin</module>
         <module>gson-2.8.x-plugin</module>
+        <module>lettuce-5.x-plugin</module>
     </modules>
 
     <dependencies>
diff --git a/docker/config/component-libraries.yml b/docker/config/component-libraries.yml
index 5aab340..1ea9f1f 100644
--- a/docker/config/component-libraries.yml
+++ b/docker/config/component-libraries.yml
@@ -198,6 +198,9 @@ Gson:
 Redisson:
   id: 56
   languages: Java
+Lettuce:
+  id: 57
+  languages: Java
 
 
 # .NET/.NET Core components
@@ -283,6 +286,7 @@ Component-Server-Mappings:
   mysql-connector-java: Mysql
   Jedis: Redis
   Redisson: Redis
+  Lettuce: Redis
   StackExchange.Redis: Redis
   SqlClient: SqlServer
   Npgsql: PostgreSQL
diff --git a/docs/en/guides/Component-library-settings.md b/docs/en/guides/Component-library-settings.md
index d2f7634..ea32041 100644
--- a/docs/en/guides/Component-library-settings.md
+++ b/docs/en/guides/Component-library-settings.md
@@ -56,6 +56,7 @@ Component-Server-Mappings:
   Jedis: Redis
   StackExchange.Redis: Redis
   Redisson: Redis
+  Lettuce: Redis
   SqlClient: SqlServer
   Npgsql: PostgreSQL
   MySqlConnector: Mysql
diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md
index 91c57f3..a10cc52 100644
--- a/docs/en/setup/service-agent/java-agent/README.md
+++ b/docs/en/setup/service-agent/java-agent/README.md
@@ -87,6 +87,7 @@ Now, we have the following known optional plugins.
 * [Trace Oracle and Resin](agent-optional-plugins/Oracle-Resin-plugins.md)
 * [Filter traces through specified endpoint name patterns](agent-optional-plugins/trace-ignore-plugin.md)
 * Gson serialization lib in optional plugin folder
+* Lettuce 5.x(JRE1.8+) in optional plugin folder 
 
 ## Advanced Features
 * Set the settings through system properties for config file override. Read [setting override](Setting-override.md).
diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md
index 10c0892..2c04fe6 100644
--- a/docs/en/setup/service-agent/java-agent/Supported-list.md
+++ b/docs/en/setup/service-agent/java-agent/Supported-list.md
@@ -41,6 +41,7 @@
   * Redis
     * [Jedis](https://github.com/xetorthio/jedis) 2.x
     * [Redisson](https://github.com/redisson/redisson) Easy Java Redis client 3.5.2+
+    * [Lettuce](https://github.com/lettuce-io/lettuce-core) 5.x (Optional²)
   * [MongoDB Java Driver](https://github.com/mongodb/mongo-java-driver) 2.13-2.14,3.3+
   * Memcached Client
     * [Spymemcached](https://github.com/couchbase/spymemcached) 2.x
diff --git a/docs/others/cn/guides/Component-library-settings.md b/docs/others/cn/guides/Component-library-settings.md
index 16806b0..1d531df 100644
--- a/docs/others/cn/guides/Component-library-settings.md
+++ b/docs/others/cn/guides/Component-library-settings.md
@@ -55,6 +55,8 @@ H2:
 Component-Server-Mappings:
   Jedis: Redis
   StackExchange.Redis: Redis
+  Redisson: Redis
+  Lettuce: Redis
   SqlClient: SqlServer
   Npgsql: PostgreSQL
   MySqlConnector: Mysql
diff --git a/docs/others/cn/guides/Java-Plugin-Development-Guide.md b/docs/others/cn/guides/Java-Plugin-Development-Guide.md
index 615e13a..7eb5699 100644
--- a/docs/others/cn/guides/Java-Plugin-Development-Guide.md
+++ b/docs/others/cn/guides/Java-Plugin-Development-Guide.md
@@ -69,7 +69,7 @@ ExitSpan代表一个服务客户端或MQ的生产者,在SkyWalking的早期命
 以下是有关跨线程传播的三个步骤:
 1. 使用`ContextManager#capture`获取ContextSnapshot对象。
 2. 让子线程以任何方式,通过方法参数或由现有参数携带来访问ContextSnapshot
-3. 在子线程中使用`ContextManager#continies`。
+3. 在子线程中使用`ContextManager#continued`。
 
 ## 核心 API
 ### ContextManager
diff --git a/oap-server/server-core/src/test/resources/component-libraries.yml b/oap-server/server-core/src/test/resources/component-libraries.yml
index 1bc3126..6023696 100644
--- a/oap-server/server-core/src/test/resources/component-libraries.yml
+++ b/oap-server/server-core/src/test/resources/component-libraries.yml
@@ -180,6 +180,9 @@ Undertow:
 Redisson:
   id: 56
   languages: Java
+Lettuce:
+  id: 57
+  languages: Java
 
 # .NET/.NET Core components
 # [3000, 4000) for C#/.NET only
@@ -262,6 +265,7 @@ Component-Server-Mappings:
   mysql-connector-java: Mysql
   Jedis: Redis
   Redisson: Redis
+  Lettuce: Redis
   StackExchange.Redis: Redis
   SqlClient: SqlServer
   Npgsql: PostgreSQL
diff --git a/oap-server/server-starter/src/main/resources/component-libraries.yml b/oap-server/server-starter/src/main/resources/component-libraries.yml
index 4fdf028..bae435c 100644
--- a/oap-server/server-starter/src/main/resources/component-libraries.yml
+++ b/oap-server/server-starter/src/main/resources/component-libraries.yml
@@ -198,6 +198,9 @@ Gson:
 Redisson:
   id: 56
   languages: Java
+Lettuce:
+  id: 57
+  languages: Java
 
 
 # .NET/.NET Core components
@@ -284,6 +287,7 @@ Component-Server-Mappings:
   Jedis: Redis
   StackExchange.Redis: Redis
   Redisson: Redis
+  Lettuce: Redis
   SqlClient: SqlServer
   Npgsql: PostgreSQL
   MySqlConnector: Mysql