SLING-10967 add support to register Gauges directly without whiteboard support (#1)
SLING-10967 add support to register Gauges directly without whiteboard support
diff --git a/src/main/java/org/apache/sling/commons/metrics/Gauge.java b/src/main/java/org/apache/sling/commons/metrics/Gauge.java
index 9813120..c7cae12 100644
--- a/src/main/java/org/apache/sling/commons/metrics/Gauge.java
+++ b/src/main/java/org/apache/sling/commons/metrics/Gauge.java
@@ -23,7 +23,16 @@
import org.osgi.annotation.versioning.ConsumerType;
/**
- * A gauge metric is an instantaneous reading of a particular value. To instrument a queue's depth,
+ * A gauge metric is an instantaneous reading of a particular value.
+ *
+ * Since package version 1.3.0 a gauge can directly created via the MetricsService {@see MetricsService#gauge(String,Supplier<T>)},
+ * which should be used for the majority of cases.
+ *
+ * <p> Nevertheless it's still possible to register a gauge instance with OSGi ServiceRegistry with {@code Gauge#NAME} set
+ * to Gauge name. Then the Gauge instance would be registered with MetricService via the whiteboard
+ * pattern.
+ *
+ * To instrument a queue's depth,
* for example:<br>
* <pre><code>
* final Queue<String> queue = new ConcurrentLinkedQueue<String>();
@@ -34,9 +43,7 @@
* };
* </code></pre>
*
- * <p> A Gauge instance should be registered with OSGi ServiceRegistry with {@code Gauge#NAME} set
- * to Gauge name. Then the Gauge instance would be registered with MetricService via whiteboard
- * pattern
+
*
* @param <T> the type of the metric's value
*/
diff --git a/src/main/java/org/apache/sling/commons/metrics/MetricsService.java b/src/main/java/org/apache/sling/commons/metrics/MetricsService.java
index 5bf4eae..d6548de 100644
--- a/src/main/java/org/apache/sling/commons/metrics/MetricsService.java
+++ b/src/main/java/org/apache/sling/commons/metrics/MetricsService.java
@@ -20,6 +20,8 @@
package org.apache.sling.commons.metrics;
+import java.util.function.Supplier;
+
import org.osgi.annotation.versioning.ProviderType;
/**
@@ -56,6 +58,11 @@
public <A> A adaptTo(Class<A> type) {
return null;
}
+
+ @Override
+ public <T> Gauge<T> gauge(String name, Supplier<T> supplier) {
+ return null;
+ }
};
/**
@@ -95,6 +102,15 @@
Meter meter(String name);
/**
+ * Creates a new {@link Gauge} and registers it under the given name.
+ * If a gauge with teh same exists already the the same instance is returned.
+ * @param name the name of the gauge
+ * @param supplier provides the values which are returned by the gauge
+ * @return the gauge
+ */
+ <T> Gauge<T> gauge(String name, Supplier<T> supplier);
+
+ /**
* Adapts the service to the specified type. This can be used to
* get instance to underlying {@code MetricRegistry}
*
@@ -104,4 +120,5 @@
* or null if this metric cannot be adapted to the specified type.
*/
<A> A adaptTo(Class<A> type);
+
}
diff --git a/src/main/java/org/apache/sling/commons/metrics/internal/GaugeImpl.java b/src/main/java/org/apache/sling/commons/metrics/internal/GaugeImpl.java
new file mode 100644
index 0000000..7ad069e
--- /dev/null
+++ b/src/main/java/org/apache/sling/commons/metrics/internal/GaugeImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.commons.metrics.internal;
+
+
+import org.apache.sling.commons.metrics.Gauge;
+import org.apache.sling.commons.metrics.Metric;
+
+public class GaugeImpl<T> implements Gauge<T>, Metric {
+
+ com.codahale.metrics.Gauge<T> gauge;
+
+ public GaugeImpl(com.codahale.metrics.Gauge<T> g) {
+ this.gauge = g;
+ }
+
+ @Override
+ public <A> A adaptTo(Class<A> type) {
+ if (type == com.codahale.metrics.Gauge.class){
+ return (A) gauge;
+ }
+ return null;
+ }
+
+ @Override
+ public T getValue() {
+ return this.gauge.getValue();
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/commons/metrics/internal/InternalMetricsServiceFactory.java b/src/main/java/org/apache/sling/commons/metrics/internal/InternalMetricsServiceFactory.java
index c3f7fff..5411df8 100644
--- a/src/main/java/org/apache/sling/commons/metrics/internal/InternalMetricsServiceFactory.java
+++ b/src/main/java/org/apache/sling/commons/metrics/internal/InternalMetricsServiceFactory.java
@@ -22,8 +22,10 @@
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Supplier;
import org.apache.sling.commons.metrics.Counter;
+import org.apache.sling.commons.metrics.Gauge;
import org.apache.sling.commons.metrics.Histogram;
import org.apache.sling.commons.metrics.Meter;
import org.apache.sling.commons.metrics.MetricsService;
@@ -98,5 +100,12 @@
metricsMapper.addMapping(name, bundle);
registeredNames.add(name);
}
+
+ @Override
+ public <T> Gauge<T> gauge(String name, Supplier<T> supplier) {
+ addMapping(name);
+ return delegate.gauge(name, supplier);
+ }
+
}
}
diff --git a/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java b/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java
index 094c51a..e9c00ed 100644
--- a/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java
+++ b/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java
@@ -28,15 +28,19 @@
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.function.Supplier;
import javax.management.MBeanServer;
import com.codahale.metrics.JmxReporter;
import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.MetricRegistry.MetricSupplier;
+
import org.apache.sling.commons.metrics.Meter;
import org.apache.sling.commons.metrics.MetricsService;
import org.apache.sling.commons.metrics.Timer;
import org.apache.sling.commons.metrics.Counter;
+import org.apache.sling.commons.metrics.Gauge;
import org.apache.sling.commons.metrics.Histogram;
import org.apache.sling.commons.metrics.Metric;
import org.osgi.framework.BundleContext;
@@ -121,6 +125,10 @@
return getOrAdd(name, MetricBuilder.METERS);
}
+ public <T> Gauge<T> gauge(String name, Supplier<T> supplier) {
+ return getOrAddGauge(name,supplier);
+ }
+
@SuppressWarnings("unchecked")
@Override
public <A> A adaptTo(Class<A> type) {
@@ -156,6 +164,24 @@
throw new IllegalArgumentException(name + " is already used for a different type of metric");
}
+ @SuppressWarnings("unchecked")
+ private <T> Gauge<T> getOrAddGauge(String name, Supplier<T> supplier) {
+ final Metric metric = metrics.get(name);
+ if (metric instanceof Gauge<?>) {
+ return (Gauge<T>) metric;
+ } else {
+ try {
+ return registerGauge(name,supplier);
+ } catch (IllegalArgumentException e) {
+ final Metric added = metrics.get(name);
+ if (added instanceof Gauge<?>) {
+ return (Gauge<T>) added;
+ }
+ }
+ }
+ throw new IllegalArgumentException(name + " is already used for a different type of metric");
+ }
+
private <T extends Metric> T register(String name, T metric) throws IllegalArgumentException {
final Metric existing = metrics.putIfAbsent(name, metric);
if (existing != null) {
@@ -164,6 +190,18 @@
return metric;
}
+ private <T> Gauge<T> registerGauge(String name, Supplier<T> supplier) {
+ com.codahale.metrics.Gauge<T> codahaleGauge = supplier::get;
+ @SuppressWarnings("rawtypes")
+ MetricSupplier<com.codahale.metrics.Gauge> metricSupplier = () -> codahaleGauge;
+
+ @SuppressWarnings("unchecked")
+ com.codahale.metrics.Gauge<T> g = registry.gauge(name, metricSupplier);
+ GaugeImpl<T> gauge = new GaugeImpl<>(g);
+ metrics.put(name, gauge);
+ return gauge;
+ }
+
/**
* A quick and easy way of capturing the notion of default metrics.
*/
diff --git a/src/main/java/org/apache/sling/commons/metrics/package-info.java b/src/main/java/org/apache/sling/commons/metrics/package-info.java
index 0fa4a33..13586eb 100644
--- a/src/main/java/org/apache/sling/commons/metrics/package-info.java
+++ b/src/main/java/org/apache/sling/commons/metrics/package-info.java
@@ -22,7 +22,7 @@
*
* @version 1.0
*/
-@Version("1.2.0")
+@Version("1.3.0")
package org.apache.sling.commons.metrics;
diff --git a/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java b/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java
index a8af34a..b412e50 100644
--- a/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java
+++ b/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java
@@ -22,6 +22,7 @@
import java.lang.management.ManagementFactory;
import java.util.Collections;
import java.util.Set;
+import java.util.function.Supplier;
import javax.management.MBeanServer;
import javax.management.ObjectName;
@@ -126,6 +127,19 @@
assertSame(histo, service.histogram("test"));
}
+ @Test
+ public void gaugeRegistration () throws Exception{
+ activate();
+ Gauge<Long> gauge = service.gauge("gauge",() -> 42L);
+ assertNotNull(gauge);
+ assertTrue(getRegistry().getGauges().containsKey("gauge"));
+ assertEquals(new Long(42L),gauge.getValue());
+
+ // Just the name matters, not the supplier
+ Gauge<?> gauge2 = service.gauge("gauge", () -> 43L);
+ assertSame(gauge, gauge2);
+ }
+
@Test(expected = IllegalArgumentException.class)
public void sameNameDifferentTypeMetric() throws Exception{
activate();
@@ -151,7 +165,7 @@
}
@Test
- public void gaugeRegistration() throws Exception{
+ public void gaugeRegistrationViaWhiteboard() throws Exception{
activate();
ServiceRegistration<Gauge> reg = context.bundleContext().registerService(Gauge.class, new TestGauge(42),
MapUtil.toDictionary(Gauge.NAME, "foo"));