Skip to content

Commit 8132882

Browse files
authored
Enable gRPC Client attempt and Server metrics (#1039)
* add metrics ClientInterceptor and metrics ServerStreamTracer.Factory to auto-configuration
1 parent 45d71f9 commit 8132882

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

grpc-client-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/client/autoconfigure/GrpcClientMetricAutoConfiguration.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,17 @@
2222
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
2323
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2424
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
25+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
2526
import org.springframework.context.annotation.Configuration;
2627
import org.springframework.core.annotation.Order;
2728

29+
import com.google.common.base.Stopwatch;
30+
2831
import io.grpc.ClientInterceptor;
2932
import io.micrometer.core.instrument.MeterRegistry;
3033
import io.micrometer.core.instrument.binder.grpc.MetricCollectingClientInterceptor;
3134
import net.devh.boot.grpc.client.interceptor.GrpcGlobalClientInterceptor;
35+
import net.devh.boot.grpc.client.metrics.MetricsClientInterceptor;
3236
import net.devh.boot.grpc.common.util.InterceptorOrder;
3337

3438
/**
@@ -56,4 +60,18 @@ public MetricCollectingClientInterceptor metricCollectingClientInterceptor(final
5660
return new MetricCollectingClientInterceptor(registry);
5761
}
5862

63+
/**
64+
* Creates a {@link ClientInterceptor} that collects metrics about client attempts and client calls.
65+
*
66+
* @param registry The registry used to create the metrics.
67+
* @return The newly created MetricsClientInterceptor bean.
68+
*/
69+
@ConditionalOnProperty(prefix = "grpc", name = "metricsA66Enabled", matchIfMissing = true)
70+
@GrpcGlobalClientInterceptor
71+
@Order(InterceptorOrder.ORDER_TRACING_METRICS)
72+
@ConditionalOnMissingBean
73+
public MetricsClientInterceptor metricsClientInterceptor(final MeterRegistry registry) {
74+
return new MetricsClientInterceptor(registry, Stopwatch::createUnstarted);
75+
}
76+
5977
}

grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/autoconfigure/GrpcServerMetricAutoConfiguration.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,14 @@
3333
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
3434
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
3535
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
36+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
3637
import org.springframework.context.annotation.Bean;
3738
import org.springframework.context.annotation.Configuration;
3839
import org.springframework.context.annotation.Lazy;
3940
import org.springframework.core.annotation.Order;
4041

42+
import com.google.common.base.Stopwatch;
43+
4144
import io.grpc.BindableService;
4245
import io.grpc.MethodDescriptor;
4346
import io.grpc.ServiceDescriptor;
@@ -47,6 +50,8 @@
4750
import net.devh.boot.grpc.common.util.InterceptorOrder;
4851
import net.devh.boot.grpc.server.config.GrpcServerProperties;
4952
import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
53+
import net.devh.boot.grpc.server.metrics.MetricsServerStreamTracers;
54+
import net.devh.boot.grpc.server.serverfactory.GrpcServerConfigurer;
5055

5156
/**
5257
* Auto configuration class for Spring-Boot. This allows zero config server metrics for gRPC services.
@@ -75,6 +80,15 @@ public MetricCollectingServerInterceptor metricCollectingServerInterceptor(final
7580
return metricCollector;
7681
}
7782

83+
@ConditionalOnProperty(prefix = "grpc", name = "metricsA66Enabled", matchIfMissing = true)
84+
@Bean
85+
public GrpcServerConfigurer streamTracerFactoryConfigurer(final MeterRegistry registry) {
86+
MetricsServerStreamTracers metricsServerStreamTracers = new MetricsServerStreamTracers(
87+
Stopwatch::createUnstarted);
88+
return builder -> builder
89+
.addStreamTracerFactory(metricsServerStreamTracers.getMetricsServerTracerFactory(registry));
90+
}
91+
7892
@Bean
7993
@Lazy
8094
InfoContributor grpcInfoContributor(final GrpcServerProperties properties,
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2016-2023 The gRPC-Spring Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.devh.boot.grpc.test.interceptor;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
24+
import org.junit.jupiter.api.Test;
25+
import org.springframework.beans.factory.annotation.Autowired;
26+
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
27+
import org.springframework.boot.test.context.SpringBootTest;
28+
import org.springframework.context.ApplicationContext;
29+
import org.springframework.test.annotation.DirtiesContext;
30+
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
31+
32+
import io.grpc.ClientInterceptor;
33+
import io.micrometer.core.instrument.binder.grpc.MetricCollectingClientInterceptor;
34+
import io.micrometer.core.instrument.binder.grpc.ObservationGrpcClientInterceptor;
35+
import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
36+
import net.devh.boot.grpc.client.interceptor.GlobalClientInterceptorRegistry;
37+
import net.devh.boot.grpc.client.metrics.MetricsClientInterceptor;
38+
39+
@SpringBootTest
40+
@SpringJUnitConfig(classes = {GrpcClientAutoConfiguration.class})
41+
@EnableAutoConfiguration
42+
@DirtiesContext
43+
public class DefaultClientInterceptorTest {
44+
45+
@Autowired
46+
private ApplicationContext applicationContext;
47+
48+
@Autowired
49+
private GlobalClientInterceptorRegistry registry;
50+
51+
@Test
52+
void testDefaultInterceptors() {
53+
final List<ClientInterceptor> expected = new ArrayList<>();
54+
expected.add(this.applicationContext.getBean(MetricCollectingClientInterceptor.class));
55+
expected.add(this.applicationContext.getBean(MetricsClientInterceptor.class));
56+
expected.add(this.applicationContext.getBean(ObservationGrpcClientInterceptor.class));
57+
58+
final List<ClientInterceptor> actual = new ArrayList<>(this.registry.getClientInterceptors());
59+
assertThat(actual).containsExactlyInAnyOrderElementsOf(expected);
60+
}
61+
}

0 commit comments

Comments
 (0)