You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ch...@apache.org on 2016/11/17 06:06:36 UTC

svn commit: r1770122 - in /sling/trunk/bundles/commons/metrics/src: main/java/org/apache/sling/commons/metrics/ main/java/org/apache/sling/commons/metrics/internal/ test/java/org/apache/sling/commons/metrics/internal/

Author: chetanm
Date: Thu Nov 17 06:06:36 2016
New Revision: 1770122

URL: http://svn.apache.org/viewvc?rev=1770122&view=rev
Log:
SLING-5966 - Add Gauge support to metrics

Added:
    sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/Gauge.java   (with props)
    sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java   (with props)
Modified:
    sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java
    sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/package-info.java
    sling/trunk/bundles/commons/metrics/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java

Added: sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/Gauge.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/Gauge.java?rev=1770122&view=auto
==============================================================================
--- sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/Gauge.java (added)
+++ sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/Gauge.java Thu Nov 17 06:06:36 2016
@@ -0,0 +1,54 @@
+/*
+ * 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;
+
+import aQute.bnd.annotation.ConsumerType;
+
+/**
+ * A gauge metric is an instantaneous reading of a particular value. To instrument a queue's depth,
+ * for example:<br>
+ * <pre><code>
+ * final Queue&lt;String&gt; queue = new ConcurrentLinkedQueue&lt;String&gt;();
+ * final Gauge&lt;Integer&gt; queueDepth = new Gauge&lt;Integer&gt;() {
+ *     public Integer getValue() {
+ *         return queue.size();
+ *     }
+ * };
+ * </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
+ */
+@ConsumerType
+public interface Gauge<T> {
+    /**
+     * Service property name which determines the name of the Gauge
+     */
+    String NAME = "name";
+    /**
+     * Returns the metric's current value.
+     *
+     * @return the metric's current value
+     */
+    T getValue();
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/Gauge.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java?rev=1770122&view=auto
==============================================================================
--- sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java (added)
+++ sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java Thu Nov 17 06:06:36 2016
@@ -0,0 +1,119 @@
+/*
+ * 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 java.io.Closeable;
+import java.util.Collections;
+
+import com.codahale.metrics.MetricRegistry;
+import org.apache.sling.commons.metrics.Gauge;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class GaugeManager implements ServiceTrackerCustomizer<Gauge, GaugeManager.GaugeImpl>, Closeable {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final MetricRegistry registry;
+    private final BundleMetricsMapper mapper;
+    private final BundleContext bundleContext;
+    private ServiceTracker<Gauge, GaugeImpl> tracker;
+
+    public GaugeManager(BundleContext context, MetricRegistry registry, BundleMetricsMapper mapper) {
+        this.registry = registry;
+        this.mapper = mapper;
+        this.bundleContext = context;
+        this.tracker = new ServiceTracker<>(context, Gauge.class, this);
+        tracker.open();
+    }
+
+    //~-------------------------------------< ServiceTrackerCustomizer >
+
+    @Override
+    public GaugeImpl addingService(ServiceReference<Gauge> reference) {
+        String name = (String) reference.getProperty(Gauge.NAME);
+        if (name == null){
+            log.warn("A {} service is registered without [{}] property. This Gauge would not be " +
+                    "registered with MetricsRegistry", reference, Gauge.NAME);
+            return null;
+        }
+
+        Gauge gauge = bundleContext.getService(reference);
+        GaugeImpl gaugeImpl = new GaugeImpl(name, gauge);
+        register(reference, gaugeImpl);
+        return gaugeImpl;
+    }
+
+    @Override
+    public void modifiedService(ServiceReference<Gauge> reference, GaugeImpl service) {
+        String name = (String) reference.getProperty(Gauge.NAME);
+        if (name == null){
+            return;
+        }
+
+        if (!name.equals(service.name)){
+            unregister(service);
+            service.name = name;
+            register(reference, service);
+        }
+    }
+
+    @Override
+    public void removedService(ServiceReference<Gauge> reference, GaugeImpl service) {
+        unregister(service);
+    }
+
+    //~------------------------------------< Closeable >
+
+    @Override
+    public void close() {
+        tracker.close();
+    }
+
+    //~-------------------------------------< Internal >
+
+    private void unregister(GaugeImpl service) {
+        mapper.unregister(Collections.singleton(service.name));
+    }
+
+    private void register(ServiceReference<Gauge> reference, GaugeImpl gaugeImpl) {
+        mapper.addMapping(gaugeImpl.name, reference.getBundle());
+        registry.register(gaugeImpl.name, gaugeImpl);
+    }
+
+    //~--------------------------------------< GaugeImpl >
+
+    public static class GaugeImpl implements com.codahale.metrics.Gauge {
+        String name;
+        final Gauge gauge;
+
+        public GaugeImpl(String name, Gauge gauge) {
+            this.name = name;
+            this.gauge = gauge;
+        }
+
+        @Override
+        public Object getValue() {
+            return gauge.getValue();
+        }
+    }
+}

Propchange: sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java?rev=1770122&r1=1770121&r2=1770122&view=diff
==============================================================================
--- sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java (original)
+++ sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/internal/MetricsServiceImpl.java Thu Nov 17 06:06:36 2016
@@ -54,6 +54,7 @@ public class MetricsServiceImpl implemen
     private final ConcurrentMap<String, Metric> metrics = new ConcurrentHashMap<>();
     private final MetricRegistry registry = new MetricRegistry();
     private final BundleMetricsMapper metricsMapper = new BundleMetricsMapper(registry);
+    private GaugeManager gaugeManager;
 
     @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
     private MBeanServer server;
@@ -64,6 +65,8 @@ public class MetricsServiceImpl implemen
     private void activate(BundleContext context, Map<String, Object> config) {
         enableJMXReporter();
 
+        gaugeManager = new GaugeManager(context, registry, metricsMapper);
+
         final Dictionary<String, String> svcProps = new Hashtable<>();
         svcProps.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Metrics Service");
         svcProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
@@ -84,6 +87,8 @@ public class MetricsServiceImpl implemen
         }
         regs.clear();
 
+        gaugeManager.close();
+
         metrics.clear();
 
         if (reporter != null) {

Modified: sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/package-info.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/package-info.java?rev=1770122&r1=1770121&r2=1770122&view=diff
==============================================================================
--- sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/package-info.java (original)
+++ sling/trunk/bundles/commons/metrics/src/main/java/org/apache/sling/commons/metrics/package-info.java Thu Nov 17 06:06:36 2016
@@ -22,7 +22,7 @@
  *
  * @version 1.0
  */
-@Version("1.0")
+@Version("1.1.0")
 @Export(optional = "provide:=true")
 package org.apache.sling.commons.metrics;
 

Modified: sling/trunk/bundles/commons/metrics/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/metrics/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java?rev=1770122&r1=1770121&r2=1770122&view=diff
==============================================================================
--- sling/trunk/bundles/commons/metrics/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java (original)
+++ sling/trunk/bundles/commons/metrics/src/test/java/org/apache/sling/commons/metrics/internal/MetricServiceTest.java Thu Nov 17 06:06:36 2016
@@ -31,20 +31,25 @@ import javax.management.QueryExp;
 import com.codahale.metrics.JmxReporter;
 import com.codahale.metrics.MetricRegistry;
 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;
 import org.apache.sling.commons.metrics.Timer;
+import org.apache.sling.testing.mock.osgi.MapUtil;
 import org.apache.sling.testing.mock.osgi.MockOsgi;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
 import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
+import org.osgi.framework.ServiceRegistration;
 
 import static org.apache.sling.commons.metrics.internal.BundleMetricsMapper.JMX_TYPE_METRICS;
 import static org.hamcrest.Matchers.empty;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
@@ -145,6 +150,19 @@ public class MetricServiceTest {
 
     }
 
+    @Test
+    public void gaugeRegistration() throws Exception{
+        activate();
+        ServiceRegistration<Gauge> reg = context.bundleContext().registerService(Gauge.class, new TestGauge(42),
+                MapUtil.toDictionary(Gauge.NAME, "foo"));
+
+        assertTrue(getRegistry().getGauges().containsKey("foo"));
+        assertEquals(42, getRegistry().getGauges().get("foo").getValue());
+
+        reg.unregister();
+        assertFalse(getRegistry().getGauges().containsKey("foo"));
+    }
+
     private MetricRegistry getRegistry(){
         return context.getService(MetricRegistry.class);
     }
@@ -153,4 +171,17 @@ public class MetricServiceTest {
         MockOsgi.activate(service, context.bundleContext(), Collections.<String, Object>emptyMap());
     }
 
+    private static class TestGauge implements Gauge {
+        int value;
+
+        public TestGauge(int value){
+            this.value = value;
+        }
+
+        @Override
+        public Object getValue() {
+            return value;
+        }
+    }
+
 }