diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java index a3d9856ff7..45b3beb063 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServices.java @@ -46,12 +46,14 @@ import com.codahale.metrics.Timer; * * * @author Dave Syer + * @author Jay Anderson + * @author Andy Wilkinson */ public class DropwizardMetricServices implements CounterService, GaugeService { private final MetricRegistry registry; - private final ConcurrentMap gaugeLocks = new ConcurrentHashMap(); + private final ConcurrentMap gauges = new ConcurrentHashMap(); private final ConcurrentHashMap names = new ConcurrentHashMap(); @@ -99,15 +101,22 @@ public class DropwizardMetricServices implements CounterService, GaugeService { } else { name = wrapGaugeName(name); - final double gauge = value; - // Ensure we synchronize to avoid another thread pre-empting this thread after - // remove causing an error in Dropwizard metrics - // NOTE: Dropwizard provides no way to do this atomically - synchronized (getGaugeLock(name)) { - this.registry.remove(name); - this.registry.register(name, new SimpleGauge(gauge)); + setGaugeValue(name, value); + } + } + + private void setGaugeValue(String name, double value) { + // NOTE: Dropwizard provides no way to do this atomically + SimpleGauge gauge = this.gauges.get(name); + if (gauge == null) { + SimpleGauge newGauge = new SimpleGauge(value); + gauge = this.gauges.putIfAbsent(name, newGauge); + if (gauge == null) { + this.registry.register(name, newGauge); + return; } } + gauge.setValue(value); } private String wrapGaugeName(String metricName) { @@ -130,16 +139,6 @@ public class DropwizardMetricServices implements CounterService, GaugeService { return name; } - private Object getGaugeLock(String name) { - Object lock = this.gaugeLocks.get(name); - if (lock == null) { - Object newLock = new Object(); - lock = this.gaugeLocks.putIfAbsent(name, newLock); - lock = (lock == null ? newLock : lock); - } - return lock; - } - @Override public void reset(String name) { if (!name.startsWith("meter")) { @@ -153,7 +152,7 @@ public class DropwizardMetricServices implements CounterService, GaugeService { */ private final static class SimpleGauge implements Gauge { - private final double value; + private volatile double value; private SimpleGauge(double value) { this.value = value; @@ -163,6 +162,10 @@ public class DropwizardMetricServices implements CounterService, GaugeService { public Double getValue() { return this.value; } + + public void setValue(double value) { + this.value = value; + } } } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java index 0666a59642..4e7aadd091 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/dropwizard/DropwizardMetricServicesTests.java @@ -65,9 +65,10 @@ public class DropwizardMetricServicesTests { @Test public void setGauge() { this.writer.submit("foo", 2.1); - this.writer.submit("foo", 2.3); @SuppressWarnings("unchecked") Gauge gauge = (Gauge) this.registry.getMetrics().get("gauge.foo"); + assertEquals(new Double(2.1), gauge.getValue()); + this.writer.submit("foo", 2.3); assertEquals(new Double(2.3), gauge.getValue()); }