diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/LettuceMetricsAutoConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/LettuceMetricsAutoConfiguration.java new file mode 100644 index 0000000000..ccad314730 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/LettuceMetricsAutoConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2021 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.actuate.autoconfigure.metrics.redis; + +import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder; +import io.lettuce.core.metrics.MicrometerOptions; +import io.micrometer.core.instrument.MeterRegistry; + +import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.data.redis.ClientResourcesBuilderCustomizer; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; + +/** + * Auto-configuration for Lettuce metrics. + * + * @author Antonin Arquey + * @since 2.6.0 + */ +@Configuration(proxyBeanMethods = false) +@AutoConfigureBefore(RedisAutoConfiguration.class) +@AutoConfigureAfter({ MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class }) +@ConditionalOnClass(LettuceConnectionFactory.class) +@ConditionalOnBean(MeterRegistry.class) +public class LettuceMetricsAutoConfiguration { + + @Bean + public ClientResourcesBuilderCustomizer lettuceMetrics(MeterRegistry meterRegistry) { + MicrometerOptions options = MicrometerOptions.builder().histogram(true).build(); + return (client) -> client.commandLatencyRecorder(new MicrometerCommandLatencyRecorder(meterRegistry, options)) + .build(); + } + +} diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/package-info.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/package-info.java new file mode 100644 index 0000000000..961a84ff66 --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2012-2021 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. + */ + +/** + * Auto-configuration for Redis metrics. + */ +package org.springframework.boot.actuate.autoconfigure.metrics.redis; diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories index 08a70b7174..f0f203463f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/resources/META-INF/spring.factories @@ -74,6 +74,7 @@ org.springframework.boot.actuate.autoconfigure.metrics.jersey.JerseyServerMetric org.springframework.boot.actuate.autoconfigure.metrics.mongo.MongoMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.orm.jpa.HibernateMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.r2dbc.ConnectionPoolMetricsAutoConfiguration,\ +org.springframework.boot.actuate.autoconfigure.metrics.redis.LettuceMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.client.HttpClientMetricsAutoConfiguration,\ org.springframework.boot.actuate.autoconfigure.metrics.web.jetty.JettyMetricsAutoConfiguration,\ @@ -111,6 +112,5 @@ org.springframework.boot.actuate.autoconfigure.web.jersey.JerseyChildManagementC org.springframework.boot.actuate.autoconfigure.web.reactive.ReactiveManagementChildContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementChildContextConfiguration,\ org.springframework.boot.actuate.autoconfigure.web.servlet.WebMvcEndpointChildContextConfiguration - org.springframework.boot.diagnostics.FailureAnalyzer=\ org.springframework.boot.actuate.autoconfigure.metrics.ValidationFailureAnalyzer diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/LettuceMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/LettuceMetricsAutoConfigurationTests.java new file mode 100644 index 0000000000..e1352dd80b --- /dev/null +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/redis/LettuceMetricsAutoConfigurationTests.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2021 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.actuate.autoconfigure.metrics.redis; + +import io.lettuce.core.metrics.MicrometerCommandLatencyRecorder; +import io.lettuce.core.resource.ClientResources; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.actuate.autoconfigure.metrics.test.MetricsRun; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; + +import static org.assertj.core.api.Assertions.assertThat; + +class LettuceMetricsAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(LettuceMetricsAutoConfiguration.class)); + + @Test + void whenThereIsAMeterRegistryThenCommandLatencyRecorderIsAdded() { + this.contextRunner.with(MetricsRun.simple()) + .withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)).run((context) -> { + ClientResources clientResources = context.getBean(LettuceConnectionFactory.class) + .getClientResources(); + assertThat(clientResources.commandLatencyRecorder()).isNotNull() + .isInstanceOf(MicrometerCommandLatencyRecorder.class); + }); + } + + @Test + void whenThereIsNoMeterRegistryThenClientResourcesCustomizationBacksOff() { + this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class)).run((context) -> { + ClientResources clientResources = context.getBean(LettuceConnectionFactory.class).getClientResources(); + assertThat(clientResources.commandLatencyRecorder().isEnabled()) + .isNotInstanceOf(MicrometerCommandLatencyRecorder.class); + }); + } + +} diff --git a/spring-boot-project/spring-boot-docs/build.gradle b/spring-boot-project/spring-boot-docs/build.gradle index 2f6a5f5125..b13fd2ea8b 100644 --- a/spring-boot-project/spring-boot-docs/build.gradle +++ b/spring-boot-project/spring-boot-docs/build.gradle @@ -223,6 +223,7 @@ tasks.withType(org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask) { attributes "embedded-mongo-version": versionConstraints["de.flapdoodle.embed:de.flapdoodle.embed.mongo"], "jetty-version": versionConstraints["org.eclipse.jetty:jetty-server"], "jooq-version": versionConstraints["org.jooq:jooq"], + "lettuce-version": versionConstraints["io.lettuce:lettuce-core"], "spring-amqp-version": versionConstraints["org.springframework.amqp:spring-amqp"], "spring-batch-version": versionConstraints["org.springframework.batch:spring-batch-core"], "spring-boot-version": project.version, diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc index 8df74bba92..fc1e1973c7 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/actuator/metrics.adoc @@ -1068,6 +1068,14 @@ Long task timers require a separate metric name and can be stacked with a short +[[actuator.metrics.supported.redis]] +==== Redis Metrics + +Auto-configuration will register a `MicrometerCommandLatencyRecorder` for the auto-configured `LettuceConnectionFactory`. +For more details refer to {lettuce-docs}#command.latency.metrics.micrometer[Micrometer Metrics] section of the Lettuce documentation. + + + [[actuator.metrics.registering-custom]] === Registering Custom Metrics To register custom metrics, inject `MeterRegistry` into your component: diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc index 8e433bfb4d..a2c6842e40 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/attributes.adoc @@ -105,3 +105,4 @@ :micrometer-concepts-docs: {micrometer-docs}/concepts :micrometer-registry-docs: {micrometer-docs}/registry :tomcat-docs: https://tomcat.apache.org/tomcat-9.0-doc +:lettuce-docs: https://lettuce.io/core/{lettuce-version}/reference/index.html \ No newline at end of file