This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-commons-metrics.git
commit 5fd7b2c8f5fb74083d431743620886e969113888 Author: Chetan Mehrotra <[email protected]> AuthorDate: Thu Nov 17 06:06:36 2016 +0000 SLING-5966 - Add Gauge support to metrics git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1770122 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/sling/commons/metrics/Gauge.java | 54 ++++++++++ .../commons/metrics/internal/GaugeManager.java | 119 +++++++++++++++++++++ .../metrics/internal/MetricsServiceImpl.java | 5 + .../apache/sling/commons/metrics/package-info.java | 2 +- .../metrics/internal/MetricServiceTest.java | 31 ++++++ 5 files changed, 210 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/sling/commons/metrics/Gauge.java b/src/main/java/org/apache/sling/commons/metrics/Gauge.java new file mode 100644 index 0000000..ac723a6 --- /dev/null +++ b/src/main/java/org/apache/sling/commons/metrics/Gauge.java @@ -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<String> queue = new ConcurrentLinkedQueue<String>(); + * final Gauge<Integer> queueDepth = new Gauge<Integer>() { + * 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 diff --git a/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java b/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java new file mode 100644 index 0000000..bc48066 --- /dev/null +++ b/src/main/java/org/apache/sling/commons/metrics/internal/GaugeManager.java @@ -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(); + } + } +} 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 03efcee..1bc6514 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 @@ -54,6 +54,7 @@ public class MetricsServiceImpl implements MetricsService { 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 implements MetricsService { 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 implements MetricsService { } regs.clear(); + gaugeManager.close(); + metrics.clear(); if (reporter != null) { 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 aa5623b..5b24541 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.0") +@Version("1.1.0") @Export(optional = "provide:=true") 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 72a8e02..a8af34a 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 @@ -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; + } + } + } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
