diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc index f93147f06c8..67027624999 100644 --- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc +++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/actuator/metrics.adoc @@ -1053,7 +1053,7 @@ Metrics for Jetty's javadoc:org.eclipse.jetty.server.Connector[] instances are b [[actuator.metrics.supported.redis]] === Redis Metrics -Auto-configuration registers a javadoc:io.lettuce.core.metrics.MicrometerCommandLatencyRecorder[] for the auto-configured javadoc:org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory[]. +Auto-configuration registers a javadoc:io.lettuce.core.tracing.MicrometerTracing[] for the auto-configured javadoc:org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory[]. For more detail, see the {url-lettuce-docs}/advanced-usage/#observability[Observability section] of the Lettuce documentation. diff --git a/module/spring-boot-data-redis/build.gradle b/module/spring-boot-data-redis/build.gradle index 3f8b68f0885..afc852b7b7a 100644 --- a/module/spring-boot-data-redis/build.gradle +++ b/module/spring-boot-data-redis/build.gradle @@ -56,6 +56,7 @@ dependencies { testImplementation(project(":core:spring-boot-test")) testImplementation(project(":test-support:spring-boot-test-support")) + testImplementation("io.micrometer:micrometer-observation-test") testImplementation("io.projectreactor:reactor-test") testRuntimeOnly("ch.qos.logback:logback-classic") diff --git a/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/metrics/LettuceMetricsAutoConfiguration.java b/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/observation/LettuceObservationAutoConfiguration.java similarity index 55% rename from module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/metrics/LettuceMetricsAutoConfiguration.java rename to module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/observation/LettuceObservationAutoConfiguration.java index 0e084c74371..36c9db24443 100644 --- a/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/metrics/LettuceMetricsAutoConfiguration.java +++ b/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/observation/LettuceObservationAutoConfiguration.java @@ -14,43 +14,36 @@ * limitations under the License. */ -package org.springframework.boot.data.redis.autoconfigure.metrics; +package org.springframework.boot.data.redis.autoconfigure.observation; import io.lettuce.core.RedisClient; -import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder; -import io.lettuce.core.metrics.MicrometerOptions; -import io.micrometer.core.instrument.MeterRegistry; +import io.lettuce.core.tracing.MicrometerTracing; +import io.micrometer.observation.ObservationRegistry; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.data.redis.autoconfigure.ClientResourcesBuilderCustomizer; import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration; import org.springframework.context.annotation.Bean; /** - * Auto-configuration for Lettuce metrics. + * Auto-configuration for Lettuce observability. * * @author Antonin Arquey * @author Yanming Zhou + * @author Dũng Đăng Minh * @since 4.0.0 */ @AutoConfiguration(before = DataRedisAutoConfiguration.class, - afterName = "org.springframework.boot.micrometer.metrics.autoconfigure.CompositeMeterRegistryAutoConfiguration") -@ConditionalOnClass({ RedisClient.class, MicrometerCommandLatencyRecorder.class, MeterRegistry.class }) -@ConditionalOnBean(MeterRegistry.class) -public final class LettuceMetricsAutoConfiguration { + afterName = "org.springframework.boot.micrometer.observation.autoconfigure.ObservationAutoConfiguration") +@ConditionalOnClass({ RedisClient.class, MicrometerTracing.class, ObservationRegistry.class }) +@ConditionalOnBean(ObservationRegistry.class) +public final class LettuceObservationAutoConfiguration { @Bean - @ConditionalOnMissingBean - MicrometerOptions micrometerOptions() { - return MicrometerOptions.create(); - } - - @Bean - ClientResourcesBuilderCustomizer lettuceMetrics(MeterRegistry meterRegistry, MicrometerOptions options) { - return (client) -> client.commandLatencyRecorder(new MicrometerCommandLatencyRecorder(meterRegistry, options)); + ClientResourcesBuilderCustomizer lettuceObservation(ObservationRegistry observationRegistry) { + return (client) -> client.tracing(new MicrometerTracing(observationRegistry, "Redis")); } } diff --git a/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/metrics/package-info.java b/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/observation/package-info.java similarity index 84% rename from module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/metrics/package-info.java rename to module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/observation/package-info.java index 8e44b394cf5..454d2649ec6 100644 --- a/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/metrics/package-info.java +++ b/module/spring-boot-data-redis/src/main/java/org/springframework/boot/data/redis/autoconfigure/observation/package-info.java @@ -15,9 +15,9 @@ */ /** - * Auto-configuration for Spring Data Redis metrics. + * Auto-configuration for Spring Data Redis observation. */ @NullMarked -package org.springframework.boot.data.redis.autoconfigure.metrics; +package org.springframework.boot.data.redis.autoconfigure.observation; import org.jspecify.annotations.NullMarked; diff --git a/module/spring-boot-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/module/spring-boot-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index c2adccbf23a..03b2339b4e6 100644 --- a/module/spring-boot-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/module/spring-boot-data-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -3,4 +3,4 @@ org.springframework.boot.data.redis.autoconfigure.DataRedisReactiveAutoConfigura org.springframework.boot.data.redis.autoconfigure.DataRedisRepositoriesAutoConfiguration org.springframework.boot.data.redis.autoconfigure.health.DataRedisHealthContributorAutoConfiguration org.springframework.boot.data.redis.autoconfigure.health.DataRedisReactiveHealthContributorAutoConfiguration -org.springframework.boot.data.redis.autoconfigure.metrics.LettuceMetricsAutoConfiguration +org.springframework.boot.data.redis.autoconfigure.observation.LettuceObservationAutoConfiguration diff --git a/module/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/metrics/LettuceMetricsAutoConfigurationTests.java b/module/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/metrics/LettuceMetricsAutoConfigurationTests.java deleted file mode 100644 index 2419e3a609f..00000000000 --- a/module/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/metrics/LettuceMetricsAutoConfigurationTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2012-present 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.boot.data.redis.autoconfigure.metrics; - -import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder; -import io.lettuce.core.metrics.MicrometerOptions; -import io.lettuce.core.resource.ClientResources; -import io.micrometer.core.instrument.simple.SimpleMeterRegistry; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.autoconfigure.AutoConfigurations; -import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration; -import org.springframework.boot.test.context.runner.ApplicationContextRunner; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link LettuceMetricsAutoConfiguration}. - * - * @author Antonin Arquey - */ -class LettuceMetricsAutoConfigurationTests { - - private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(LettuceMetricsAutoConfiguration.class)); - - @Test - void whenThereIsAMeterRegistryThenCommandLatencyRecorderIsAdded() { - this.contextRunner.withBean(SimpleMeterRegistry.class) - .withConfiguration(AutoConfigurations.of(DataRedisAutoConfiguration.class)) - .run((context) -> { - ClientResources clientResources = context.getBean(LettuceConnectionFactory.class).getClientResources(); - assertThat(clientResources.commandLatencyRecorder()) - .isInstanceOf(MicrometerCommandLatencyRecorder.class); - }); - } - - @Test - void autoConfiguredMicrometerOptionsUsesLettucesDefaults() { - this.contextRunner.withBean(SimpleMeterRegistry.class) - .withConfiguration(AutoConfigurations.of(DataRedisAutoConfiguration.class)) - .run((context) -> { - MicrometerOptions micrometerOptions = context.getBean(MicrometerOptions.class); - assertThat(micrometerOptions.isEnabled()).isTrue(); - assertThat(micrometerOptions.isHistogram()).isFalse(); - assertThat(micrometerOptions.localDistinction()).isFalse(); - assertThat(micrometerOptions.maxLatency()).isEqualTo(MicrometerOptions.DEFAULT_MAX_LATENCY); - assertThat(micrometerOptions.minLatency()).isEqualTo(MicrometerOptions.DEFAULT_MIN_LATENCY); - }); - } - - @Test - void whenUserDefinesAMicrometerOptionsBeanThenCommandLatencyRecorderUsesIt() { - this.contextRunner.withBean(SimpleMeterRegistry.class) - .withConfiguration(AutoConfigurations.of(DataRedisAutoConfiguration.class)) - .withUserConfiguration(CustomMicrometerOptionsConfiguration.class) - .run((context) -> { - ClientResources clientResources = context.getBean(LettuceConnectionFactory.class).getClientResources(); - assertThat(clientResources.commandLatencyRecorder()) - .isInstanceOf(MicrometerCommandLatencyRecorder.class); - assertThat(clientResources.commandLatencyRecorder()).hasFieldOrPropertyWithValue("options", - context.getBean("customMicrometerOptions")); - }); - } - - @Test - void whenThereIsNoMeterRegistryThenClientResourcesCustomizationBacksOff() { - this.contextRunner.withConfiguration(AutoConfigurations.of(DataRedisAutoConfiguration.class)).run((context) -> { - ClientResources clientResources = context.getBean(LettuceConnectionFactory.class).getClientResources(); - assertThat(clientResources.commandLatencyRecorder()) - .isNotInstanceOf(MicrometerCommandLatencyRecorder.class); - }); - } - - @Configuration(proxyBeanMethods = false) - static class CustomMicrometerOptionsConfiguration { - - @Bean - MicrometerOptions customMicrometerOptions() { - return MicrometerOptions.create(); - } - - } - -} diff --git a/module/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/observation/LettuceObservationAutoConfigurationTests.java b/module/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/observation/LettuceObservationAutoConfigurationTests.java new file mode 100644 index 00000000000..366d04243d9 --- /dev/null +++ b/module/spring-boot-data-redis/src/test/java/org/springframework/boot/data/redis/autoconfigure/observation/LettuceObservationAutoConfigurationTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-present 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.boot.data.redis.autoconfigure.observation; + +import io.lettuce.core.resource.ClientResources; +import io.lettuce.core.tracing.MicrometerTracing; +import io.micrometer.observation.tck.TestObservationRegistry; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.data.redis.autoconfigure.DataRedisAutoConfiguration; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link LettuceObservationAutoConfiguration}. + * + * @author Antonin Arquey + * @author Stephane Nicoll + */ +class LettuceObservationAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(LettuceObservationAutoConfiguration.class)); + + @Test + void whenThereIsAnObservationRegistryThenMicrometerTracingIsAdded() { + this.contextRunner.withBean(TestObservationRegistry.class, TestObservationRegistry::create) + .withConfiguration(AutoConfigurations.of(DataRedisAutoConfiguration.class)) + .run((context) -> { + ClientResources clientResources = context.getBean(LettuceConnectionFactory.class).getClientResources(); + assertThat(clientResources.tracing()).isInstanceOf(MicrometerTracing.class); + }); + + } + + @Test + void whenThereIsNoObservationRegistryThenClientResourcesCustomizationBacksOff() { + this.contextRunner.withConfiguration(AutoConfigurations.of(DataRedisAutoConfiguration.class)).run((context) -> { + ClientResources clientResources = context.getBean(LettuceConnectionFactory.class).getClientResources(); + assertThat(clientResources.tracing()).isNotInstanceOf(MicrometerTracing.class); + }); + } + +}