Skip to content

Commit

Permalink
Enable gRPC Client attempt and Server metrics (#1039)
Browse files Browse the repository at this point in the history
* add metrics ClientInterceptor and metrics ServerStreamTracer.Factory to auto-configuration
  • Loading branch information
DNVindhya authored Jan 30, 2024
1 parent 45d71f9 commit 8132882
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@
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.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import com.google.common.base.Stopwatch;

import io.grpc.ClientInterceptor;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.grpc.MetricCollectingClientInterceptor;
import net.devh.boot.grpc.client.interceptor.GrpcGlobalClientInterceptor;
import net.devh.boot.grpc.client.metrics.MetricsClientInterceptor;
import net.devh.boot.grpc.common.util.InterceptorOrder;

/**
Expand Down Expand Up @@ -56,4 +60,18 @@ public MetricCollectingClientInterceptor metricCollectingClientInterceptor(final
return new MetricCollectingClientInterceptor(registry);
}

/**
* Creates a {@link ClientInterceptor} that collects metrics about client attempts and client calls.
*
* @param registry The registry used to create the metrics.
* @return The newly created MetricsClientInterceptor bean.
*/
@ConditionalOnProperty(prefix = "grpc", name = "metricsA66Enabled", matchIfMissing = true)
@GrpcGlobalClientInterceptor
@Order(InterceptorOrder.ORDER_TRACING_METRICS)
@ConditionalOnMissingBean
public MetricsClientInterceptor metricsClientInterceptor(final MeterRegistry registry) {
return new MetricsClientInterceptor(registry, Stopwatch::createUnstarted);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@
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.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;

import com.google.common.base.Stopwatch;

import io.grpc.BindableService;
import io.grpc.MethodDescriptor;
import io.grpc.ServiceDescriptor;
Expand All @@ -47,6 +50,8 @@
import net.devh.boot.grpc.common.util.InterceptorOrder;
import net.devh.boot.grpc.server.config.GrpcServerProperties;
import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor;
import net.devh.boot.grpc.server.metrics.MetricsServerStreamTracers;
import net.devh.boot.grpc.server.serverfactory.GrpcServerConfigurer;

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

@ConditionalOnProperty(prefix = "grpc", name = "metricsA66Enabled", matchIfMissing = true)
@Bean
public GrpcServerConfigurer streamTracerFactoryConfigurer(final MeterRegistry registry) {
MetricsServerStreamTracers metricsServerStreamTracers = new MetricsServerStreamTracers(
Stopwatch::createUnstarted);
return builder -> builder
.addStreamTracerFactory(metricsServerStreamTracers.getMetricsServerTracerFactory(registry));
}

@Bean
@Lazy
InfoContributor grpcInfoContributor(final GrpcServerProperties properties,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2016-2023 The gRPC-Spring 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
*
* http://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 net.devh.boot.grpc.test.interceptor;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.ArrayList;
import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;

import io.grpc.ClientInterceptor;
import io.micrometer.core.instrument.binder.grpc.MetricCollectingClientInterceptor;
import io.micrometer.core.instrument.binder.grpc.ObservationGrpcClientInterceptor;
import net.devh.boot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
import net.devh.boot.grpc.client.interceptor.GlobalClientInterceptorRegistry;
import net.devh.boot.grpc.client.metrics.MetricsClientInterceptor;

@SpringBootTest
@SpringJUnitConfig(classes = {GrpcClientAutoConfiguration.class})
@EnableAutoConfiguration
@DirtiesContext
public class DefaultClientInterceptorTest {

@Autowired
private ApplicationContext applicationContext;

@Autowired
private GlobalClientInterceptorRegistry registry;

@Test
void testDefaultInterceptors() {
final List<ClientInterceptor> expected = new ArrayList<>();
expected.add(this.applicationContext.getBean(MetricCollectingClientInterceptor.class));
expected.add(this.applicationContext.getBean(MetricsClientInterceptor.class));
expected.add(this.applicationContext.getBean(ObservationGrpcClientInterceptor.class));

final List<ClientInterceptor> actual = new ArrayList<>(this.registry.getClientInterceptors());
assertThat(actual).containsExactlyInAnyOrderElementsOf(expected);
}
}

0 comments on commit 8132882

Please sign in to comment.