Skip to content

Commit

Permalink
fixes #559
Browse files Browse the repository at this point in the history
WebReactiveOptions support metrics
  • Loading branch information
skarpenko committed Apr 7, 2023
1 parent 8417772 commit 296ab24
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@
<artifactId>awaitility</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@
package reactivefeign.spring.config;

import com.github.tomakehurst.wiremock.WireMockServer;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Metrics;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
Expand All @@ -37,11 +43,18 @@

import java.util.Collections;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static reactivefeign.spring.config.WebClientCustomizerTest.MOCK_SERVER_PORT_PROPERTY;
import static reactor.netty.Metrics.ACTIVE_CONNECTIONS;
import static reactor.netty.Metrics.CONNECTION_PROVIDER_PREFIX;
import static reactor.netty.Metrics.DATA_SENT;
import static reactor.netty.Metrics.HTTP_CLIENT_PREFIX;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ReactiveFeignClientUsingPropertiesTests.Application.class, webEnvironment = WebEnvironment.NONE)
Expand Down Expand Up @@ -69,6 +82,8 @@ public class ReactiveFeignClientUsingPropertiesTests {
@Autowired
private MultipleDefaultQueryClient multipleSingleDefaultQueryClient;

private static final MeterRegistry meterRegistry = new SimpleMeterRegistry();

@BeforeClass
public static void setupStubs() {

Expand All @@ -82,6 +97,10 @@ public static void setupStubs() {
.withFixedDelay(1000)
.withBody("OK")));

mockHttpServer.stubFor(get(urlEqualTo("/barMetered"))
.willReturn(aResponse()
.withBody("OK")));

mockHttpServer.stubFor(get(urlEqualTo("/header"))
.withHeader("header", equalTo("value"))
.willReturn(aResponse().withBody("OK")));
Expand All @@ -100,6 +119,13 @@ public static void setupStubs() {
mockHttpServer.start();

System.setProperty(MOCK_SERVER_PORT_PROPERTY, Integer.toString(mockHttpServer.port()));

Metrics.addRegistry(meterRegistry);
}

@BeforeEach
public void beforeTest(){
meterRegistry.clear();
}

@Test
Expand Down Expand Up @@ -138,6 +164,23 @@ public void testBar() {
fail("it should timeout");
}

@Test
public void testBarMetered() {

String response = barClient.barMetered()
.doOnNext(s -> {
Metrics.globalRegistry.forEachMeter(meter -> {
Gauge activeConnections = meterRegistry.find(CONNECTION_PROVIDER_PREFIX + ACTIVE_CONNECTIONS).gauge();
assertEquals(activeConnections.value(), 1., 0.);
DistributionSummary dataSent = meterRegistry.find(HTTP_CLIENT_PREFIX + DATA_SENT).summary();
assertEquals(dataSent.count(), 1);
});
})
.block();

assertEquals("OK", response);
}

@ReactiveFeignClient(name = "foo", url = "http://localhost:${" + MOCK_SERVER_PORT_PROPERTY+"}")
protected interface FooClient {

Expand All @@ -150,6 +193,9 @@ protected interface BarClient {

@RequestMapping(method = RequestMethod.GET, value = "/bar")
Mono<String> bar();

@RequestMapping(method = RequestMethod.GET, value = "/barMetered")
Mono<String> barMetered();
}

@ReactiveFeignClient(name = "header", url = "http://localhost:${" + MOCK_SERVER_PORT_PROPERTY+"}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ reactive.feign.client.config.queries.defaultQueryParameters[query2]=value2


reactive.feign.client.config.bar.options.connectTimeoutMillis=500
reactive.feign.client.config.bar.options.readTimeoutMillis=500
reactive.feign.client.config.bar.options.readTimeoutMillis=500
reactive.feign.client.config.bar.options.connectionMetricsEnabled=true
reactive.feign.client.config.bar.options.metricsEnabled=true
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import static java.lang.Boolean.TRUE;
import static reactor.netty.resources.LoopResources.DEFAULT_NATIVE;

class NettyClientHttpConnectorBuilder {
Expand All @@ -40,6 +42,9 @@ public static ClientHttpConnector buildNettyClientHttpConnector(HttpClient httpC
}

ConnectionProvider.Builder connectionProviderBuilder = connectionProvider.mutate();
if(webOptions.getConnectionMetricsEnabled() != null){
connectionProviderBuilder = connectionProviderBuilder.metrics(webOptions.getConnectionMetricsEnabled());
}
if (webOptions.getMaxConnections() != null) {
connectionProviderBuilder = connectionProviderBuilder.maxConnections(webOptions.getMaxConnections());
}
Expand All @@ -65,6 +70,10 @@ public static ClientHttpConnector buildNettyClientHttpConnector(HttpClient httpC
.runOn(HttpResources.get(), DEFAULT_NATIVE);
}

if(webOptions.getMetricsEnabled() != null){
httpClient = httpClient.metrics(webOptions.getMetricsEnabled(), Function.identity());
}

if (webOptions.getConnectTimeoutMillis() != null) {
httpClient = httpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
webOptions.getConnectTimeoutMillis().intValue());
Expand Down Expand Up @@ -110,7 +119,7 @@ public static ClientHttpConnector buildNettyClientHttpConnector(HttpClient httpC
if(webOptions.getSslContext() != null){
httpClient = httpClient.secure(sslProviderBuilder -> sslProviderBuilder.sslContext(webOptions.getSslContext()));
}
else if (Objects.equals(Boolean.TRUE, webOptions.isDisableSslValidation())) {
else if (Objects.equals(TRUE, webOptions.isDisableSslValidation())) {
try {
SslContext sslContext = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ public class WebReactiveOptions extends ReactiveOptions {
private final Long responseTimeoutMillis;
private final SslContext sslContext;
private final Boolean disableSslValidation;
private final Boolean metricsEnabled;

private final ConnectionProvider connectionProvider;
private final Integer maxConnections;
private final Boolean connectionMetricsEnabled;
private final Long connectionMaxIdleTimeMillis;
private final Long connectionMaxLifeTimeMillis;
private final Integer pendingAcquireMaxCount;
Expand All @@ -47,8 +49,9 @@ private WebReactiveOptions(Boolean useHttp2, Long connectTimeoutMillis,
Boolean tryUseCompression, Boolean followRedirects,
ProxySettings proxySettings,
SslContext sslContext, Boolean disableSslValidation,
Boolean metricsEnabled,
ConnectionProvider connectionProvider,
Integer maxConnections,
Integer maxConnections, Boolean connectionMetricsEnabled,
Long connectionMaxIdleTimeMillis, Long connectionMaxLifeTimeMillis,
Integer pendingAcquireMaxCount, Long pendingAcquireTimeoutMillis) {
super(useHttp2, connectTimeoutMillis, tryUseCompression, followRedirects, proxySettings);
Expand All @@ -58,8 +61,10 @@ private WebReactiveOptions(Boolean useHttp2, Long connectTimeoutMillis,
this.responseTimeoutMillis = responseTimeoutMillis;
this.sslContext = sslContext;
this.disableSslValidation = disableSslValidation;
this.metricsEnabled = metricsEnabled;
this.connectionProvider = connectionProvider;
this.maxConnections = maxConnections;
this.connectionMetricsEnabled = connectionMetricsEnabled;
this.connectionMaxIdleTimeMillis = connectionMaxIdleTimeMillis;
this.connectionMaxLifeTimeMillis = connectionMaxLifeTimeMillis;
this.pendingAcquireMaxCount = pendingAcquireMaxCount;
Expand Down Expand Up @@ -90,6 +95,10 @@ public SslContext getSslContext() {
return sslContext;
}

public Boolean getMetricsEnabled() {
return metricsEnabled;
}

public ConnectionProvider getConnectionProvider() {
return connectionProvider;
}
Expand All @@ -98,6 +107,10 @@ public Integer getMaxConnections() {
return maxConnections;
}

public Boolean getConnectionMetricsEnabled() {
return connectionMetricsEnabled;
}

public Long getConnectionMaxIdleTimeMillis() {
return connectionMaxIdleTimeMillis;
}
Expand All @@ -120,8 +133,10 @@ public static class Builder extends ReactiveOptions.Builder {
private Long responseTimeoutMillis;
private Boolean disableSslValidation;
private SslContext sslContext;
private Boolean metricsEnabled;
private ConnectionProvider connectionProvider;
private Integer maxConnections;
private Boolean connectionMetricsEnabled;
private Long connectionMaxIdleTimeMillis;
private Long connectionMaxLifeTimeMillis;
private Integer pendingAcquireMaxCount;
Expand Down Expand Up @@ -154,6 +169,21 @@ public Builder setSslContext(SslContext sslContext) {
return this;
}

public Builder setMetricsEnabled(Boolean metricsEnabled) {
this.metricsEnabled = metricsEnabled;
return this;
}

public Builder setConnectionProvider(ConnectionProvider connectionProvider) {
this.connectionProvider = connectionProvider;
return this;
}

public Builder setConnectionMetricsEnabled(Boolean connectionMetricsEnabled) {
this.connectionMetricsEnabled = connectionMetricsEnabled;
return this;
}

public Builder setMaxConnections(Integer maxConnections) {
this.maxConnections = maxConnections;
return this;
Expand Down Expand Up @@ -184,8 +214,10 @@ public WebReactiveOptions build() {
readTimeoutMillis, writeTimeoutMillis, responseTimeoutMillis,
acceptCompressed, followRedirects, proxySettings,
sslContext, disableSslValidation,
metricsEnabled,
connectionProvider,
maxConnections, connectionMaxIdleTimeMillis, connectionMaxLifeTimeMillis,
maxConnections, connectionMetricsEnabled,
connectionMaxIdleTimeMillis, connectionMaxLifeTimeMillis,
pendingAcquireMaxCount, pendingAcquireTimeoutMillis);
}
}
Expand Down

0 comments on commit 296ab24

Please sign in to comment.