You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by jo...@apache.org on 2022/01/11 18:11:20 UTC

[sling-org-apache-sling-commons-metrics] branch master updated: SLING-10967 add support to register Gauges directly without whiteboard support (#1)

This is an automated email from the ASF dual-hosted git repository.

joerghoh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-metrics.git


The following commit(s) were added to refs/heads/master by this push:
     new 6697f95  SLING-10967 add support to register Gauges directly without whiteboard support (#1)
6697f95 is described below

commit 6697f957c18368f15e539b2e594142f24df0d6cd
Author: Jörg Hoh <jo...@users.noreply.github.com>
AuthorDate: Tue Jan 11 19:11:13 2022 +0100

    SLING-10967 add support to register Gauges directly without whiteboard support (#1)
    
    SLING-10967 add support to register Gauges directly without whiteboard support
---
 .../org/apache/sling/commons/metrics/Gauge.java    | 15 ++++++---
 .../sling/commons/metrics/MetricsService.java      | 17 ++++++++++
 .../{package-info.java => internal/GaugeImpl.java} | 34 ++++++++++++++-----
 .../internal/InternalMetricsServiceFactory.java    |  9 +++++
 .../metrics/internal/MetricsServiceImpl.java       | 38 ++++++++++++++++++++++
 .../apache/sling/commons/metrics/package-info.java |  2 +-
 .../metrics/internal/MetricServiceTest.java        | 16 ++++++++-
 7 files changed, 117 insertions(+), 14 deletions(-)

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 @@ package org.apache.sling.commons.metrics;
 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&lt;String&gt; queue = new ConcurrentLinkedQueue&lt;String&gt;();
@@ -34,9 +43,7 @@ import org.osgi.annotation.versioning.ConsumerType;
  * };
  * </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 interface MetricsService {
         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 @@ public interface MetricsService {
     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 @@ public interface MetricsService {
      * 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/package-info.java b/src/main/java/org/apache/sling/commons/metrics/internal/GaugeImpl.java
similarity index 57%
copy from src/main/java/org/apache/sling/commons/metrics/package-info.java
copy to src/main/java/org/apache/sling/commons/metrics/internal/GaugeImpl.java
index 0fa4a33..7ad069e 100644
--- a/src/main/java/org/apache/sling/commons/metrics/package-info.java
+++ b/src/main/java/org/apache/sling/commons/metrics/internal/GaugeImpl.java
@@ -17,13 +17,31 @@
  * under the License.
  */
 
-/**
- * Provides an API to generate and collect metrics in various forms
- *
- * @version 1.0
- */
-@Version("1.2.0")
-package org.apache.sling.commons.metrics;
+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();
+    }
 
-import org.osgi.annotation.versioning.Version;
\ No newline at end of file
+}
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 @@ package org.apache.sling.commons.metrics.internal;
 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 @@ class InternalMetricsServiceFactory implements ServiceFactory<MetricsService> {
             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.List;
 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 @@ public class MetricsServiceImpl implements MetricsService {
         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 @@ public class MetricsServiceImpl implements MetricsService {
         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 @@ public class MetricsServiceImpl implements MetricsService {
         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 @@ package org.apache.sling.commons.metrics.internal;
 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 @@ public class MetricServiceTest {
         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 @@ public class MetricServiceTest {
     }
 
     @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"));