Skip to content

Commit

Permalink
Switching to injectable factories per bootique/bootique#345
Browse files Browse the repository at this point in the history
  • Loading branch information
andrus committed Dec 9, 2023
1 parent 67335cf commit 91e7a23
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,29 +21,48 @@
import com.codahale.metrics.MetricRegistry;
import io.bootique.annotation.BQConfig;
import io.bootique.annotation.BQConfigProperty;
import io.bootique.di.Injector;
import io.bootique.jersey.client.HttpClientFactoryFactory;
import io.bootique.jersey.client.JerseyClientFeatures;
import io.bootique.jersey.client.instrumented.mdc.MDCAwareClientAsyncExecutorProvider;
import jakarta.ws.rs.core.Feature;
import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.spi.ConnectorProvider;

import javax.inject.Inject;
import java.util.Set;

/**
* @since 3.0
*/
@BQConfig
public class InstrumentedHttpClientFactoryFactory extends HttpClientFactoryFactory {

private final MetricRegistry metricRegistry;

private JerseyClientHealthChecksFactory health;

@Inject
public InstrumentedHttpClientFactoryFactory(
Injector injector,
@JerseyClientFeatures Set<Feature> features,
ConnectorProvider connectorProvider,
MetricRegistry metricRegistry) {
super(injector, features, connectorProvider);
this.metricRegistry = metricRegistry;
}

@BQConfigProperty("Configures client healthcheck thresholds")
public void setHealth(JerseyClientHealthChecksFactory health) {
this.health = health;
}

public JerseyClientHealthChecks createHealthChecks(MetricRegistry metricRegistry) {
return getHealth().createHealthChecks(metricRegistry);
public JerseyClientHealthChecks createHealthChecks() {
return getHealth().createHealthChecks();
}

private JerseyClientHealthChecksFactory getHealth() {
return health != null ? health : new JerseyClientHealthChecksFactory();
return health != null ? health : new JerseyClientHealthChecksFactory(metricRegistry);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,46 @@
import io.bootique.metrics.health.check.ValueRange;
import io.bootique.metrics.health.check.ValueRangeCheck;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

@BQConfig
public class JerseyClientHealthChecksFactory {

public static final String REQUESTS_PER_MIN_CHECK = JerseyClientInstrumentedModule
public static final String REQUESTS_PER_MIN_CHECK = JerseyClientInstrumentedModule
.METRIC_NAMING
.name("Requests", "PerMin");

private final MetricRegistry metricRegistry;

private DoubleRangeFactory requestsPerMin;

@Inject
public JerseyClientHealthChecksFactory(MetricRegistry metricRegistry) {
this.metricRegistry = metricRegistry;
}

@BQConfigProperty
public void setRequestsPerMin(DoubleRangeFactory requestsPerMin) {
this.requestsPerMin = requestsPerMin;
}

public JerseyClientHealthChecks createHealthChecks(MetricRegistry metricRegistry) {
return new JerseyClientHealthChecks(createHealthChecksMap(metricRegistry));
public JerseyClientHealthChecks createHealthChecks() {
return new JerseyClientHealthChecks(createHealthChecksMap());
}

protected Map<String, HealthCheck> createHealthChecksMap(MetricRegistry registry) {
protected Map<String, HealthCheck> createHealthChecksMap() {
Map<String, HealthCheck> checks = new HashMap<>(3);
checks.put(REQUESTS_PER_MIN_CHECK, createTimeRequestsCheck(registry));
checks.put(REQUESTS_PER_MIN_CHECK, createTimeRequestsCheck());
return checks;
}

private HealthCheck createTimeRequestsCheck(MetricRegistry registry) {
private HealthCheck createTimeRequestsCheck() {
ValueRange<Double> range = getRequestsPerMin();
Supplier<Double> deferredGauge = ()
-> registry.timer(RequestTimer.TIMER_NAME).getOneMinuteRate();
-> metricRegistry.timer(RequestTimer.TIMER_NAME).getOneMinuteRate();

return new ValueRangeCheck<>(range, deferredGauge);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ InstrumentedHttpClientFactoryFactory providerInstrumentedHttpClientFactoryFactor

@Provides
@Singleton
JerseyClientHealthChecks provideThresholdHealthCheck(InstrumentedHttpClientFactoryFactory factory, MetricRegistry metricRegistry) {
return factory.createHealthChecks(metricRegistry);
JerseyClientHealthChecks provideThresholdHealthCheck(InstrumentedHttpClientFactoryFactory factory) {
return factory.createHealthChecks();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,13 @@
import io.bootique.jetty.server.ServerHolder;
import io.bootique.junit5.BQApp;
import io.bootique.junit5.BQTest;
import io.bootique.junit5.BQTestFactory;
import io.bootique.junit5.BQTestTool;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Collection;
Expand All @@ -63,10 +60,9 @@ public class InstrumentedClientIT {
.module(jetty.moduleReplacingConnectors())
.createRuntime();

@BQTestTool
final BQTestFactory testFactory = new BQTestFactory();

BQRuntime client;
// important to recreate the client app before every test as it starts with zero metrics counters
@BQApp(skipRun = true)
final BQRuntime client = Bootique.app().autoLoadModules().createRuntime();

private static String getUrlBadPort(String getUrl) {
ServerHolder serverHolder = server.getInstance(ServerHolder.class);
Expand All @@ -75,12 +71,6 @@ private static String getUrlBadPort(String getUrl) {
return getUrl.replace(":" + goodPort, ":" + badPort);
}

@BeforeEach
public void resetClient() {
// important to recreate the client app before every test as it starts with zero metrics counters
client = testFactory.app().autoLoadModules().createRuntime();
}

@Test
public void metrics() {
// fault filter to init metrics
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
package io.bootique.jersey.client.instrumented;

import com.codahale.metrics.MetricRegistry;
import io.bootique.di.Injector;
import io.bootique.jersey.client.ClientAsyncExecutorProvider;
import io.bootique.jersey.client.instrumented.mdc.MDCAwareClientAsyncExecutorProvider;
Expand All @@ -38,8 +39,11 @@ public class InstrumentedHttpClientFactoryFactoryTest {
@Test
public void createClientFactory_AsyncThreadPool() {

Client client = new InstrumentedHttpClientFactoryFactory()
.createClientFactory(mockInjector, Set.of(), new HttpUrlConnectorProvider()).newClient();
Client client = new InstrumentedHttpClientFactoryFactory(
mockInjector,
Set.of(),
new HttpUrlConnectorProvider(),
mock(MetricRegistry.class)).createClientFactory().newClient();

try {
assertTrue(client.getConfiguration().isRegistered(MDCAwareClientAsyncExecutorProvider.class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class RangeHealthCheckTest {
@BeforeEach
public void before() {
this.registry = Mockito.mock(MetricRegistry.class);
this.healthCheckFactory = new JerseyClientHealthChecksFactory();
this.healthCheckFactory = new JerseyClientHealthChecksFactory(registry);
DoubleRangeFactory timeRequestsThresholds = new DoubleRangeFactory();
timeRequestsThresholds.setCritical(0.05);
timeRequestsThresholds.setWarning(0.01);
Expand All @@ -33,7 +33,7 @@ public void before() {

Mockito.when(registry.timer(RequestTimer.TIMER_NAME)).thenReturn(Mockito.mock(Timer.class));

JerseyClientHealthChecks rangeHealthCheck = healthCheckFactory.createHealthChecks(registry);
JerseyClientHealthChecks rangeHealthCheck = healthCheckFactory.createHealthChecks();
this.healthCheckRegistry = new HealthCheckRegistry(rangeHealthCheck.getHealthChecks());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.glassfish.jersey.message.GZipEncoder;

import javax.inject.Inject;
import java.security.KeyStore;
import java.util.Collections;
import java.util.HashMap;
Expand All @@ -48,6 +49,10 @@
@BQConfig("Configures HttpClientFactory, including named authenticators, timeouts, SSL certificates, etc.")
public class HttpClientFactoryFactory {

private final Injector injector;
private final Set<Feature> features;
private final ConnectorProvider connectorProvider;

protected boolean followRedirects;
protected boolean compression;
protected int readTimeoutMs;
Expand All @@ -57,7 +62,16 @@ public class HttpClientFactoryFactory {
protected Map<String, TrustStoreFactory> trustStores;
protected Map<String, WebTargetFactory> targets;

public HttpClientFactoryFactory() {
@Inject
public HttpClientFactoryFactory(
Injector injector,
@JerseyClientFeatures Set<Feature> features,
ConnectorProvider connectorProvider) {

this.injector = injector;
this.features = features;
this.connectorProvider = connectorProvider;

this.followRedirects = true;
this.compression = true;
}
Expand Down Expand Up @@ -130,10 +144,7 @@ public HttpTargets createTargets(HttpClientFactory clientFactory) {
return new DefaultHttpTargets(createNamedTargets(clientFactory));
}

public HttpClientFactory createClientFactory(
Injector injector,
Set<Feature> features,
ConnectorProvider connectorProvider) {
public HttpClientFactory createClientFactory() {

ClientConfig config = createConfig(features, connectorProvider);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@
import io.bootique.di.Injector;
import io.bootique.di.Key;
import io.bootique.di.Provides;
import jakarta.ws.rs.core.Feature;
import org.glassfish.jersey.client.HttpUrlConnectorProvider;
import org.glassfish.jersey.client.spi.ConnectorProvider;

import javax.inject.Singleton;
import java.util.Set;

public class JerseyClientModule implements BQModule {

Expand Down Expand Up @@ -77,13 +75,8 @@ HttpClientFactoryFactory provideClientFactoryFactory(ConfigurationFactory config

@Provides
@Singleton
HttpClientFactory provideClientFactory(
HttpClientFactoryFactory factoryFactory,
Injector injector,
@JerseyClientFeatures Set<Feature> features,
ConnectorProvider connectorProvider) {

return factoryFactory.createClientFactory(injector, features, connectorProvider);
HttpClientFactory provideClientFactory(HttpClientFactoryFactory factoryFactory) {
return factoryFactory.createClientFactory();
}

@Provides
Expand Down
Loading

0 comments on commit 91e7a23

Please sign in to comment.