diff --git a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc
index b3e5b196a..436d0aab6 100644
--- a/docs/src/main/asciidoc/spring-cloud-sleuth.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-sleuth.adoc
@@ -1373,6 +1373,11 @@ IMPORTANT: We don't support baggage propagation for JMS
We instrument the Zuul Ribbon integration by enriching the Ribbon requests with tracing information.
To disable Zuul support, set the `spring.sleuth.zuul.enabled` property to `false`.
+=== Redis
+
+We set `tracing` property to Lettcue `ClientResources` instance to enable Brave tracing built in Lettuce .
+To disable Redis support, set the `spring.sleuth.redis.enabled` property to `false`.
+
== Running examples
You can see the running examples deployed in the https://run.pivotal.io/[Pivotal Web Services].
diff --git a/spring-cloud-sleuth-core/pom.xml b/spring-cloud-sleuth-core/pom.xml
index f752dc33c..3caf750ef 100644
--- a/spring-cloud-sleuth-core/pom.xml
+++ b/spring-cloud-sleuth-core/pom.xml
@@ -249,6 +249,13 @@
brave-instrumentation-grpc
true
+
+
+ io.lettuce
+ lettuce-core
+ true
+
+
org.springframework.boot
spring-boot-autoconfigure-processor
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/redis/OnRedisEnabled.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/redis/OnRedisEnabled.java
new file mode 100644
index 000000000..1d2d96a46
--- /dev/null
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/redis/OnRedisEnabled.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.sleuth.instrument.redis;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+
+/**
+ * Verifies if Redis property was enabled.
+ *
+ * @author Chao Chang
+ * @since 2.2.0
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Documented
+@ConditionalOnProperty(value = "spring.sleuth.redis.enabled", matchIfMissing = true)
+@interface OnRedisEnabled {
+
+}
diff --git a/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/redis/TraceRedisAutoConfiguration.java b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/redis/TraceRedisAutoConfiguration.java
new file mode 100644
index 000000000..996a3e595
--- /dev/null
+++ b/spring-cloud-sleuth-core/src/main/java/org/springframework/cloud/sleuth/instrument/redis/TraceRedisAutoConfiguration.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.sleuth.instrument.redis;
+
+import brave.Tracing;
+import io.lettuce.core.resource.ClientResources;
+import io.lettuce.core.tracing.BraveTracing;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
+ * Auto-configuration} enables Redis span information propagation.
+ *
+ * @author Chao Chang
+ * @since 2.2.0
+ */
+@Configuration
+@OnRedisEnabled
+@ConditionalOnBean({ Tracing.class, ClientResources.class })
+@AutoConfigureAfter({ TraceAutoConfiguration.class })
+public class TraceRedisAutoConfiguration {
+
+ @Configuration
+ static class LettuceConfig {
+
+ @Bean
+ static TraceLettuceClientResourcesBeanPostProcessor traceLettuceClientResourcesBeanPostProcessor(
+ Tracing tracing) {
+ return new TraceLettuceClientResourcesBeanPostProcessor(tracing);
+ }
+
+ }
+
+}
+
+class TraceLettuceClientResourcesBeanPostProcessor implements BeanPostProcessor {
+
+ private static final Log log = LogFactory
+ .getLog(TraceLettuceClientResourcesBeanPostProcessor.class);
+
+ private final Tracing tracing;
+
+ TraceLettuceClientResourcesBeanPostProcessor(Tracing tracing) {
+ this.tracing = tracing;
+ }
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName)
+ throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ if (bean instanceof ClientResources) {
+ ClientResources cr = (ClientResources) bean;
+ if (!cr.tracing().isEnabled()) {
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "Lettuce ClientResources bean is auto-configured to enable tracing.");
+ }
+ return cr.mutate().tracing(BraveTracing.create(this.tracing)).build();
+ }
+ if (log.isDebugEnabled()) {
+ log.debug(
+ "Lettuce ClientResources bean is skipped for auto-configuration because tracing was already enabled.");
+ }
+ }
+ return bean;
+ }
+
+}
diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index 8c3f68828..d4d453bb8 100644
--- a/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -53,6 +53,12 @@
"type": "java.lang.Boolean",
"description": "Enable span information propagation when using GRPC.",
"defaultValue": true
+ },
+ {
+ "name": "spring.sleuth.redis.enabled",
+ "type": "java.lang.Boolean",
+ "description": "Enable span information propagation when using Redis.",
+ "defaultValue": true
}
]
}
diff --git a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories
index db0e76446..5e0814f5f 100644
--- a/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-sleuth-core/src/main/resources/META-INF/spring.factories
@@ -24,7 +24,8 @@ org.springframework.cloud.sleuth.instrument.grpc.TraceGrpcAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.messaging.TraceMessagingAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.messaging.TraceSpringIntegrationAutoConfiguration,\
org.springframework.cloud.sleuth.instrument.messaging.websocket.TraceWebSocketAutoConfiguration,\
-org.springframework.cloud.sleuth.instrument.opentracing.OpentracingAutoConfiguration
+org.springframework.cloud.sleuth.instrument.opentracing.OpentracingAutoConfiguration,\
+org.springframework.cloud.sleuth.instrument.redis.TraceRedisAutoConfiguration
# Environment Post Processor
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.sleuth.autoconfig.TraceEnvironmentPostProcessor
diff --git a/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/redis/TraceRedisAutoConfigurationTests.java b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/redis/TraceRedisAutoConfigurationTests.java
new file mode 100644
index 000000000..2a873c706
--- /dev/null
+++ b/spring-cloud-sleuth-core/src/test/java/org/springframework/cloud/sleuth/instrument/redis/TraceRedisAutoConfigurationTests.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2013-2019 the original author or authors.
+ *
+ * Licensed 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
+ *
+ * https://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.springframework.cloud.sleuth.instrument.redis;
+
+import brave.Tracing;
+import io.lettuce.core.resource.ClientResources;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.assertj.core.api.BDDAssertions.then;
+
+/**
+ * @author Chao Chang
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TraceRedisAutoConfigurationTests.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
+public class TraceRedisAutoConfigurationTests {
+
+ @Autowired
+ ClientResources clientResources;
+
+ @Autowired
+ TestTraceLettuceClientResourcesBeanPostProcessor traceLettuceClientResourcesBeanPostProcessor;
+
+ @Test
+ public void tracing_should_be_set() {
+ then(this.traceLettuceClientResourcesBeanPostProcessor.tracingCalled).isTrue();
+ then(this.clientResources.tracing().isEnabled()).isTrue();
+ }
+
+ @Configuration
+ @EnableAutoConfiguration
+ protected static class Config {
+
+ @Bean
+ ClientResources clientResources() {
+ ClientResources clientResources = ClientResources.create();
+ then(clientResources.tracing().isEnabled()).isFalse();
+ return clientResources;
+ }
+
+ @Bean
+ TestTraceLettuceClientResourcesBeanPostProcessor testTraceLettuceClientResourcesBeanPostProcessor(
+ Tracing tracing) {
+ return new TestTraceLettuceClientResourcesBeanPostProcessor(tracing);
+ }
+
+ }
+
+}
+
+class TestTraceLettuceClientResourcesBeanPostProcessor
+ extends TraceLettuceClientResourcesBeanPostProcessor {
+
+ boolean tracingCalled = false;
+
+ TestTraceLettuceClientResourcesBeanPostProcessor(Tracing tracing) {
+ super(tracing);
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName)
+ throws BeansException {
+ this.tracingCalled = true;
+ return super.postProcessAfterInitialization(bean, beanName);
+ }
+
+}