From 61b1323440107915528c6239563f28cc91ea4849 Mon Sep 17 00:00:00 2001 From: Sunny Date: Sun, 27 Oct 2024 20:27:06 +0000 Subject: [PATCH] Auto-configure Micrometer Observations This commit auto-configures in the Micrometer Observations API and its Observation server interceptor. Resolves #1 Signed-off-by: Sunny --- spring-grpc-dependencies/pom.xml | 8 ++++ spring-grpc-spring-boot-autoconfigure/pom.xml | 10 ++++ ...rpcServerObservationAutoConfiguration.java | 32 +++++++++++++ ...rverObservationAutoConfigurationTests.java | 48 +++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfiguration.java create mode 100644 spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfigurationTests.java diff --git a/spring-grpc-dependencies/pom.xml b/spring-grpc-dependencies/pom.xml index dd4275e..8c39409 100644 --- a/spring-grpc-dependencies/pom.xml +++ b/spring-grpc-dependencies/pom.xml @@ -54,6 +54,7 @@ 1.63.2 3.25.5 2.46.0 + 1.13.6 @@ -112,6 +113,13 @@ proto-google-common-protos ${google-common-protos.version} + + io.micrometer + micrometer-bom + ${micrometer.version} + pom + import + diff --git a/spring-grpc-spring-boot-autoconfigure/pom.xml b/spring-grpc-spring-boot-autoconfigure/pom.xml index 35521a0..74f57b2 100644 --- a/spring-grpc-spring-boot-autoconfigure/pom.xml +++ b/spring-grpc-spring-boot-autoconfigure/pom.xml @@ -75,6 +75,16 @@ spring-boot-starter provided + + io.micrometer + micrometer-observation + true + + + io.micrometer + micrometer-core + true + diff --git a/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfiguration.java b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfiguration.java new file mode 100644 index 0000000..37027ab --- /dev/null +++ b/spring-grpc-spring-boot-autoconfigure/src/main/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfiguration.java @@ -0,0 +1,32 @@ +package org.springframework.grpc.autoconfigure.server; + +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptor; +import io.micrometer.core.instrument.binder.grpc.ObservationGrpcServerInterceptor; +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.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.grpc.server.ServerBuilderCustomizer; + +@AutoConfiguration( + afterName = "org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration") +@ConditionalOnClass(value = { ObservationRegistry.class, ObservationGrpcServerInterceptor.class }) +@ConditionalOnBean(ObservationRegistry.class) +@ConditionalOnProperty(value = "spring.grpc.server.observation.enabled", matchIfMissing = true) +public class GrpcServerObservationAutoConfiguration { + + @Bean + public ServerInterceptor observationGrpcServerInterceptor(ObservationRegistry observationRegistry) { + return new ObservationGrpcServerInterceptor(observationRegistry); + } + + @Bean + > ServerBuilderCustomizer metricsInterceptor( + ServerInterceptor observationGrpcServerInterceptor) { + return (serverBuilder) -> serverBuilder.intercept(observationGrpcServerInterceptor); + } + +} \ No newline at end of file diff --git a/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfigurationTests.java b/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfigurationTests.java new file mode 100644 index 0000000..2282beb --- /dev/null +++ b/spring-grpc-spring-boot-autoconfigure/src/test/java/org/springframework/grpc/autoconfigure/server/GrpcServerObservationAutoConfigurationTests.java @@ -0,0 +1,48 @@ +package org.springframework.grpc.autoconfigure.server; + +import io.grpc.ServerBuilder; +import io.grpc.ServerInterceptor; +import io.micrometer.observation.ObservationRegistry; +import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.grpc.server.ServerBuilderCustomizer; + +import static org.assertj.core.api.Assertions.assertThat; + +class GrpcServerObservationAutoConfigurationTests { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(GrpcServerObservationAutoConfiguration.class)); + + @Test + void whenObservationRegistryNotProvided_thenObservationInterceptorNotConfigured() { + this.contextRunner.run(context -> { + assertThat(context).doesNotHaveBean(ServerBuilderCustomizer.class); + }); + } + + @Test + void whenObservationInterceptorConfigured_thenServerBuilderCustomizerConfigured() { + this.contextRunner.withBean(ObservationRegistry.class, ObservationRegistry::create).run(context -> { + assertThat(context).hasSingleBean(ServerBuilderCustomizer.class); + assertThat(context).hasSingleBean(ServerInterceptor.class); + ServerInterceptor interceptor = context.getBean(ServerInterceptor.class); + ServerBuilderCustomizer customizer = context.getBean(ServerBuilderCustomizer.class); + ServerBuilder builder = org.mockito.Mockito.mock(ServerBuilder.class); + customizer.customize(builder); + org.mockito.Mockito.verify(builder, org.mockito.Mockito.times(1)).intercept(interceptor); + }); + } + + @Test + void whenObservationPropertyDisabled_thenServerBuilderCustomizerNotConfigured() { + this.contextRunner.withPropertyValues("spring.grpc.server.observation.enabled=false") + .withBean(ObservationRegistry.class, ObservationRegistry::create) + .run(context -> { + assertThat(context).doesNotHaveBean(ServerBuilderCustomizer.class); + assertThat(context).doesNotHaveBean(ServerInterceptor.class); + }); + } + +} \ No newline at end of file