Skip to content

Commit 61b1323

Browse files
hmtangonobc
authored andcommitted
Auto-configure Micrometer Observations
This commit auto-configures in the Micrometer Observations API and its Observation server interceptor. Resolves #1 Signed-off-by: Sunny <[email protected]>
1 parent c56784f commit 61b1323

File tree

4 files changed

+98
-0
lines changed

4 files changed

+98
-0
lines changed

spring-grpc-dependencies/pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
<grpc.version>1.63.2</grpc.version>
5555
<protobuf-java.version>3.25.5</protobuf-java.version>
5656
<google-common-protos.version>2.46.0</google-common-protos.version>
57+
<micrometer.version>1.13.6</micrometer.version>
5758
</properties>
5859

5960
<dependencyManagement>
@@ -112,6 +113,13 @@
112113
<artifactId>proto-google-common-protos</artifactId>
113114
<version>${google-common-protos.version}</version>
114115
</dependency>
116+
<dependency>
117+
<groupId>io.micrometer</groupId>
118+
<artifactId>micrometer-bom</artifactId>
119+
<version>${micrometer.version}</version>
120+
<type>pom</type>
121+
<scope>import</scope>
122+
</dependency>
115123
</dependencies>
116124
</dependencyManagement>
117125

spring-grpc-spring-boot-autoconfigure/pom.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@
7575
<artifactId>spring-boot-starter</artifactId>
7676
<scope>provided</scope>
7777
</dependency>
78+
<dependency>
79+
<groupId>io.micrometer</groupId>
80+
<artifactId>micrometer-observation</artifactId>
81+
<optional>true</optional>
82+
</dependency>
83+
<dependency>
84+
<groupId>io.micrometer</groupId>
85+
<artifactId>micrometer-core</artifactId>
86+
<optional>true</optional>
87+
</dependency>
7888

7989
<!-- test dependencies -->
8090
<dependency>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.springframework.grpc.autoconfigure.server;
2+
3+
import io.grpc.ServerBuilder;
4+
import io.grpc.ServerInterceptor;
5+
import io.micrometer.core.instrument.binder.grpc.ObservationGrpcServerInterceptor;
6+
import io.micrometer.observation.ObservationRegistry;
7+
import org.springframework.boot.autoconfigure.AutoConfiguration;
8+
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
9+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
10+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
11+
import org.springframework.context.annotation.Bean;
12+
import org.springframework.grpc.server.ServerBuilderCustomizer;
13+
14+
@AutoConfiguration(
15+
afterName = "org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration")
16+
@ConditionalOnClass(value = { ObservationRegistry.class, ObservationGrpcServerInterceptor.class })
17+
@ConditionalOnBean(ObservationRegistry.class)
18+
@ConditionalOnProperty(value = "spring.grpc.server.observation.enabled", matchIfMissing = true)
19+
public class GrpcServerObservationAutoConfiguration {
20+
21+
@Bean
22+
public ServerInterceptor observationGrpcServerInterceptor(ObservationRegistry observationRegistry) {
23+
return new ObservationGrpcServerInterceptor(observationRegistry);
24+
}
25+
26+
@Bean
27+
<T extends ServerBuilder<T>> ServerBuilderCustomizer<T> metricsInterceptor(
28+
ServerInterceptor observationGrpcServerInterceptor) {
29+
return (serverBuilder) -> serverBuilder.intercept(observationGrpcServerInterceptor);
30+
}
31+
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.springframework.grpc.autoconfigure.server;
2+
3+
import io.grpc.ServerBuilder;
4+
import io.grpc.ServerInterceptor;
5+
import io.micrometer.observation.ObservationRegistry;
6+
import org.junit.jupiter.api.Test;
7+
import org.springframework.boot.autoconfigure.AutoConfigurations;
8+
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
9+
import org.springframework.grpc.server.ServerBuilderCustomizer;
10+
11+
import static org.assertj.core.api.Assertions.assertThat;
12+
13+
class GrpcServerObservationAutoConfigurationTests {
14+
15+
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
16+
.withConfiguration(AutoConfigurations.of(GrpcServerObservationAutoConfiguration.class));
17+
18+
@Test
19+
void whenObservationRegistryNotProvided_thenObservationInterceptorNotConfigured() {
20+
this.contextRunner.run(context -> {
21+
assertThat(context).doesNotHaveBean(ServerBuilderCustomizer.class);
22+
});
23+
}
24+
25+
@Test
26+
void whenObservationInterceptorConfigured_thenServerBuilderCustomizerConfigured() {
27+
this.contextRunner.withBean(ObservationRegistry.class, ObservationRegistry::create).run(context -> {
28+
assertThat(context).hasSingleBean(ServerBuilderCustomizer.class);
29+
assertThat(context).hasSingleBean(ServerInterceptor.class);
30+
ServerInterceptor interceptor = context.getBean(ServerInterceptor.class);
31+
ServerBuilderCustomizer customizer = context.getBean(ServerBuilderCustomizer.class);
32+
ServerBuilder<?> builder = org.mockito.Mockito.mock(ServerBuilder.class);
33+
customizer.customize(builder);
34+
org.mockito.Mockito.verify(builder, org.mockito.Mockito.times(1)).intercept(interceptor);
35+
});
36+
}
37+
38+
@Test
39+
void whenObservationPropertyDisabled_thenServerBuilderCustomizerNotConfigured() {
40+
this.contextRunner.withPropertyValues("spring.grpc.server.observation.enabled=false")
41+
.withBean(ObservationRegistry.class, ObservationRegistry::create)
42+
.run(context -> {
43+
assertThat(context).doesNotHaveBean(ServerBuilderCustomizer.class);
44+
assertThat(context).doesNotHaveBean(ServerInterceptor.class);
45+
});
46+
}
47+
48+
}

0 commit comments

Comments
 (0)