[AB-353] reducing chance of concurrent modification exception when registering a new metric on the fly

This commit is contained in:
Sheldan
2021-12-25 10:53:55 +01:00
parent 9ce07a1a4a
commit cc898b27bb
2 changed files with 49 additions and 41 deletions

View File

@@ -33,9 +33,9 @@ public class JDAMetrics extends ListenerAdapter {
.tagList(Arrays.asList(MetricTag.getTag(EVENT_CLASS, eventName)))
.name(JDA_EVENT_METRIC)
.build();
log.info("Registering new metric for event {}. There are now {} metrics.", eventName, coveredEvents.size());
metricService.registerCounter(metric, "Events of type " + eventName);
coveredEvents.put(event.getClass(), metric);
log.info("Registering new metric for event {}. There are now {} metrics.", eventName, coveredEvents.size());
}
metricService.incrementCounter(coveredEvents.get(event.getClass()));
}

View File

@@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
@@ -15,14 +16,15 @@ import java.util.function.ToDoubleFunction;
@Slf4j
public class PrometheusMetricServiceBean implements MetricService {
private final List<Counter> counters = new ArrayList<>();
private final List<Gauge> gauges = new ArrayList<>();
private final List<Counter> counters = Collections.synchronizedList(new ArrayList<>());
private final List<Gauge> gauges = Collections.synchronizedList(new ArrayList<>());
@Autowired
private MeterRegistry registry;
@Override
public void registerCounter(CounterMetric metric, String description) {
synchronized (counters) {
if(doesCounterExist(metric)) {
throw new IllegalArgumentException("Counter metric already exists.");
}
@@ -36,6 +38,7 @@ public class PrometheusMetricServiceBean implements MetricService {
.register(registry);
counters.add(counter);
}
}
@Override
public void registerGauge(CounterMetric counterMetric, Supplier<Number> f, String help) {
@@ -44,11 +47,11 @@ public class PrometheusMetricServiceBean implements MetricService {
@Override
public void registerGauge(CounterMetric counterMetric, Supplier<Number> f, String help, String baseUnit) {
synchronized (gauges) {
List<Tag> micrometerTags = new ArrayList<>();
counterMetric.getTagList().forEach(metricTag ->
micrometerTags.add(Tag.of(metricTag.getKey(), metricTag.getValue()))
);
Gauge gauge = Gauge
.builder(counterMetric.getName(), f)
.tags(micrometerTags)
@@ -58,6 +61,8 @@ public class PrometheusMetricServiceBean implements MetricService {
gauges.add(gauge);
}
}
@Override
public <T> void registerGauge(CounterMetric counterMetric, T obj, ToDoubleFunction<T> f, String help) {
registerGauge(counterMetric, obj, f, help, null);
@@ -65,11 +70,11 @@ public class PrometheusMetricServiceBean implements MetricService {
@Override
public <T> void registerGauge(CounterMetric counterMetric, T obj, ToDoubleFunction<T> f, String help, String baseUnit) {
synchronized (gauges) {
List<Tag> micrometerTags = new ArrayList<>();
counterMetric.getTagList().forEach(metricTag ->
micrometerTags.add(Tag.of(metricTag.getKey(), metricTag.getValue()))
);
Gauge gauge = Gauge
.builder(counterMetric.getName(), obj, f)
.tags(micrometerTags)
@@ -78,6 +83,7 @@ public class PrometheusMetricServiceBean implements MetricService {
.register(registry);
gauges.add(gauge);
}
}
@Override
public void incrementCounter(CounterMetric counterMetric) {
@@ -86,12 +92,14 @@ public class PrometheusMetricServiceBean implements MetricService {
@Override
public void incrementCounter(CounterMetric counterMetric, Long amount) {
synchronized (counters) {
Optional<Counter> counterOptional = counters.stream().filter(counter -> compareCounterIdAndCounterMetric(counter.getId(), counterMetric)).findFirst();
counterOptional.ifPresent(counter -> counter.increment(amount));
if(!counterOptional.isPresent()) {
log.warn("Trying to increment counter {} with tags {}, which was not available (yet).", counterMetric.getName(), String.join(counterMetric.getTagList().toString()));
}
}
}
private boolean doesCounterExist(CounterMetric counterMetric) {
return counters.stream().anyMatch(counter -> compareCounterIdAndCounterMetric(counter.getId(), counterMetric));