You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2019/09/04 12:43:08 UTC
[sling-whiteboard] 01/02: Initial version of
org.apache.sling.commons.metrics.prometheus
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-whiteboard.git
commit 26a5c1e82d78f8021e045d198d0d90018d37cac3
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Thu Aug 1 18:27:50 2019 +0300
Initial version of org.apache.sling.commons.metrics.prometheus
---
metrics-prometheus/pom.xml | 72 ++++++++
.../prometheus/impl/WrapperMetricsServlet.java | 193 +++++++++++++++++++++
2 files changed, 265 insertions(+)
diff --git a/metrics-prometheus/pom.xml b/metrics-prometheus/pom.xml
new file mode 100644
index 0000000..c63b950
--- /dev/null
+++ b/metrics-prometheus/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/metrics-prometheus/src/main/java/org/apache/sling/metrics/prometheus/impl/WrapperMetricsServlet.java b/metrics-prometheus/src/main/java/org/apache/sling/metrics/prometheus/impl/WrapperMetricsServlet.java
new file mode 100644
index 0000000..0394744
--- /dev/null
+++ b/metrics-prometheus/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;
+ }
+ }
+}