You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by GitBox <gi...@apache.org> on 2020/09/21 06:03:48 UTC

[GitHub] [druid] Tiaaa opened a new pull request #10412: prometheus metric exporter

Tiaaa opened a new pull request #10412:
URL: https://github.com/apache/druid/pull/10412


   <!-- Thanks for trying to help us make Apache Druid be the best it can be! Please fill out as much of the following information as is possible (where relevant, and remove it when irrelevant) to help make the intention and scope of this PR clear in order to ease review. -->
   
   Fixes #8621 
   
   <!-- Replace XXXX with the id of the issue fixed in this PR. Remove this section if there is no corresponding issue. Don't reference the issue in the title of this pull-request. -->
   
   <!-- If you are a committer, follow the PR action item checklist for committers:
   https://github.com/apache/druid/blob/master/dev/committer-instructions.md#pr-and-issue-action-item-checklist-for-committers. -->
   
   
   Adds a new extension prometheus-emitter to expose Druid metrics for collection directly by a Prometheus server.
   
   
   <!-- Describe the goal of this PR, what problem are you fixing. If there is a corresponding issue (referenced above), it's not necessary to repeat the description here, however, you may choose to keep one summary sentence. -->
   
   <!-- Describe your patch: what did you change in code? How did you fix the problem? -->
   
   <!-- If there are several relatively logically separate changes in this PR, create a mini-section for each of them. For example: -->
   
   
   <!--
   In each section, please describe design decisions made, including:
    - Choice of algorithms
    - Behavioral aspects. What configuration values are acceptable? How are corner cases and error conditions handled, such as when there are insufficient resources?
    - Class organization and design (how the logic is split between classes, inheritance, composition, design patterns)
    - Method organization and design (how the logic is split between methods, parameters and return types)
    - Naming (class, method, API, configuration, HTTP endpoint, names of emitted metrics)
   -->
   
   
   <!-- It's good to describe an alternative design (or mention an alternative name) for every design (or naming) decision point and compare the alternatives with the designs that you've implemented (or the names you've chosen) to highlight the advantages of the chosen designs and names. -->
   
   <!-- If there was a discussion of the design of the feature implemented in this PR elsewhere (e. g. a "Proposal" issue, any other issue, or a thread in the development mailing list), link to that discussion from this PR description and explain what have changed in your final design compared to your original proposal or the consensus version in the end of the discussion. If something hasn't changed since the original discussion, you can omit a detailed discussion of those aspects of the design here, perhaps apart from brief mentioning for the sake of readability of this PR description. -->
   
   <!-- Some of the aspects mentioned above may be omitted for simple and small changes. -->
   
   <hr>
   
   This PR has:
   - [x] been self-reviewed.
   - [x] added documentation for new or modified features or behaviors.
   - [ ] added Javadocs for most classes and all non-trivial methods. Linked related entities via Javadoc links.
   - [ ] added or updated version, license, or notice information in [licenses.yaml](https://github.com/apache/druid/blob/master/licenses.yaml)
   - [x] added comments explaining the "why" and the intent of the code wherever would not be obvious for an unfamiliar reader.
   - [x] added unit tests or modified existing tests to cover new code paths, ensuring the threshold for [code coverage](https://github.com/apache/druid/blob/master/dev/code-review/code-coverage.md) is met.
   - [ ] added integration tests.
   - [x] been tested in a test Druid cluster.
   
   <!-- Check the items by putting "x" in the brackets for the done things. Not all of these items apply to every PR. Remove the items which are not done or not relevant to the PR. None of the items from the checklist above are strictly necessary, but it would be very helpful if you at least self-review the PR. -->
   
   <hr>
   
   ##### Key changed/added classes in this PR
    * org.apache.druid.emitter.prometheus.*
   
   This is re-open the PR here https://github.com/apache/druid/pull/8621 


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] clintropolis commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
clintropolis commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r585308569



##########
File path: website/.spelling
##########
@@ -1223,7 +1228,7 @@ SysMonitor
 TaskCountStatsMonitor
 TaskSlotCountStatsMonitor
 bufferCapacity
-bufferpoolName
+bufferPoolName

Review comment:
       oops, missed one, it's causing CI to fail




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-754220748


   For what is worth, Ive been running production clusters with this extension for monitoring for over a year. Things are stable but there are a couple open issues around pushgateway collection of Peon task metrics that are the main reasons to delay merging.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] ArvinZheng commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
ArvinZheng commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r513125045



##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");

Review comment:
       Reuse the pattern in `PrometheusEmitterConfig`

##########
File path: extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
##########
@@ -0,0 +1,128 @@
+{
+  "query/time" : { "dimensions" : ["dataSource", "type"], "type" : "timer", "conversionFactor": 1000.0, "help":  "Seconds taken to complete a query."},
+  "query/bytes" : { "dimensions" : ["dataSource", "type"], "type" : "count", "help":  "Number of bytes returned in query response."},
+  "query/node/time" : { "dimensions" : ["server"], "type" : "timer", "conversionFactor": 1000.0, "help": "Seconds taken to query individual historical/realtime processes."},
+  "query/node/ttfb" : { "dimensions" : ["server"], "type" : "timer", "help":  "Time to first byte. Seconds elapsed until Broker starts receiving the response from individual historical/realtime processes."},
+  "query/node/bytes" : { "dimensions" : ["server"], "type" : "count", "help": "Number of bytes returned from querying individual historical/realtime processes."},
+  "query/node/backpressure": { "dimensions" : ["server"], "type" : "timer", "help": "Seconds that the channel to this process has spent suspended due to backpressure."},
+  "query/intervalChunk/time" : { "dimensions" : [], "type" : "timer", "conversionFactor": 1000.0, "help": "Only emitted if interval chunking is enabled. Milliseconds required to query an interval chunk. This metric is deprecated and will be removed in the future because interval chunking is deprecated."},
+
+  "query/segment/time" : { "dimensions" : [], "type" : "timer", "conversionFactor": 1000.0, "help": "Seconds taken to query individual segment. Includes time to page in the segment from disk."},
+  "query/wait/time" : { "dimensions" : [], "type" : "timer", "conversionFactor": 1000.0, "help": "Seconds spent waiting for a segment to be scanned."},
+  "segment/scan/pending" : { "dimensions" : [], "type" : "gauge", "help": "Number of segments in queue waiting to be scanned."},
+  "query/segmentAndCache/time" : { "dimensions" : [], "type" : "timer", "conversionFactor": 1000.0, "help": "Seconds taken to query individual segment or hit the cache (if it is enabled on the Historical process)."},
+  "query/cpu/time" : { "dimensions" : ["dataSource", "type"], "type" : "timer", "conversionFactor": "1000000", "help": "Seconds of CPU time taken to complete a query"},
+
+  "query/count" : { "dimensions" : [], "type" : "count", "help": "Number of total queries" },
+  "query/success/count" : { "dimensions" : [], "type" : "count", "help": "Number of queries successfully processed"},
+  "query/failed/count" : { "dimensions" : [], "type" : "count", "help": "Number of failed queries"},
+  "query/interrupted/count" : { "dimensions" : [], "type" : "count", "help": "Number of queries interrupted due to cancellation or timeout"},
+
+  "query/cache/delta/numEntries" : { "dimensions" : [], "type" : "count", "help": "Number of entries in cache"},

Review comment:
       potential bug, deltas can be negative but Prometheus counter accepts only non-negative increment.

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {
+      return map.get(name);
+    } else if (map.containsKey(service + "_" + name)) {
+      return map.get(service + "_" + name);
+    } else {
+      return null;
+    }
+  }
+
+  public Metrics(String namespace, String path)
+  {
+    Map<String, Metric> metrics = readMap(path);
+    for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
+      String name = entry.getKey();
+      Metric metric = entry.getValue();
+      Metric.Type type = metric.type;
+      String[] dimensions = metric.dimensions.toArray(new String[0]);
+      String formattedName = pattern.matcher(StringUtils.toLowerCase(name)).replaceAll("_");
+      SimpleCollector collector = null;
+      if (Metric.Type.count.equals(type)) {
+        collector = new Counter.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.gauge.equals(type)) {
+        collector = new Gauge.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.timer.equals(type)) {
+        collector = new Histogram.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .buckets(.1, .25, .5, .75, 1, 2.5, 5, 7.5, 10, 30, 60, 120, 300)
+            .help(metric.help)
+            .register();
+      } else {
+        log.error("Unrecognized metric type [%s]", type);
+      }
+
+      if (collector != null) {
+        map.put(name, new DimensionsAndCollector(dimensions, collector, metric.conversionFactor));
+      }
+    }
+
+  }
+
+  private Map<String, Metric> readMap(String path)
+  {
+    try {
+      InputStream is;
+      if (Strings.isNullOrEmpty(path)) {
+        log.info("Using default metric dimension and types");
+        is = this.getClass().getClassLoader().getResourceAsStream("defaultMetrics.json");
+      } else {
+        log.info("Using metric dimensions at types at [%s]", path);

Review comment:
       typo, `metric dimensions at types` -> `metric dimensions and types`, maybe we could replace it by `metric configuration`

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()
+  {
+    if (strategy.equals(PrometheusEmitterConfig.Strategy.exporter)) {
+      if (server == null) {
+        try {
+          server = new HTTPServer(config.getPort());
+        }
+        catch (IOException e) {
+          log.error(e, "Unable to start prometheus HTTPServer");
+        }
+      } else {
+        log.error("HTTPServer is already started");
+      }
+    } else if (strategy.equals(PrometheusEmitterConfig.Strategy.pushgateway)) {
+      pushGateway = new PushGateway(config.getPushGatewayAddress());
+    }
+
+  }
+
+  @Override
+  public void emit(Event event)
+  {
+    if (event instanceof ServiceMetricEvent) {
+      emitMetric((ServiceMetricEvent) event);
+    }
+  }
+
+  void emitMetric(ServiceMetricEvent metricEvent)

Review comment:
       private?

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitterConfig.java
##########
@@ -0,0 +1,104 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.common.base.Preconditions;
+
+import javax.annotation.Nullable;
+import javax.xml.ws.BindingType;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitterConfig
+{
+
+  Pattern pattern = Pattern.compile("[a-zA-Z_:][a-zA-Z0-9_:]*");

Review comment:
       final, and static maybe, so that we can reuse this object/regex in other places

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {
+      return map.get(name);
+    } else if (map.containsKey(service + "_" + name)) {
+      return map.get(service + "_" + name);
+    } else {
+      return null;
+    }
+  }
+
+  public Metrics(String namespace, String path)
+  {
+    Map<String, Metric> metrics = readMap(path);
+    for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
+      String name = entry.getKey();
+      Metric metric = entry.getValue();
+      Metric.Type type = metric.type;
+      String[] dimensions = metric.dimensions.toArray(new String[0]);
+      String formattedName = pattern.matcher(StringUtils.toLowerCase(name)).replaceAll("_");
+      SimpleCollector collector = null;
+      if (Metric.Type.count.equals(type)) {
+        collector = new Counter.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.gauge.equals(type)) {
+        collector = new Gauge.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.timer.equals(type)) {
+        collector = new Histogram.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .buckets(.1, .25, .5, .75, 1, 2.5, 5, 7.5, 10, 30, 60, 120, 300)
+            .help(metric.help)
+            .register();
+      } else {
+        log.error("Unrecognized metric type [%s]", type);
+      }
+
+      if (collector != null) {
+        map.put(name, new DimensionsAndCollector(dimensions, collector, metric.conversionFactor));
+      }
+    }
+
+  }
+
+  private Map<String, Metric> readMap(String path)

Review comment:
       maybe `readConfig` or `loadConfig`?

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");

Review comment:
       Reuse the pattern in `PrometheusEmitterConfig`

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {
+      return map.get(name);
+    } else if (map.containsKey(service + "_" + name)) {
+      return map.get(service + "_" + name);
+    } else {
+      return null;
+    }
+  }
+
+  public Metrics(String namespace, String path)
+  {
+    Map<String, Metric> metrics = readMap(path);
+    for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
+      String name = entry.getKey();
+      Metric metric = entry.getValue();
+      Metric.Type type = metric.type;
+      String[] dimensions = metric.dimensions.toArray(new String[0]);
+      String formattedName = pattern.matcher(StringUtils.toLowerCase(name)).replaceAll("_");
+      SimpleCollector collector = null;
+      if (Metric.Type.count.equals(type)) {
+        collector = new Counter.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.gauge.equals(type)) {
+        collector = new Gauge.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.timer.equals(type)) {
+        collector = new Histogram.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .buckets(.1, .25, .5, .75, 1, 2.5, 5, 7.5, 10, 30, 60, 120, 300)
+            .help(metric.help)
+            .register();
+      } else {
+        log.error("Unrecognized metric type [%s]", type);
+      }
+
+      if (collector != null) {
+        map.put(name, new DimensionsAndCollector(dimensions, collector, metric.conversionFactor));
+      }
+    }
+
+  }
+
+  private Map<String, Metric> readMap(String path)
+  {
+    try {
+      InputStream is;
+      if (Strings.isNullOrEmpty(path)) {
+        log.info("Using default metric dimension and types");

Review comment:
       maybe replace `metric dimensions and types` by `metric configuration`? 

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {
+      return map.get(name);
+    } else if (map.containsKey(service + "_" + name)) {
+      return map.get(service + "_" + name);
+    } else {
+      return null;
+    }
+  }
+
+  public Metrics(String namespace, String path)
+  {
+    Map<String, Metric> metrics = readMap(path);
+    for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
+      String name = entry.getKey();
+      Metric metric = entry.getValue();
+      Metric.Type type = metric.type;
+      String[] dimensions = metric.dimensions.toArray(new String[0]);
+      String formattedName = pattern.matcher(StringUtils.toLowerCase(name)).replaceAll("_");
+      SimpleCollector collector = null;
+      if (Metric.Type.count.equals(type)) {
+        collector = new Counter.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.gauge.equals(type)) {
+        collector = new Gauge.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.timer.equals(type)) {
+        collector = new Histogram.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .buckets(.1, .25, .5, .75, 1, 2.5, 5, 7.5, 10, 30, 60, 120, 300)
+            .help(metric.help)
+            .register();
+      } else {
+        log.error("Unrecognized metric type [%s]", type);
+      }
+
+      if (collector != null) {
+        map.put(name, new DimensionsAndCollector(dimensions, collector, metric.conversionFactor));
+      }
+    }
+
+  }
+
+  private Map<String, Metric> readMap(String path)
+  {
+    try {
+      InputStream is;
+      if (Strings.isNullOrEmpty(path)) {
+        log.info("Using default metric dimension and types");
+        is = this.getClass().getClassLoader().getResourceAsStream("defaultMetrics.json");
+      } else {
+        log.info("Using metric dimensions at types at [%s]", path);
+        is = new FileInputStream(new File(path));
+      }
+      return mapper.readerFor(new TypeReference<Map<String, Metric>>()
+      {
+      }).readValue(is);
+    }
+    catch (IOException e) {
+      throw new ISE(e, "Failed to parse metric dimensions and types");
+    }
+  }
+
+  public Map<String, DimensionsAndCollector> getMap()

Review comment:
       maybe we can rename the `map` to `registeredMetrics` and then we could rename this method to `getRegisteredMetrics()`, I feel like this will be easier to read

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {
+      return map.get(name);
+    } else if (map.containsKey(service + "_" + name)) {
+      return map.get(service + "_" + name);
+    } else {
+      return null;
+    }
+  }
+
+  public Metrics(String namespace, String path)
+  {
+    Map<String, Metric> metrics = readMap(path);
+    for (Map.Entry<String, Metric> entry : metrics.entrySet()) {
+      String name = entry.getKey();
+      Metric metric = entry.getValue();
+      Metric.Type type = metric.type;
+      String[] dimensions = metric.dimensions.toArray(new String[0]);
+      String formattedName = pattern.matcher(StringUtils.toLowerCase(name)).replaceAll("_");
+      SimpleCollector collector = null;
+      if (Metric.Type.count.equals(type)) {
+        collector = new Counter.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.gauge.equals(type)) {
+        collector = new Gauge.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .help(metric.help)
+            .register();
+      } else if (Metric.Type.timer.equals(type)) {
+        collector = new Histogram.Builder()
+            .namespace(namespace)
+            .name(formattedName)
+            .labelNames(dimensions)
+            .buckets(.1, .25, .5, .75, 1, 2.5, 5, 7.5, 10, 30, 60, 120, 300)
+            .help(metric.help)
+            .register();
+      } else {
+        log.error("Unrecognized metric type [%s]", type);
+      }
+
+      if (collector != null) {
+        map.put(name, new DimensionsAndCollector(dimensions, collector, metric.conversionFactor));
+      }
+    }
+
+  }
+
+  private Map<String, Metric> readMap(String path)
+  {
+    try {
+      InputStream is;
+      if (Strings.isNullOrEmpty(path)) {
+        log.info("Using default metric dimension and types");
+        is = this.getClass().getClassLoader().getResourceAsStream("defaultMetrics.json");
+      } else {
+        log.info("Using metric dimensions at types at [%s]", path);
+        is = new FileInputStream(new File(path));
+      }
+      return mapper.readerFor(new TypeReference<Map<String, Metric>>()
+      {
+      }).readValue(is);
+    }
+    catch (IOException e) {
+      throw new ISE(e, "Failed to parse metric dimensions and types");

Review comment:
       same as above

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()
+  {
+    if (strategy.equals(PrometheusEmitterConfig.Strategy.exporter)) {
+      if (server == null) {
+        try {
+          server = new HTTPServer(config.getPort());
+        }
+        catch (IOException e) {
+          log.error(e, "Unable to start prometheus HTTPServer");
+        }
+      } else {
+        log.error("HTTPServer is already started");
+      }
+    } else if (strategy.equals(PrometheusEmitterConfig.Strategy.pushgateway)) {
+      pushGateway = new PushGateway(config.getPushGatewayAddress());
+    }
+
+  }
+
+  @Override
+  public void emit(Event event)
+  {
+    if (event instanceof ServiceMetricEvent) {
+      emitMetric((ServiceMetricEvent) event);
+    }
+  }
+
+  void emitMetric(ServiceMetricEvent metricEvent)
+  {
+    String name = metricEvent.getMetric();
+    String service = metricEvent.getService();
+    Map<String, Object> userDims = metricEvent.getUserDims();
+    identifier = (userDims.get("task") == null ? metricEvent.getHost() : (String) userDims.get("task"));
+    Number value = metricEvent.getValue();
+
+    DimensionsAndCollector metric = metrics.getByName(name, service);
+    if (metric != null) {
+      String[] labelValues = new String[metric.getDimensions().length];
+      String[] labelNames = metric.getDimensions();
+      for (int i = 0; i < labelValues.length; i++) {
+        String labelName = labelNames[i];
+        //labelName is controlled by the user. Instead of potential NPE on invalid labelName we use "unknown" as the dimension value
+        Object userDim = userDims.get(labelName);
+        labelValues[i] = userDim != null ? pattern.matcher(userDim.toString()).replaceAll("_") : "unknown";
+      }
+
+      if (metric.getCollector() instanceof Counter) {
+        ((Counter) metric.getCollector()).labels(labelValues).inc(value.doubleValue());
+      } else if (metric.getCollector() instanceof Gauge) {
+        ((Gauge) metric.getCollector()).labels(labelValues).set(value.doubleValue());
+      } else if (metric.getCollector() instanceof Histogram) {
+        ((Histogram) metric.getCollector()).labels(labelValues).observe(value.doubleValue() / metric.getConversionFactor());
+      } else {
+        log.error("Unrecognized metric type [%s]", metric.getCollector().getClass());
+      }
+    } else {
+      log.debug("Unmapped metric [%s]", name);
+    }
+  }
+
+  @Override
+  public void flush()
+  {
+    Map<String, DimensionsAndCollector> map = metrics.getMap();
+    try {
+      for (DimensionsAndCollector collector : map.values()) {
+        pushGateway.push(collector.getCollector(), config.getNamespace(), ImmutableMap.of(config.getNamespace(), identifier));

Review comment:
       potential NPE? if the configured strategy is not pushgateway, then this `pushGateway` wouldn't have been instantiated

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()

Review comment:
       we should schedule a task to push updates periodically when the strategy is set to `pushgateway`

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {

Review comment:
       `return Optional.ofNullable(map.get(name)).orElse(map.get(service + "_" + name));`

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()
+  {
+    if (strategy.equals(PrometheusEmitterConfig.Strategy.exporter)) {
+      if (server == null) {
+        try {
+          server = new HTTPServer(config.getPort());
+        }
+        catch (IOException e) {
+          log.error(e, "Unable to start prometheus HTTPServer");
+        }
+      } else {
+        log.error("HTTPServer is already started");
+      }
+    } else if (strategy.equals(PrometheusEmitterConfig.Strategy.pushgateway)) {
+      pushGateway = new PushGateway(config.getPushGatewayAddress());
+    }
+
+  }
+
+  @Override
+  public void emit(Event event)
+  {
+    if (event instanceof ServiceMetricEvent) {
+      emitMetric((ServiceMetricEvent) event);
+    }
+  }
+
+  void emitMetric(ServiceMetricEvent metricEvent)
+  {
+    String name = metricEvent.getMetric();
+    String service = metricEvent.getService();
+    Map<String, Object> userDims = metricEvent.getUserDims();
+    identifier = (userDims.get("task") == null ? metricEvent.getHost() : (String) userDims.get("task"));
+    Number value = metricEvent.getValue();
+
+    DimensionsAndCollector metric = metrics.getByName(name, service);
+    if (metric != null) {
+      String[] labelValues = new String[metric.getDimensions().length];
+      String[] labelNames = metric.getDimensions();
+      for (int i = 0; i < labelValues.length; i++) {
+        String labelName = labelNames[i];
+        //labelName is controlled by the user. Instead of potential NPE on invalid labelName we use "unknown" as the dimension value
+        Object userDim = userDims.get(labelName);
+        labelValues[i] = userDim != null ? pattern.matcher(userDim.toString()).replaceAll("_") : "unknown";
+      }
+
+      if (metric.getCollector() instanceof Counter) {
+        ((Counter) metric.getCollector()).labels(labelValues).inc(value.doubleValue());
+      } else if (metric.getCollector() instanceof Gauge) {
+        ((Gauge) metric.getCollector()).labels(labelValues).set(value.doubleValue());
+      } else if (metric.getCollector() instanceof Histogram) {
+        ((Histogram) metric.getCollector()).labels(labelValues).observe(value.doubleValue() / metric.getConversionFactor());
+      } else {
+        log.error("Unrecognized metric type [%s]", metric.getCollector().getClass());
+      }
+    } else {
+      log.debug("Unmapped metric [%s]", name);
+    }
+  }
+
+  @Override
+  public void flush()
+  {
+    Map<String, DimensionsAndCollector> map = metrics.getMap();
+    try {
+      for (DimensionsAndCollector collector : map.values()) {
+        pushGateway.push(collector.getCollector(), config.getNamespace(), ImmutableMap.of(config.getNamespace(), identifier));

Review comment:
       Also should we use a more meaningful label name for `identifier` instead of using the `config.getNamespace()`?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] Tiaaa commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
Tiaaa commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-760624945


   Verification of metrics on a local mini druid cluster as shown in below table. 
   
   Coordinator, historical, broker, router, middle-manager, overlord set up as prometheus monitoring target.
   Peon metrics is sent to pushgateway. 
   
   Component | Metric
   -- | --
   Coordinator | # TYPE druid_segment_size gauge druid_segment_size{dataSource="wiki_test",} 21679.0  # TYPE druid_segment_loadqueue_count gauge druid_segment_loadqueue_count{server="stats_druid_historical_2_stats_druid_historical_stats_dev_svc_cluster_local_8083",} 0.0 druid_segment_loadqueue_count{server="stats_druid_historical_1_stats_druid_historical_stats_dev_svc_cluster_local_8083",} 0.0 druid_segment_loadqueue_count{server="stats_druid_historical_0_stats_druid_historical_stats_dev_svc_cluster_local_8083",} 1.0
   Historical | # TYPE druid_query_time histogram druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.1",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.25",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.5",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.75",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="1.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="2.5",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="5.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="7.5",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="10.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="30.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="60.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="120.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="
 scan",le="300.0",} 1.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="+Inf",} 1.0                                                                                                                                      druid_query_time_count{dataSource="wiki_test",type="scan",} 1.0 druid_query_time_sum{dataSource="wiki_test",type="scan",} 0.093
   Broker | # TYPE druid_query_time histogram druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.1",} 2.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.25",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.5",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="0.75",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="1.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="2.5",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="5.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="7.5",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="10.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="30.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="60.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="120.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan
 ",le="300.0",} 3.0 druid_query_time_bucket{dataSource="wiki_test",type="scan",le="+Inf",} 3.0 druid_query_time_count{dataSource="wiki_test",type="scan",} 3.0 druid_query_time_sum{dataSource="wiki_test",type="scan",} 0.132  # TYPE druid_query_node_time histogram druid_query_node_time_bucket{server="stats_druid_historical_1_stats_druid_historical_stats_dev_svc_cluster_local_8083",le="0.1",} 0.0
   Router | # TYPE druid_jvm_mem_used gauge druid_jvm_mem_used{memKind="heap",} 4.8370752E7 druid_jvm_mem_used{memKind="nonheap",} 6.4390328E7
   Middle-manager | # TYPE druid_jvm_pool_used gauge druid_jvm_pool_used{poolKind="heap",poolName="PS_Old_Gen",} 2.8118984E7 druid_jvm_pool_used{poolKind="nonheap",poolName="Code_Cache",} 1.2116608E7 druid_jvm_pool_used{poolKind="heap",poolName="PS_Survivor_Space",} 0.0 druid_jvm_pool_used{poolKind="nonheap",poolName="Metaspace",} 4.5766376E7 druid_jvm_pool_used{poolKind="heap",poolName="PS_Eden_Space",} 2.5587941728E10
   Overlord | # TYPE druid_task_run_time histogram druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="0.1",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="0.25",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="0.5",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="0.75",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="1.0",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="2.5",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="5.0",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="7.5",} 0.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="10.0",} 1.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="30.0",} 1.0 druid_task_run_time_bucket{dataSo
 urce="wiki_test",taskType="index_parallel",le="60.0",} 1.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="120.0",} 1.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="300.0",} 1.0 druid_task_run_time_bucket{dataSource="wiki_test",taskType="index_parallel",le="+Inf",} 1.0 druid_task_run_time_count{dataSource="wiki_test",taskType="index_parallel",} 1.0 druid_task_run_time_sum{dataSource="wiki_test",taskType="index_parallel",} 9.553
   Peon | push_time_seconds{druid="index_parallel_wiki_test_2021-01-10T23:42:35.061Z",instance="",job="druid"} 1.6103221647556024e+09
   
   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] clintropolis commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
clintropolis commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-794551318


   >@clintropolis anything left we need to do before merge?
   
   Oops no, sorry got distracted and hadn't got back to this yet.
   
   >Will this be available în the next 0.21.0 release?
   
   Unfortunately we have already cut the branch for 0.21.0, after which we only merge bug fixes, so this will go out in the release after that. 0.21.0 has been a bit delayed, so it shouldn't be too much longer before we begin the next release as well.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] jinfwhuang commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
jinfwhuang commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r498982127



##########
File path: extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
##########
@@ -0,0 +1,128 @@
+{
+  "query/time" : { "dimensions" : ["dataSource", "type"], "type" : "timer", "conversionFactor": 1000.0, "help":  "Seconds taken to complete a query."},

Review comment:
       Are these conversion a good idea?
   
   It would mean that these metrics will be slightly different from how they are described in this documentation. https://druid.apache.org/docs/latest/operations/metrics.html




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] Tiaaa commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
Tiaaa commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r499157969



##########
File path: extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
##########
@@ -0,0 +1,128 @@
+{
+  "query/time" : { "dimensions" : ["dataSource", "type"], "type" : "timer", "conversionFactor": 1000.0, "help":  "Seconds taken to complete a query."},

Review comment:
       https://prometheus.io/docs/practices/naming/#base-units
   It's coming from prometheus common practice. 
   
   cc @michaelschiff 




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] clintropolis merged pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
clintropolis merged pull request #10412:
URL: https://github.com/apache/druid/pull/10412


   


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-794306587


   @clintropolis anything left we need to do before merge?


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-760648631


   @Tiaaa awesome! I see peon metrics in pushgateway as well.
   <img width="1780" alt="Screen Shot 2021-01-14 at 8 42 38 PM" src="https://user-images.githubusercontent.com/1669670/104682480-a0131900-56a9-11eb-8817-3dea4d0b3b0d.png">
   Couple things I've noticed while testing:
   * Successful pushes in peon tasks still log an exception:
   ```
   2021-01-15T04:38:20,671 ERROR [main] org.apache.druid.emitter.prometheus.PrometheusEmitter - Unable to push prometheus metrics to pushGateway
   java.io.IOException: Response code from http://pushgateway:9091/metrics/job/druid/druid/index_parallel_test_data_pbppbchf_2021-01-15T04%3A38%3A07.325Z was 200
   	at io.prometheus.client.exporter.PushGateway.doRequest(PushGateway.java:325) ~[prometheus_simpleclient_pushgateway_0.7.0.jar:?]
   	at io.prometheus.client.exporter.PushGateway.push(PushGateway.java:138) ~[prometheus_simpleclient_pushgateway_0.7.0.jar:?]
   	at io.prometheus.client.exporter.PushGateway.push(PushGateway.java:151) ~[prometheus_simpleclient_pushgateway_0.7.0.jar:?]
   	at org.apache.druid.emitter.prometheus.PrometheusEmitter.flush(PrometheusEmitter.java:134) [prometheus_emitter_0.18.0-SNAPSHOT.jar:0.18.0-SNAPSHOT]
   	at org.apache.druid.emitter.prometheus.PrometheusEmitter.close(PrometheusEmitter.java:150) [prometheus_emitter_0.18.0-SNAPSHOT.jar:0.18.0-SNAPSHOT]
   	at org.apache.druid.java.util.emitter.core.ComposingEmitter.close(ComposingEmitter.java:93) [druid-core-0.18.1.jar:0.18.1]
   	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_242]
   	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_242]
   	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_242]
   	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_242]
   	at org.apache.druid.java.util.common.lifecycle.Lifecycle$AnnotationBasedHandler.stop(Lifecycle.java:465) [druid-core-0.18.1.jar:0.18.1]
   	at org.apache.druid.java.util.common.lifecycle.Lifecycle.stop(Lifecycle.java:368) [druid-core-0.18.1.jar:0.18.1]
   	at org.apache.druid.cli.CliPeon.run(CliPeon.java:296) [druid-services-0.18.1.jar:0.18.1]
   	at org.apache.druid.cli.Main.main(Main.java:113) [druid-services-0.18.1.jar:0.18.1]
   ```
   * the label we're using right now is the task ID.  I think this it going to be too high cardinality for Prometheus


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] clintropolis commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
clintropolis commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-786962571


   >@clintropolis it looks like this is the last failing build step: https://travis-ci.com/github/apache/druid/jobs/483326128 - seems unrelated to the new emitter. Are we good to merge?
   
   Sorry for the delay, I will have a look as soon as I'm able and see if we can get this merged :+1:


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] Tiaaa commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
Tiaaa commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r558784419



##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()

Review comment:
       Given the only metric pushed by peon is "last pushed timestamp", I think it's valid to remove the scheduled task. Removed. 




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] ArvinZheng commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
ArvinZheng commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r516431300



##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/Metrics.java
##########
@@ -0,0 +1,157 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.SimpleCollector;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.regex.Pattern;
+
+public class Metrics
+{
+
+  private static final Logger log = new Logger(Metrics.class);
+  private final Map<String, DimensionsAndCollector> map = new HashMap<>();
+  private final ObjectMapper mapper = new ObjectMapper();
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z_:][^a-zA-Z0-9_:]*");
+
+  public DimensionsAndCollector getByName(String name, String service)
+  {
+    if (map.containsKey(name)) {

Review comment:
       you don't need to change the return type, but anyway this is a minor comment, feel free to pick whichever you prefer

##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");

Review comment:
       Oh, sorry, my bad.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r557865992



##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()

Review comment:
       Sorry I missed this - I think the scheduled executor may not be necessary. Main reason we've added strategy `pushgateway` is for things that are potentially too short-lived to be scraped by prometheus. Things that are living long enough to be pushing every 5 minutes are likely not "task" based, and may be better fit for normal scraping.  I lean toward keeping things simple, and pushing once at close seems sufficient.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] suhassumukh commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
suhassumukh commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-754037435


   Is there a timeline for this feature?


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff edited a comment on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff edited a comment on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-760648631


   @Tiaaa awesome! I see peon metrics in pushgateway as well.
   <img width="1780" alt="Screen Shot 2021-01-14 at 8 42 38 PM" src="https://user-images.githubusercontent.com/1669670/104682480-a0131900-56a9-11eb-8817-3dea4d0b3b0d.png">
   
   One thing - the label we're using right now is the task ID.  I think this it going to be too high cardinality for Prometheus


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] Tiaaa commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
Tiaaa commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r585178104



##########
File path: docs/development/extensions-contrib/prometheus.md
##########
@@ -0,0 +1,70 @@
+---
+id: prometheus
+title: "Prometheus Emitter"
+---
+
+<!--
+  ~ 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.
+  -->
+
+
+To use this Apache Druid (incubating) extension, make sure to [include](../../development/extensions.md#loading-extensions) `prometheus-emitter` extension.
+
+## Introduction
+
+This extension exposes Druid metrics for collection by a Prometheus server
+(https://prometheus.io/)

Review comment:
       Good suggestion, added. 




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] stroeovidiu commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
stroeovidiu commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-786656326


   Any update on this ? Looking forward having it.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] jinfwhuang commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
jinfwhuang commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r499193916



##########
File path: extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
##########
@@ -0,0 +1,128 @@
+{
+  "query/time" : { "dimensions" : ["dataSource", "type"], "type" : "timer", "conversionFactor": 1000.0, "help":  "Seconds taken to complete a query."},

Review comment:
       Okay. I guess there are tradeoffs with either choices. Maybe a good way to do is that for those converted, we can just put the unit in the prometheus names. Otherwise, if we refer to the druid metrics doc, we would find the name of the metrics to be documented in a different unit. 
   




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-786958769


   @clintropolis it looks like this is the last failing build step: https://travis-ci.com/github/apache/druid/jobs/483326128 - seems unrelated to the new emitter.  Are we good to merge?


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] clintropolis commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
clintropolis commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r584020750



##########
File path: docs/development/extensions-contrib/prometheus.md
##########
@@ -0,0 +1,70 @@
+---
+id: prometheus
+title: "Prometheus Emitter"
+---
+
+<!--
+  ~ 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.
+  -->
+
+
+To use this Apache Druid (incubating) extension, make sure to [include](../../development/extensions.md#loading-extensions) `prometheus-emitter` extension.

Review comment:
       Druid is no longer in the Apache Incubator, so this `(incubating)` should be removed.

##########
File path: docs/operations/metrics.md
##########
@@ -284,9 +284,9 @@ These metrics are only available if the JVMMonitor module is included.
 |`jvm/pool/init`|Initial pool.|poolKind, poolName.|Varies.|
 |`jvm/pool/max`|Max pool.|poolKind, poolName.|Varies.|
 |`jvm/pool/used`|Pool used.|poolKind, poolName.|< max pool|
-|`jvm/bufferpool/count`|Bufferpool count.|bufferpoolName.|Varies.|
-|`jvm/bufferpool/used`|Bufferpool used.|bufferpoolName.|close to capacity|
-|`jvm/bufferpool/capacity`|Bufferpool capacity.|bufferpoolName.|Varies.|
+|`jvm/bufferpool/count`|Bufferpool count.|bufferPoolName.|Varies.|

Review comment:
       I don't think this change should have happened? `bufferpoolName` still appears to be the dimension name in `JvmMonitor` as far as I can tell. There are a few other places scattered around where this appears to have happened. Potentially this is a result of missing changes or resolving a conflict with https://github.com/apache/druid/pull/10075

##########
File path: docs/development/extensions-contrib/prometheus.md
##########
@@ -0,0 +1,70 @@
+---
+id: prometheus
+title: "Prometheus Emitter"
+---
+
+<!--
+  ~ 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.
+  -->
+
+
+To use this Apache Druid (incubating) extension, make sure to [include](../../development/extensions.md#loading-extensions) `prometheus-emitter` extension.
+
+## Introduction
+
+This extension exposes Druid metrics for collection by a Prometheus server
+(https://prometheus.io/)

Review comment:
       It would be worth perhaps linking to metrics documentation https://druid.apache.org/docs/latest/operations/metrics.html (`[Druid Metrics](../../operations/metrics.md)`) and maybe emitter configuration stuffs, https://druid.apache.org/docs/latest/configuration/index.html#emitting-metrics (`[configuration](../../configuration/index.md#emitting-metrics`). 
   
   Also, you should probably include instructions to add ```druid.emitter=prometheus``` to the configs.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] stroeovidiu commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
stroeovidiu commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-794320724


   Will this be available în the next 0.21.0 release?
   
   Thank you


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] clintropolis commented on pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
clintropolis commented on pull request #10412:
URL: https://github.com/apache/druid/pull/10412#issuecomment-760677409


   hmm, it looks like the commits have become sort of messed up for this PR one way or another and github is showing a lot of unrelated commits. @Tiaaa any chance you can try clean this up to only show the changes of this PR to make it easier to review?


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] michaelschiff commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
michaelschiff commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r557865992



##########
File path: extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
##########
@@ -0,0 +1,153 @@
+/*
+ * 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.druid.emitter.prometheus;
+
+
+import com.google.common.collect.ImmutableMap;
+import io.prometheus.client.Counter;
+import io.prometheus.client.Gauge;
+import io.prometheus.client.Histogram;
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.exporter.PushGateway;
+import org.apache.druid.java.util.common.logger.Logger;
+import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ *
+ */
+public class PrometheusEmitter implements Emitter
+{
+
+  private static final Logger log = new Logger(PrometheusEmitter.class);
+  private final Metrics metrics;
+  private final PrometheusEmitterConfig config;
+  private final PrometheusEmitterConfig.Strategy strategy;
+  private final Pattern pattern = Pattern.compile("[^a-zA-Z0-9_][^a-zA-Z0-9_]*");
+
+  private HTTPServer server;
+  private PushGateway pushGateway;
+  private String identifier;
+
+  static PrometheusEmitter of(PrometheusEmitterConfig config)
+  {
+    return new PrometheusEmitter(config);
+  }
+
+  public PrometheusEmitter(PrometheusEmitterConfig config)
+  {
+    this.config = config;
+    this.strategy = config.getStrategy();
+    metrics = new Metrics(config.getNamespace(), config.getDimensionMapPath());
+  }
+
+
+  @Override
+  public void start()

Review comment:
       Sorry I missed this - I think the scheduled executor may not be necessary. Main reason we've added strategy `pushgateway` is for things that are potentially too short-lived to be scraped by prometheus (in druid that's really just peon tasks). Things that are living long enough to be pushing every 5 minutes are likely not "task" based, and may be better fit for normal scraping.  I lean toward keeping things simple, and pushing once at close seems sufficient.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org


[GitHub] [druid] Tiaaa commented on a change in pull request #10412: prometheus metric exporter

Posted by GitBox <gi...@apache.org>.
Tiaaa commented on a change in pull request #10412:
URL: https://github.com/apache/druid/pull/10412#discussion_r585177968



##########
File path: docs/operations/metrics.md
##########
@@ -284,9 +284,9 @@ These metrics are only available if the JVMMonitor module is included.
 |`jvm/pool/init`|Initial pool.|poolKind, poolName.|Varies.|
 |`jvm/pool/max`|Max pool.|poolKind, poolName.|Varies.|
 |`jvm/pool/used`|Pool used.|poolKind, poolName.|< max pool|
-|`jvm/bufferpool/count`|Bufferpool count.|bufferpoolName.|Varies.|
-|`jvm/bufferpool/used`|Bufferpool used.|bufferpoolName.|close to capacity|
-|`jvm/bufferpool/capacity`|Bufferpool capacity.|bufferpoolName.|Varies.|
+|`jvm/bufferpool/count`|Bufferpool count.|bufferPoolName.|Varies.|

Review comment:
       Yes you are right checked the metric dimension, fixed.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org