Skip to content

Commit

Permalink
Make metric providers properly lazy
Browse files Browse the repository at this point in the history
This commit turns injection of metric registries in metric providers
into a lazy variant (`Provider<>`), and turns field injection into
constructor injection. This is all to make `CompoundMetricsProvider`
work properly in case some of the metric providers actually cannot
function properly, because the respective dependencies do not exist.
  • Loading branch information
Ladicek committed Oct 25, 2024
1 parent cc34c43 commit b42db12
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
@Alternative
@Priority(1)
public class CompoundMetricsProvider implements MetricsProvider {
@Inject
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true")
boolean metricsEnabled;

private final Map<Object, MetricsRecorder> cache = new ConcurrentHashMap<>();
private final boolean metricsEnabled;

private final MetricsProvider[] providers;

CompoundMetricsProvider() {
private final Map<Object, MetricsRecorder> cache = new ConcurrentHashMap<>();

@Inject
CompoundMetricsProvider(
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true") boolean metricsEnabled) {
CDI<Object> cdi = CDI.current();
List<Class<? extends MetricsProvider>> allProviders = List.of(MicroProfileMetricsProvider.class,
OpenTelemetryProvider.class, MicrometerProvider.class);
Expand All @@ -42,9 +42,10 @@ public class CompoundMetricsProvider implements MetricsProvider {
try {
providers.add(cdi.select(clazz).get());
} catch (Exception ignored) {
// either the bean does not exist, or some of its dependencies are not injectable
// either the bean does not exist, or some of its dependencies does not exist
}
}
this.metricsEnabled = providers.isEmpty() ? false : metricsEnabled;
this.providers = providers.toArray(new MetricsProvider[0]);
}

Expand All @@ -57,6 +58,10 @@ public boolean isEnabled() {
public MetricsRecorder create(MeteredOperation operation) {
if (metricsEnabled) {
return cache.computeIfAbsent(operation.cacheKey(), ignored -> {
if (providers.length == 1) {
return providers[0].create(operation);
}

MetricsRecorder[] recorders = new MetricsRecorder[providers.length];
for (int i = 0; i < providers.length; i++) {
recorders[i] = providers[i].create(operation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;

import org.eclipse.microprofile.config.inject.ConfigProperty;
Expand All @@ -24,31 +24,27 @@

@Singleton
public class MicroProfileMetricsProvider implements MetricsProvider {
@Inject
@RegistryType(type = MetricRegistry.Type.BASE)
MetricRegistry registry;

@Inject
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true")
boolean metricsEnabled;
private final boolean metricsEnabled;

@Inject
ExecutorHolder executorHolder;
private final MetricRegistry registry;

private final Map<Object, MetricsRecorder> cache = new ConcurrentHashMap<>();

@PostConstruct
void init() {
if (!metricsEnabled) {
return;
}
@Inject
MicroProfileMetricsProvider(
// lazy for `CompoundMetricsProvider`
@RegistryType(type = MetricRegistry.Type.BASE) Provider<MetricRegistry> registry,
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true") boolean metricsEnabled,
ExecutorHolder executorHolder) {
this.metricsEnabled = metricsEnabled;
this.registry = registry.get();

Metadata metadata = Metadata.builder()
.withName(MetricsConstants.TIMER_SCHEDULED)
.withUnit(MetricUnits.NONE)
.build();
Timer timer = executorHolder.getTimer();
registry.gauge(metadata, timer, Timer::countScheduledTasks, new Tag("id", "" + timer.getId()));
this.registry.gauge(metadata, timer, Timer::countScheduledTasks, new Tag("id", "" + timer.getId()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;

import org.eclipse.microprofile.config.inject.ConfigProperty;
Expand All @@ -22,26 +22,23 @@

@Singleton
public class MicrometerProvider implements MetricsProvider {
@Inject
MeterRegistry registry;

@Inject
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true")
boolean metricsEnabled;
private final boolean metricsEnabled;

@Inject
ExecutorHolder executorHolder;
private final MeterRegistry registry;

private final Map<Object, MetricsRecorder> cache = new ConcurrentHashMap<>();

@PostConstruct
void init() {
if (!metricsEnabled) {
return;
}
@Inject
MicrometerProvider(
// lazy for `CompoundMetricsProvider`
Provider<MeterRegistry> registry,
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true") boolean metricsEnabled,
ExecutorHolder executorHolder) {
this.metricsEnabled = metricsEnabled;
this.registry = registry.get();

Timer timer = executorHolder.getTimer();
registry.gauge(MetricsConstants.TIMER_SCHEDULED, Collections.singletonList(Tag.of("id", "" + timer.getId())),
this.registry.gauge(MetricsConstants.TIMER_SCHEDULED, Collections.singletonList(Tag.of("id", "" + timer.getId())),
timer, Timer::countScheduledTasks);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import jakarta.annotation.PostConstruct;
import jakarta.inject.Inject;
import jakarta.inject.Provider;
import jakarta.inject.Singleton;

import org.eclipse.microprofile.config.inject.ConfigProperty;
Expand All @@ -22,27 +22,24 @@

@Singleton
public class OpenTelemetryProvider implements MetricsProvider {
@Inject
Meter meter;

@Inject
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true")
boolean metricsEnabled;
private final boolean metricsEnabled;

@Inject
ExecutorHolder executorHolder;
private final Meter meter;

private final Map<Object, MetricsRecorder> cache = new ConcurrentHashMap<>();

@PostConstruct
void init() {
if (!metricsEnabled) {
return;
}
@Inject
OpenTelemetryProvider(
// lazy for `CompoundMetricsProvider`
Provider<Meter> meter,
@ConfigProperty(name = "MP_Fault_Tolerance_Metrics_Enabled", defaultValue = "true") boolean metricsEnabled,
ExecutorHolder executorHolder) {
this.metricsEnabled = metricsEnabled;
this.meter = meter.get();

Timer timer = executorHolder.getTimer();
Attributes attributes = Attributes.of(AttributeKey.stringKey("id"), "" + timer.getId());
meter.upDownCounterBuilder(MetricsConstants.TIMER_SCHEDULED)
this.meter.upDownCounterBuilder(MetricsConstants.TIMER_SCHEDULED)
.buildWithCallback(m -> m.record(timer.countScheduledTasks(), attributes));
}

Expand Down

0 comments on commit b42db12

Please sign in to comment.