Skip to content

Commit

Permalink
Fix possible NPE if code creates a REST client 'early'; also tidy up …
Browse files Browse the repository at this point in the history
…a few other things (helidon-io#9554)
  • Loading branch information
tjquinno authored and arjav-desai committed Dec 11, 2024
1 parent 19ca736 commit 025c657
Showing 1 changed file with 14 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
Expand All @@ -39,7 +41,6 @@
import jakarta.enterprise.inject.spi.AfterBeanDiscovery;
import jakarta.enterprise.inject.spi.AnnotatedMethod;
import jakarta.enterprise.inject.spi.AnnotatedType;
import jakarta.enterprise.inject.spi.BeforeBeanDiscovery;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessAnnotatedType;
import jakarta.enterprise.inject.spi.WithAnnotations;
Expand Down Expand Up @@ -84,6 +85,10 @@ public class RestClientMetricsCdiExtension implements Extension {

private final Map<Class<?>, Map<Method, Set<Registration>>> registrations = new HashMap<>();

// Some code might create REST clients before CDI announces that app-scoped beans are initialized.
// We record those "early" REST clients and set up metrics for them only when we are ready.
private final Collection<Class<?>> deferredRestClients = new ConcurrentLinkedQueue<>();

private MetricRegistry metricRegistry;

/**
Expand All @@ -92,10 +97,6 @@ public class RestClientMetricsCdiExtension implements Extension {
public RestClientMetricsCdiExtension() {
}

void checkForMpMetrics(@Observes BeforeBeanDiscovery bbd) {

}

void recordRestClientTypes(@Observes @WithAnnotations({OPTIONS.class,
HEAD.class,
GET.class,
Expand Down Expand Up @@ -218,20 +219,25 @@ void prepareMetricRegistrations(@Observes AfterBeanDiscovery abd) {
void ready(@Observes @Initialized(ApplicationScoped.class) Object event,
MetricRegistry metricRegistry) {
this.metricRegistry = metricRegistry;
deferredRestClients.forEach(this::registerMetricsForRestClient);
deferredRestClients.clear();
}

void registerMetricsForRestClient(Class<?> restClient) {
if (metricRegistry == null) {
deferredRestClients.add(restClient);
return;
}
registrations.get(restClient).forEach((method, regs) -> {
List<Metric> metricsRegisteredForRestClient = LOGGER.isLoggable(DEBUG) ? new ArrayList<>() : null;
regs.forEach(registration -> {
Metric metric = registration.registrationOp.apply(metricRegistry);
if (LOGGER.isLoggable(DEBUG)) {
if (metricsRegisteredForRestClient != null) {
metricsRegisteredForRestClient.add(metric);
LOGGER.log(DEBUG, String.format("For REST client method %s#%s registering metric using %s",
restClient.getCanonicalName(),
method.getName(),
registration,
metric));
registration));
}
metricsUpdateWorkByMethod.computeIfAbsent(method, k -> new ArrayList<>())
.add(MetricsUpdateWork.create(metric));
Expand Down

0 comments on commit 025c657

Please sign in to comment.