diff --git a/.idea/misc.xml b/.idea/misc.xml
index 61e7e5b21e7..bf2061d7392 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -87,4 +87,4 @@
-
\ No newline at end of file
+
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 76466cf9c87..215cd8d95b1 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -373,6 +373,8 @@
-c
org.apache.druid.extensions.contrib:ambari-metrics-emitter
-c
+ org.apache.druid.extensions.contrib:dropwizard-emitter
+ -c
org.apache.druid.extensions.contrib:druid-azure-extensions
-c
org.apache.druid.extensions.contrib:druid-cassandra-storage
diff --git a/docs/design/extensions-contrib/dropwizard.md b/docs/design/extensions-contrib/dropwizard.md
new file mode 100644
index 00000000000..283954b304e
--- /dev/null
+++ b/docs/design/extensions-contrib/dropwizard.md
@@ -0,0 +1,630 @@
+---
+layout: doc_page
+title: "Dropwizard metrics emitter"
+---
+
+
+
+# Dropwizard Emitter
+
+To use this extension, make sure to [include](../../development/extensions.md#loading-extensions) `dropwizard-emitter` extension.
+
+## Introduction
+
+This extension integrates [Dropwizard](http://metrics.dropwizard.io/3.1.0/getting-started/#) metrics library with druid so that dropwizard users can easily absorb druid into their monitoring ecosystem.
+It accumulates druid metrics as dropwizard metrics, and emits them to various sinks via dropwizard supported reporters.
+Currently supported dropwizard metrics types counter, gauge, meter, timer and histogram.
+These metrics can be emitted using either Console or JMX reporter.
+
+## Configuration
+
+All the configuration parameters for Dropwizard emitter are under `druid.emitter.dropwizard`.
+
+|property|description|required?|default|
+|--------|-----------|---------|-------|
+|`druid.emitter.dropwizard.reporters`|List of dropwizard reporters to be used. Here is a list of [Supported Reporters](#supported-dropwizard-reporters)|yes|none|
+|`druid.emitter.dropwizard.prefix`|Optional prefix to be used for metrics name|no|none|
+|`druid.emitter.dropwizard.includeHost`|Flag to include the host and port as part of the metric name.|no|yes|
+|`druid.emitter.dropwizard.dimensionMapPath`|Path to JSON file defining the dropwizard metric type, and desired dimensions for every Druid metric|no|Default mapping provided. See below.|
+|`druid.emitter.dropwizard.alertEmitters`| List of emitters where alerts will be forwarded to. |no| empty list (no forwarding)|
+|`druid.emitter.dropwizard.maxMetricsRegistrySize`| Maximum size of metrics registry to be cached at any time. |no| 100 Mb|
+
+
+### Druid to Dropwizard Event Conversion
+
+Each metric emitted using Dropwizard must specify a type, one of `[timer, counter, guage, meter, histogram]`. Dropwizard Emitter expects this mapping to
+be provided as a JSON file. Additionally, this mapping specifies which dimensions should be included for each metric.
+If the user does not specify their own JSON file, a [default mapping](#default-metrics-mapping) is used.
+All metrics are expected to be mapped. Metrics which are not mapped will be ignored.
+Dropwizard metric path is organized using the following schema:
+
+` : { "dimensions" : , "type" : , "timeUnit" : }`
+
+e.g.
+```json
+"query/time" : { "dimensions" : ["dataSource", "type"], "type" : "timer", "timeUnit": "MILLISECONDS"},
+"segment/scan/pending" : { "dimensions" : [], "type" : "gauge"}
+```
+
+For most use-cases, the default mapping is sufficient.
+
+### Supported Dropwizard reporters
+
+#### JMX Reporter
+Used to report druid metrics via JMX.
+```
+
+druid.emitter.dropwizard.reporters={"type":"jmx"}
+
+```
+
+#### Console Reporter
+Used to print Druid Metrics to console logs.
+
+```
+
+druid.emitter.dropwizard.reporters={"type":"console","emitIntervalInSecs":30}"}
+
+```
+
+### Default Metrics Mapping
+Latest default metrics mapping can be found [here] (https://github.com/apache/incubator-druid/tree/master/extensions-contrib/dropwizard/src/main/resources/defaultMetricDimensions.json)
+```json
+{
+ "query/time": {
+ "dimensions": [
+ "dataSource",
+ "type"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/node/time": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/node/ttfb": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/node/backpressure": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/intervalChunk/time": {
+ "dimensions": [],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/segment/time": {
+ "dimensions": [],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/wait/time": {
+ "dimensions": [],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "segment/scan/pending": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/segmentAndCache/time": {
+ "dimensions": [],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "query/cpu/time": {
+ "dimensions": [
+ "dataSource",
+ "type"
+ ],
+ "type": "timer",
+ "timeUnit": "NANOSECONDS"
+ },
+ "query/cache/delta/numEntries": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/sizeBytes": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/hits": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/misses": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/evictions": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/hitRate": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/averageBytes": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/timeouts": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/delta/errors": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "query/cache/total/numEntries": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/sizeBytes": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/hits": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/misses": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/evictions": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/hitRate": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/averageBytes": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/timeouts": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "query/cache/total/errors": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "ingest/events/thrownAway": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/events/unparseable": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/events/duplicate": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/events/processed": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/rows/output": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/persist/counter": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/persist/time": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "ingest/persist/cpu": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "timer",
+ "timeUnit": "NANOSECONDS"
+ },
+ "ingest/persist/backPressure": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "gauge"
+ },
+ "ingest/persist/failed": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/handoff/failed": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "counter"
+ },
+ "ingest/merge/time": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "ingest/merge/cpu": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "timer",
+ "timeUnit": "NANOSECONDS"
+ },
+ "task/run/time": {
+ "dimensions": [
+ "dataSource",
+ "taskType"
+ ],
+ "type": "timer",
+ "timeUnit": "MILLISECONDS"
+ },
+ "segment/added/bytes": {
+ "dimensions": [
+ "dataSource",
+ "taskType"
+ ],
+ "type": "counter"
+ },
+ "segment/moved/bytes": {
+ "dimensions": [
+ "dataSource",
+ "taskType"
+ ],
+ "type": "counter"
+ },
+ "segment/nuked/bytes": {
+ "dimensions": [
+ "dataSource",
+ "taskType"
+ ],
+ "type": "counter"
+ },
+ "segment/assigned/counter": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/moved/counter": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/dropped/counter": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/deleted/counter": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/unneeded/counter": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/cost/raw": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/cost/normalization": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/cost/normalized": {
+ "dimensions": [
+ "tier"
+ ],
+ "type": "counter"
+ },
+ "segment/loadQueue/size": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "gauge"
+ },
+ "segment/loadQueue/failed": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "gauge"
+ },
+ "segment/loadQueue/counter": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "gauge"
+ },
+ "segment/dropQueue/counter": {
+ "dimensions": [
+ "server"
+ ],
+ "type": "gauge"
+ },
+ "segment/size": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "gauge"
+ },
+ "segment/overShadowed/counter": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "segment/max": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "segment/used": {
+ "dimensions": [
+ "dataSource",
+ "tier",
+ "priority"
+ ],
+ "type": "gauge"
+ },
+ "segment/usedPercent": {
+ "dimensions": [
+ "dataSource",
+ "tier",
+ "priority"
+ ],
+ "type": "gauge"
+ },
+ "jvm/pool/committed": {
+ "dimensions": [
+ "poolKind",
+ "poolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/pool/init": {
+ "dimensions": [
+ "poolKind",
+ "poolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/pool/max": {
+ "dimensions": [
+ "poolKind",
+ "poolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/pool/used": {
+ "dimensions": [
+ "poolKind",
+ "poolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/bufferpool/counter": {
+ "dimensions": [
+ "bufferPoolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/bufferpool/used": {
+ "dimensions": [
+ "bufferPoolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/bufferpool/capacity": {
+ "dimensions": [
+ "bufferPoolName"
+ ],
+ "type": "gauge"
+ },
+ "jvm/mem/init": {
+ "dimensions": [
+ "memKind"
+ ],
+ "type": "gauge"
+ },
+ "jvm/mem/max": {
+ "dimensions": [
+ "memKind"
+ ],
+ "type": "gauge"
+ },
+ "jvm/mem/used": {
+ "dimensions": [
+ "memKind"
+ ],
+ "type": "gauge"
+ },
+ "jvm/mem/committed": {
+ "dimensions": [
+ "memKind"
+ ],
+ "type": "gauge"
+ },
+ "jvm/gc/counter": {
+ "dimensions": [
+ "gcName"
+ ],
+ "type": "counter"
+ },
+ "jvm/gc/cpu": {
+ "dimensions": [
+ "gcName"
+ ],
+ "type": "timer",
+ "timeUnit": "NANOSECONDS"
+ },
+ "ingest/events/buffered": {
+ "dimensions": [
+ "serviceName, bufferCapacity"
+ ],
+ "type": "gauge"
+ },
+ "sys/swap/free": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "sys/swap/max": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "sys/swap/pageIn": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "sys/swap/pageOut": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "sys/disk/write/counter": {
+ "dimensions": [
+ "fsDevName"
+ ],
+ "type": "counter"
+ },
+ "sys/disk/read/counter": {
+ "dimensions": [
+ "fsDevName"
+ ],
+ "type": "counter"
+ },
+ "sys/disk/write/size": {
+ "dimensions": [
+ "fsDevName"
+ ],
+ "type": "counter"
+ },
+ "sys/disk/read/size": {
+ "dimensions": [
+ "fsDevName"
+ ],
+ "type": "counter"
+ },
+ "sys/net/write/size": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "sys/net/read/size": {
+ "dimensions": [],
+ "type": "counter"
+ },
+ "sys/fs/used": {
+ "dimensions": [
+ "fsDevName",
+ "fsDirName",
+ "fsTypeName",
+ "fsSysTypeName",
+ "fsOptions"
+ ],
+ "type": "gauge"
+ },
+ "sys/fs/max": {
+ "dimensions": [
+ "fsDevName",
+ "fsDirName",
+ "fsTypeName",
+ "fsSysTypeName",
+ "fsOptions"
+ ],
+ "type": "gauge"
+ },
+ "sys/mem/used": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "sys/mem/max": {
+ "dimensions": [],
+ "type": "gauge"
+ },
+ "sys/storage/used": {
+ "dimensions": [
+ "fsDirName"
+ ],
+ "type": "gauge"
+ },
+ "sys/cpu": {
+ "dimensions": [
+ "cpuName",
+ "cpuTime"
+ ],
+ "type": "gauge"
+ },
+ "coordinator-segment/counter": {
+ "dimensions": [
+ "dataSource"
+ ],
+ "type": "gauge"
+ },
+ "historical-segment/counter": {
+ "dimensions": [
+ "dataSource",
+ "tier",
+ "priority"
+ ],
+ "type": "gauge"
+ }
+}
+```
\ No newline at end of file
diff --git a/extensions-contrib/dropwizard-emitter/pom.xml b/extensions-contrib/dropwizard-emitter/pom.xml
new file mode 100644
index 00000000000..def2c20c0da
--- /dev/null
+++ b/extensions-contrib/dropwizard-emitter/pom.xml
@@ -0,0 +1,123 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.druid
+ druid
+ 0.17.0-incubating-SNAPSHOT
+ ../../pom.xml
+
+
+ org.apache.druid.extensions.contrib
+ dropwizard-emitter
+ dropwizard-emitter
+ Druid emitter extension to convert druid metric to Dropwizard metrics
+
+
+
+ org.apache.druid
+ druid-core
+ ${project.parent.version}
+ provided
+
+
+ org.apache.druid
+ druid-server
+ ${project.parent.version}
+ provided
+
+
+ io.dropwizard.metrics
+ metrics-core
+ ${dropwizard.metrics.version}
+
+
+ io.dropwizard.metrics
+ metrics-jmx
+ ${dropwizard.metrics.version}
+
+
+ junit
+ junit
+ test
+
+
+ org.easymock
+ easymock
+ test
+
+
+ pl.pragmatists
+ JUnitParams
+ 1.0.4
+ test
+
+
+ org.apache.druid
+ druid-processing
+ ${project.parent.version}
+ provided
+
+
+ com.fasterxml.jackson.core
+ jackson-annotations
+ provided
+
+
+ org.apache.curator
+ curator-client
+ provided
+
+
+ com.google.inject
+ guice
+ provided
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ provided
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ provided
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+ provided
+
+
+ com.google.guava
+ guava
+ provided
+
+
+ com.google.code.findbugs
+ jsr305
+ provided
+
+
+
diff --git a/extensions-contrib/dropwizard-emitter/src/main/java/org/apache/druid/emitter/dropwizard/DropwizardConverter.java b/extensions-contrib/dropwizard-emitter/src/main/java/org/apache/druid/emitter/dropwizard/DropwizardConverter.java
new file mode 100644
index 00000000000..7c1194726b3
--- /dev/null
+++ b/extensions-contrib/dropwizard-emitter/src/main/java/org/apache/druid/emitter/dropwizard/DropwizardConverter.java
@@ -0,0 +1,106 @@
+/*
+ * 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.dropwizard;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Strings;
+import org.apache.curator.shaded.com.google.common.io.Closeables;
+import org.apache.druid.java.util.common.ISE;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import javax.annotation.Nullable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ *
+ */
+public class DropwizardConverter
+{
+ private static final Logger log = new Logger(DropwizardConverter.class);
+ private final Map metricMap;
+
+ public DropwizardConverter(ObjectMapper mapper, String dimensionMapPath)
+ {
+ metricMap = readMap(mapper, dimensionMapPath);
+ }
+
+ /**
+ * Filters user dimensions for given metric and adds them to filteredDimensions.
+ * Returns null if there is no mapping present for the given metric.
+ */
+ @Nullable
+ public DropwizardMetricSpec addFilteredUserDims(
+ String service,
+ String metric,
+ Map userDims,
+ Map filteredDimensions
+ )
+ {
+
+ // Find the metric in the map. If we cant find it try to look it up prefixed by the service name.
+ // This is because some metrics are reported differently, but with the same name, from different services.
+ DropwizardMetricSpec metricSpec = null;
+ DropwizardMetricSpec dropwizardMetricSpec = metricMap.get(metric);
+ if (dropwizardMetricSpec != null) {
+ metricSpec = dropwizardMetricSpec;
+ } else if (metricMap.containsKey(service + "-" + metric)) {
+ metricSpec = metricMap.get(service + "-" + metric);
+ }
+ if (metricSpec != null) {
+ for (String dim : metricSpec.getDimensions()) {
+ if (userDims.containsKey(dim)) {
+ filteredDimensions.put(dim, userDims.get(dim).toString());
+ }
+ }
+ return metricSpec;
+ } else {
+ // No mapping found for given metric, return null
+ return null;
+ }
+ }
+
+ private Map readMap(ObjectMapper mapper, String dimensionMapPath)
+ {
+ InputStream is = null;
+ try {
+ if (Strings.isNullOrEmpty(dimensionMapPath)) {
+ log.info("Using default metric dimension and types");
+ is = this.getClass().getClassLoader().getResourceAsStream("defaultMetricDimensions.json");
+ } else {
+ log.info("Using metric dimensions at types at [%s]", dimensionMapPath);
+ is = new FileInputStream(new File(dimensionMapPath));
+ }
+ return mapper.readerFor(new TypeReference