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-prometheus.git

commit a5e7da1050de13667d99466fbeca7a5144c71d4d
Author: Robert Munteanu <romb...@apache.org>
AuthorDate: Thu Aug 1 18:27:50 2019 +0300

    Initial version of org.apache.sling.commons.metrics.prometheus
---
 pom.xml                                            |  72 ++++++++
 .../prometheus/impl/WrapperMetricsServlet.java     | 193 +++++++++++++++++++++
 2 files changed, 265 insertions(+)

diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..c63b950
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling-bundle-parent</artifactId>
+        <version>35</version>
+        <relativePath />
+    </parent>
+    <artifactId>org.apache.sling.commons.metrics.prometheus</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <name>Apache Sling Commons Prometheus Metrics Exporter</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>biz.aQute.bnd</groupId>
+                <artifactId>bnd-baseline-maven-plugin</artifactId>
+                <configuration>
+                    <failOnMissing>false</failOnMissing>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.5</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <version>7.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <version>7.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.prometheus</groupId>
+            <artifactId>simpleclient_servlet</artifactId>
+            <version>0.0.23</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.prometheus</groupId>
+            <artifactId>simpleclient_dropwizard</artifactId>
+            <version>0.0.23</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git 
a/src/main/java/org/apache/sling/metrics/prometheus/impl/WrapperMetricsServlet.java
 
b/src/main/java/org/apache/sling/metrics/prometheus/impl/WrapperMetricsServlet.java
new file mode 100644
index 0000000..0394744
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/metrics/prometheus/impl/WrapperMetricsServlet.java
@@ -0,0 +1,193 @@
+/*
+ * 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.metrics.prometheus.impl;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+import 
org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardContextSelect;
+import 
org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardServletPattern;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.Metric;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.MetricRegistryListener;
+import com.codahale.metrics.Timer;
+
+import io.prometheus.client.CollectorRegistry;
+import io.prometheus.client.dropwizard.DropwizardExports;
+import io.prometheus.client.exporter.MetricsServlet;
+
+@HttpWhiteboardServletPattern("/metrics")
+@HttpWhiteboardContextSelect("(osgi.http.whiteboard.context.name=org.osgi.service.http)")
+@Component(service = Servlet.class)
+public class WrapperMetricsServlet extends MetricsServlet {
+
+    private static final long serialVersionUID = 1L;
+    
+    private final MetricRegistry metrics = new MetricRegistry();
+    @SuppressWarnings("squid:S2226")
+    private DropwizardExports exports;
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    
+    private final ConcurrentMap<MetricRegistry, CopyMetricRegistryListener> 
childRegistries = new ConcurrentHashMap<>();
+
+    @Override
+    public void init() throws ServletException {
+        super.init();
+        this.exports = new DropwizardExports(metrics);
+        CollectorRegistry.defaultRegistry.register(this.exports);
+    }
+    
+    @Override
+    public void destroy() {
+        CollectorRegistry.defaultRegistry.unregister(this.exports);
+        super.destroy();
+    }
+
+    @Reference(service = MetricRegistry.class, cardinality = 
ReferenceCardinality.MULTIPLE,
+            policy = ReferencePolicy.DYNAMIC, policyOption = 
ReferencePolicyOption.GREEDY)
+    void bindMetricRegistry(MetricRegistry metricRegistry, Map<String, Object> 
properties) {
+        
+        log.info("Binding Metrics Registry...");
+        
+        String name = registryName(metricRegistry, properties);
+        
+        CopyMetricRegistryListener listener = new 
CopyMetricRegistryListener(this.metrics, metricRegistry, name);
+        listener.start();
+        childRegistries.put(metricRegistry, listener);
+        log.info("Bound Metrics Registry {} ", name);
+    }
+
+    void unbindMetricRegistry(MetricRegistry metricRegistry, Map<String, 
Object> properties) {
+        String name = registryName(metricRegistry, properties);
+        
+        CopyMetricRegistryListener metricRegistryListener = 
childRegistries.remove(metricRegistry);
+        if (metricRegistryListener != null)
+            metricRegistryListener.stop();
+        log.info("Unbound Metrics Registry {} ", name);
+    }
+
+    private String registryName(MetricRegistry metricRegistry, Map<String, 
Object> properties) {
+        String name = (String) properties.get("name");
+        if (name == null)
+            name = metricRegistry.toString();
+        return name;
+    }
+    
+    static class CopyMetricRegistryListener implements MetricRegistryListener {
+
+        private MetricRegistry parent;
+        private MetricRegistry child;
+        private String name;
+
+        public CopyMetricRegistryListener(MetricRegistry parent, 
MetricRegistry child, String name) {
+            this.parent = parent;
+            this.child = child;
+            this.name = name;
+        }
+        
+        public void start() {
+            child.addListener(this);
+        }
+        
+        public void stop() {
+            child.removeListener(this);
+            child.getMetrics().keySet().stream()
+                .map( this::getMetricName )
+                .forEach( this::removeMetric );
+        }
+
+        @Override
+        public void onGaugeAdded(String name, Gauge<?> gauge) {
+            addMetric(name, gauge);
+            
+        }
+
+        @Override
+        public void onGaugeRemoved(String name) {
+            removeMetric(name);
+            
+        }
+
+        @Override
+        public void onCounterAdded(String name, Counter counter) {
+            addMetric(name, counter);
+        }
+
+        @Override
+        public void onCounterRemoved(String name) {
+            removeMetric(name);
+        }
+
+        @Override
+        public void onHistogramAdded(String name, Histogram histogram) {
+            addMetric(name, histogram);
+        }
+
+        @Override
+        public void onHistogramRemoved(String name) {
+            removeMetric(name);
+        }
+
+        @Override
+        public void onMeterAdded(String name, Meter meter) {
+            addMetric(name, meter);
+        }
+
+        @Override
+        public void onMeterRemoved(String name) {
+            removeMetric(name);
+        }
+
+        @Override
+        public void onTimerAdded(String name, Timer timer) {
+            addMetric(name, timer);
+        }
+
+        @Override
+        public void onTimerRemoved(String name) {
+            removeMetric(name);
+        }
+
+        private void addMetric(String metricName, Metric m) {
+            parent.register(getMetricName(metricName), m);
+        }
+
+        private void removeMetric(String metricName) {
+            parent.remove(getMetricName(metricName));
+        }
+
+        private String getMetricName(String metricName) {
+            return name + "_" + metricName;
+        }
+    }
+}

Reply via email to