You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/01/16 16:14:25 UTC

[iotdb] branch master updated: [IOTDB-2191] Use IoTDB itself to collect runtime metrics (#4634)

This is an automated email from the ASF dual-hosted git repository.

rong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 478b9bd  [IOTDB-2191] Use IoTDB itself to collect runtime metrics (#4634)
478b9bd is described below

commit 478b9bd1bbe0c0dc8575fb3eac98e01750040651
Author: Xieqijun <44...@users.noreply.github.com>
AuthorDate: Mon Jan 17 00:13:54 2022 +0800

    [IOTDB-2191] Use IoTDB itself to collect runtime metrics (#4634)
---
 docs/UserGuide/System-Tools/Metric-Tool.md         |   2 +-
 docs/zh/UserGuide/System-Tools/Metric-Tool.md      |   2 +-
 metrics/ReadMe.md                                  |   1 +
 .../reporter/prometheus/PrometheusReporter.java    |   4 +-
 .../main/assembly/resources/conf/iotdb-metric.yml  |   3 +-
 .../apache/iotdb/metrics/utils/ReporterType.java   |   2 +-
 .../iotdb/metrics/config/MetricConfigTest.java     |   9 +-
 .../src/{main => }/test/resources/iotdb-metric.yml |   3 +-
 .../org.apache.iotdb.metrics.MetricManager         |   2 +-
 server/pom.xml                                     |   5 +
 .../java/org/apache/iotdb/db/conf/IoTDBConfig.java |   8 -
 .../reporter/DropwizardIoTDBReporter.java          |  74 +++++++
 .../metrics/dropwizard/reporter/IoTDBReporter.java | 233 +++++++++++++++++++++
 .../org/apache/iotdb/db/metrics/metricsUtils.java  |  61 ++++++
 .../micrometer/registry/IoTDBMeterRegistry.java    | 150 +++++++++++++
 .../micrometer/registry/IoTDBRegistryConfig.java   |  16 +-
 .../reporter/MicrometerIoTDBReporter.java          |  94 +++++++++
 .../services/org.apache.iotdb.metrics.Reporter     |   3 +-
 18 files changed, 641 insertions(+), 31 deletions(-)

diff --git a/docs/UserGuide/System-Tools/Metric-Tool.md b/docs/UserGuide/System-Tools/Metric-Tool.md
index 6f35665..0da55f6 100644
--- a/docs/UserGuide/System-Tools/Metric-Tool.md
+++ b/docs/UserGuide/System-Tools/Metric-Tool.md
@@ -198,7 +198,7 @@ The metrics collection switch is disabled by default,you need to enable it fro
 # whether enable the module
 enableMetric: false
 
-# Multiple reporter, options: [jmx, prometheus]
+# Multiple reporter, options: [jmx, prometheus, iotdb]. iotdb is off by default.
 metricReporterList:
   - jmx
   - prometheus
diff --git a/docs/zh/UserGuide/System-Tools/Metric-Tool.md b/docs/zh/UserGuide/System-Tools/Metric-Tool.md
index 06108d2..0ec988d 100644
--- a/docs/zh/UserGuide/System-Tools/Metric-Tool.md
+++ b/docs/zh/UserGuide/System-Tools/Metric-Tool.md
@@ -196,7 +196,7 @@ metric采集默认是关闭的,需要先到conf/iotdb-metric.yml中打开后
 # 是否启动监控模块,默认为false
 enableMetric: false
 
-# 数据提供方式,对外部通过jmx和prometheus协议提供metrics的数据, 可选参数:[jmx, prometheus]
+# 数据提供方式,对外部通过jmx和prometheus协议提供metrics的数据, 可选参数:[jmx, prometheus, iotdb],iotdb是默认关闭的。
 metricReporterList:
    - jmx
    - prometheus
diff --git a/metrics/ReadMe.md b/metrics/ReadMe.md
index ff1edb0..39c2be2 100644
--- a/metrics/ReadMe.md
+++ b/metrics/ReadMe.md
@@ -27,6 +27,7 @@ Metric Module
 - In each implementation, you can use many types of reporter to report the details of metric
   - Jmx Reporter
   - Prometheus Reporter
+  - IoTDB Reporter
 
 - [1. Design](#1-design)
   - [1.1. Over all Design for acquisition System](#11-over-all-design-for-acquisition-system)
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java
index c7a7e15..3a5561f 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/prometheus/PrometheusReporter.java
@@ -24,7 +24,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
-import java.util.Collections;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.concurrent.ScheduledExecutorService;
@@ -161,8 +160,7 @@ public class PrometheusReporter extends ScheduledReporter {
         RATE_UNIT,
         DURATION_UNIT,
         executor,
-        shutdownExecutorOnStop,
-        Collections.<MetricAttribute>emptySet());
+        shutdownExecutorOnStop);
     this.prometheus = prometheus;
     this.prefix = prefix;
   }
diff --git a/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml b/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
index cc5aee2..4255289 100644
--- a/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
+++ b/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
@@ -20,7 +20,8 @@
 # whether enable the module
 enableMetric: false
 
-# Multiple reporter, options: [jmx, prometheus]
+# Multiple reporter, options: [jmx, prometheus, iotdb]
+# iotdb is off by default
 metricReporterList:
   - jmx
   - prometheus
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
index 06792ba..0c9443c 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
@@ -24,7 +24,7 @@ public enum ReporterType {
   // why all below are in lower case.
   jmx,
   prometheus,
-  internal;
+  iotdb;
 
   @Override
   public String toString() {
diff --git a/metrics/interface/src/main/test/org/apache/iotdb/metrics/config/MetricConfigTest.java b/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
similarity index 86%
rename from metrics/interface/src/main/test/org/apache/iotdb/metrics/config/MetricConfigTest.java
rename to metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
index 1d8e9eb..a3aa295 100644
--- a/metrics/interface/src/main/test/org/apache/iotdb/metrics/config/MetricConfigTest.java
+++ b/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
@@ -21,12 +21,12 @@ package org.apache.iotdb.metrics.config;
 
 import org.apache.iotdb.metrics.utils.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.ReporterType;
+
 import org.junit.Assert;
 import org.junit.Test;
 import org.yaml.snakeyaml.Yaml;
 import org.yaml.snakeyaml.constructor.Constructor;
 
-import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -36,14 +36,14 @@ public class MetricConfigTest {
 
   @Test
   public void yamlConfigTest() {
-    String url = this.getClass().getClassLoader().getResource("resources/iotdb-metric.yml").getPath();
+    String url = this.getClass().getClassLoader().getResource("iotdb-metric.yml").getPath();
     System.out.println(url);
 
     MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
     Constructor constructor = new Constructor(MetricConfig.class);
     Yaml yaml = new Yaml(constructor);
     if (url != null) {
-      try (InputStream inputStream = new FileInputStream(new File(url))) {
+      try (InputStream inputStream = new FileInputStream(url)) {
         metricConfig = (MetricConfig) yaml.load(inputStream);
       } catch (IOException e) {
         Assert.fail();
@@ -52,7 +52,8 @@ public class MetricConfigTest {
 
     List<ReporterType> lists = metricConfig.getMetricReporterList();
     Assert.assertEquals(lists.size(), 2);
-    Assert.assertEquals(metricConfig.getPrometheusReporterConfig().getPrometheusExporterPort(), "9091");
+    Assert.assertEquals(
+        metricConfig.getPrometheusReporterConfig().getPrometheusExporterPort(), "9091");
     List<PredefinedMetric> predefinedMetrics = metricConfig.getPredefinedMetrics();
     Assert.assertEquals(predefinedMetrics.size(), 1);
   }
diff --git a/metrics/interface/src/main/test/resources/iotdb-metric.yml b/metrics/interface/src/test/resources/iotdb-metric.yml
similarity index 92%
rename from metrics/interface/src/main/test/resources/iotdb-metric.yml
rename to metrics/interface/src/test/resources/iotdb-metric.yml
index 44c93ae..4bf2fbe 100644
--- a/metrics/interface/src/main/test/resources/iotdb-metric.yml
+++ b/metrics/interface/src/test/resources/iotdb-metric.yml
@@ -20,7 +20,8 @@
 # whether enable the module
 enableMetric: true
 
-# can be multiple reporter, e.g., jmx,prometheus,iotdb
+# can be multiple reporter, e.g., jmx,prometheus,iotdb.
+# iotdb is off by default
 metricReporterList:
   - jmx
   - prometheus
diff --git a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager b/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
index 235ab43..6af7c7a 100644
--- a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
+++ b/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
@@ -15,4 +15,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-org.apache.iotdb.metrics.micrometer.MicrometerMetricManager
\ No newline at end of file
+org.apache.iotdb.metrics.micrometer.MicrometerMetricManager
diff --git a/server/pom.xml b/server/pom.xml
index 8530d66..df1d03b 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -232,6 +232,11 @@
             <artifactId>micrometer-metrics</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.iotdb</groupId>
+            <artifactId>dropwizard-metrics</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index 48fe306..658cc52 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -2185,14 +2185,6 @@ public class IoTDBConfig {
     this.thriftServerAwaitTimeForStopService = thriftServerAwaitTimeForStopService;
   }
 
-  public int getQueryCacheSizeInMetric() {
-    return queryCacheSizeInMetric;
-  }
-
-  public void setQueryCacheSizeInMetric(int queryCacheSizeInMetric) {
-    this.queryCacheSizeInMetric = queryCacheSizeInMetric;
-  }
-
   public boolean isEnableMQTTService() {
     return enableMQTTService;
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
new file mode 100644
index 0000000..e35d033
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
@@ -0,0 +1,74 @@
+/*
+ * 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.iotdb.db.metrics.dropwizard.reporter;
+
+import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.Reporter;
+import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager;
+import org.apache.iotdb.metrics.utils.ReporterType;
+
+import com.codahale.metrics.MetricFilter;
+
+import java.util.concurrent.TimeUnit;
+
+public class DropwizardIoTDBReporter implements Reporter {
+
+  private MetricManager dropwizardMetricManager = null;
+  private IoTDBReporter ioTDBReporter;
+
+  private static final MetricConfig metricConfig =
+      MetricConfigDescriptor.getInstance().getMetricConfig();
+
+  @Override
+  public boolean start() {
+    if (!metricConfig.getEnableMetric()) {
+      return false;
+    }
+    ioTDBReporter =
+        IoTDBReporter.forRegistry(
+                ((DropwizardMetricManager) dropwizardMetricManager).getMetricRegistry())
+            .prefixedWith("dropwizard:")
+            .filter(MetricFilter.ALL)
+            .build();
+    ioTDBReporter.start(metricConfig.getPushPeriodInSecond(), TimeUnit.SECONDS);
+    return true;
+  }
+
+  @Override
+  public boolean stop() {
+    if (ioTDBReporter == null) {
+      return false;
+    }
+    ioTDBReporter.stop();
+    return true;
+  }
+
+  @Override
+  public ReporterType getReporterType() {
+    return ReporterType.iotdb;
+  }
+
+  @Override
+  public void setMetricManager(MetricManager metricManager) {
+    this.dropwizardMetricManager = metricManager;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/IoTDBReporter.java b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/IoTDBReporter.java
new file mode 100644
index 0000000..acb05ae
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/dropwizard/reporter/IoTDBReporter.java
@@ -0,0 +1,233 @@
+/*
+ * 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.iotdb.db.metrics.dropwizard.reporter;
+
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.path.PartialPath;
+import org.apache.iotdb.db.metrics.metricsUtils;
+import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.service.basic.ServiceProvider;
+import org.apache.iotdb.db.utils.DataTypeUtils;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import com.codahale.metrics.Counter;
+import com.codahale.metrics.Gauge;
+import com.codahale.metrics.Histogram;
+import com.codahale.metrics.Meter;
+import com.codahale.metrics.MetricFilter;
+import com.codahale.metrics.MetricRegistry;
+import com.codahale.metrics.ScheduledReporter;
+import com.codahale.metrics.Snapshot;
+import com.codahale.metrics.Timer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class IoTDBReporter extends ScheduledReporter {
+
+  private static final TimeUnit DURATION_UNIT = TimeUnit.MILLISECONDS;
+  private static final TimeUnit RATE_UNIT = TimeUnit.SECONDS;
+  private final String prefix;
+  private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBReporter.class);
+  private final ServiceProvider serviceProvider;
+  private final int rpcPort;
+  private final String address;
+
+  protected IoTDBReporter(
+      MetricRegistry registry,
+      String prefix,
+      MetricFilter filter,
+      ScheduledExecutorService executor,
+      boolean shutdownExecutorOnStop) {
+    super(
+        registry,
+        "iotdb-reporter",
+        filter,
+        RATE_UNIT,
+        DURATION_UNIT,
+        executor,
+        shutdownExecutorOnStop);
+    this.prefix = prefix;
+    IoTDBConfig ioTDBConfig = IoTDBDescriptor.getInstance().getConfig();
+    rpcPort = ioTDBConfig.getRpcPort();
+    address = ioTDBConfig.getRpcAddress();
+    serviceProvider = IoTDB.serviceProvider;
+  }
+
+  public static class Builder {
+    private final MetricRegistry metricRegistry;
+    private String prefix;
+    private MetricFilter metricFilter;
+    private ScheduledExecutorService executorService;
+    private boolean shutdownExecutorOnStop;
+
+    private Builder(MetricRegistry metricRegistry) {
+      this.metricRegistry = metricRegistry;
+      this.prefix = null;
+      this.metricFilter = MetricFilter.ALL;
+      this.executorService = null;
+      this.shutdownExecutorOnStop = true;
+    }
+
+    public Builder shutdownExecutorOnStop(boolean shutdownExecutorOnStop) {
+      this.shutdownExecutorOnStop = shutdownExecutorOnStop;
+      return this;
+    }
+
+    public Builder scheduleOn(ScheduledExecutorService executorService) {
+      this.executorService = executorService;
+      return this;
+    }
+
+    public Builder prefixedWith(String prefix) {
+      this.prefix = prefix;
+      return this;
+    }
+
+    public Builder filter(MetricFilter metricFilter) {
+      this.metricFilter = metricFilter;
+      return this;
+    }
+
+    public IoTDBReporter build() {
+      return new IoTDBReporter(
+          metricRegistry, prefix, metricFilter, executorService, shutdownExecutorOnStop);
+    }
+  }
+
+  @Override
+  public void report(
+      SortedMap<String, Gauge> gauges,
+      SortedMap<String, Counter> counters,
+      SortedMap<String, Histogram> histograms,
+      SortedMap<String, Meter> meters,
+      SortedMap<String, Timer> timers) {
+    for (Map.Entry<String, Gauge> entry : gauges.entrySet()) {
+      sendGauge(entry.getKey(), entry.getValue());
+    }
+    for (Map.Entry<String, Counter> entry : counters.entrySet()) {
+      sendCounter(entry.getKey(), entry.getValue());
+    }
+    for (Map.Entry<String, Histogram> entry : histograms.entrySet()) {
+      sendHistogram(entry.getKey(), entry.getValue());
+    }
+    for (Map.Entry<String, Meter> entry : meters.entrySet()) {
+      sendMeter(entry.getKey(), entry.getValue());
+    }
+    for (Map.Entry<String, Timer> entry : timers.entrySet()) {
+      sendTimer(entry.getKey(), entry.getValue());
+    }
+  }
+
+  private void sendTimer(String name, Timer timer) {
+    writeSnapshotAndCount(
+        prefixed(name), timer.getSnapshot(), timer.getCount(), 1.0D / TimeUnit.SECONDS.toNanos(1L));
+  }
+
+  private void sendMeter(String name, Meter meter) {
+    double value = meter.getCount();
+    updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+  }
+
+  private void sendHistogram(String name, Histogram histogram) {
+    writeSnapshotAndCount(prefixed(name), histogram.getSnapshot(), histogram.getCount(), 1.0);
+  }
+
+  private void sendCounter(String name, Counter counter) {
+    double value = counter.getCount();
+    updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+  }
+
+  private void sendGauge(String name, Gauge gauge) {
+    Object obj = gauge.getValue();
+    double value;
+    if (obj instanceof Number) {
+      value = ((Number) obj).doubleValue();
+      updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+    } else if (obj instanceof Boolean) {
+      value = ((Boolean) obj) ? 1 : 0;
+      updateValue(prefixed(name), metricsUtils.emptyMap(), value);
+    } else {
+      LOGGER.warn("Invalid type for Gauge {}: {}", name, obj.getClass().getName());
+    }
+  }
+
+  private void writeSnapshotAndCount(String name, Snapshot snapshot, long count, double factor) {
+    updateValue(name, metricsUtils.mapOf("quantile", "0.5"), snapshot.getMedian() * factor);
+    updateValue(
+        name, metricsUtils.mapOf("quantile", "0.75"), snapshot.get75thPercentile() * factor);
+    updateValue(
+        name, metricsUtils.mapOf("quantile", "0.95"), snapshot.get95thPercentile() * factor);
+    updateValue(
+        name, metricsUtils.mapOf("quantile", "0.98"), snapshot.get98thPercentile() * factor);
+    updateValue(
+        name, metricsUtils.mapOf("quantile", "0.99"), snapshot.get99thPercentile() * factor);
+    updateValue(
+        name, metricsUtils.mapOf("quantile", "0.999"), snapshot.get999thPercentile() * factor);
+    updateValue(name + "_min", metricsUtils.emptyMap(), snapshot.getMin());
+    updateValue(name + "_max", metricsUtils.emptyMap(), snapshot.getMax());
+    updateValue(name + "_median", metricsUtils.emptyMap(), snapshot.getMedian());
+    updateValue(name + "_mean", metricsUtils.emptyMap(), snapshot.getMean());
+    updateValue(name + "_stddev", metricsUtils.emptyMap(), snapshot.getStdDev());
+    updateValue(name + "_count", metricsUtils.emptyMap(), count);
+  }
+
+  private void updateValue(String name, Map<String, String> labels, double value) {
+    try {
+      InsertRowPlan insertRowPlan =
+          new InsertRowPlan(
+              new PartialPath(metricsUtils.generatePath(address, rpcPort, name, labels)),
+              System.currentTimeMillis(),
+              new String[] {"value"},
+              DataTypeUtils.getValueBuffer(
+                  new ArrayList<>(Arrays.asList(TSDataType.DOUBLE)),
+                  new ArrayList<>(Arrays.asList(value))),
+              false);
+      serviceProvider.executeNonQuery(insertRowPlan);
+    } catch (IllegalPathException
+        | IoTDBConnectionException
+        | QueryProcessException
+        | StorageGroupNotSetException
+        | StorageEngineException e) {
+      LOGGER.error("illegal insertRowPlan,reason:" + e.getMessage());
+    }
+  }
+
+  private String prefixed(String name) {
+    return prefix == null ? name : (prefix + name);
+  }
+
+  public static Builder forRegistry(MetricRegistry metricRegistry) {
+    return new Builder(metricRegistry);
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/metricsUtils.java b/server/src/main/java/org/apache/iotdb/db/metrics/metricsUtils.java
new file mode 100644
index 0000000..bc5b13a
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/metricsUtils.java
@@ -0,0 +1,61 @@
+/*
+ * 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.iotdb.db.metrics;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public class metricsUtils {
+
+  public static String generatePath(
+      String address, int rpcPort, String name, Map<String, String> labels) {
+    StringBuilder stringBuilder = new StringBuilder();
+    stringBuilder
+        .append("root._metric.\"")
+        .append(address)
+        .append(":")
+        .append(rpcPort)
+        .append("\"")
+        .append(".")
+        .append("\"")
+        .append(name)
+        .append("\"");
+    for (Map.Entry<String, String> entry : labels.entrySet()) {
+      stringBuilder
+          .append(".")
+          .append("\"")
+          .append(entry.getKey())
+          .append("=")
+          .append(entry.getValue())
+          .append("\"");
+    }
+    return stringBuilder.toString();
+  }
+
+  public static Map<String, String> emptyMap() {
+    return Collections.emptyMap();
+  }
+
+  public static Map<String, String> mapOf(String key, String value) {
+    HashMap<String, String> result = new HashMap<>();
+    result.put(key, value);
+    return result;
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBMeterRegistry.java b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBMeterRegistry.java
new file mode 100644
index 0000000..fd511cf
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBMeterRegistry.java
@@ -0,0 +1,150 @@
+/*
+ * 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.iotdb.db.metrics.micrometer.registry;
+
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.exception.StorageEngineException;
+import org.apache.iotdb.db.exception.metadata.IllegalPathException;
+import org.apache.iotdb.db.exception.metadata.StorageGroupNotSetException;
+import org.apache.iotdb.db.exception.query.QueryProcessException;
+import org.apache.iotdb.db.metadata.path.PartialPath;
+import org.apache.iotdb.db.metrics.metricsUtils;
+import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.db.service.basic.ServiceProvider;
+import org.apache.iotdb.db.utils.DataTypeUtils;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.distribution.HistogramSnapshot;
+import io.micrometer.core.instrument.step.StepMeterRegistry;
+import io.micrometer.core.instrument.step.StepRegistryConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+public class IoTDBMeterRegistry extends StepMeterRegistry {
+  private static final Logger logger = LoggerFactory.getLogger(IoTDBMeterRegistry.class);
+  private final ServiceProvider serviceProvider;
+  private final int rpcPort;
+  private final String address;
+
+  public IoTDBMeterRegistry(StepRegistryConfig config, Clock clock) {
+    super(config, clock);
+    IoTDBConfig ioTDBConfig = IoTDBDescriptor.getInstance().getConfig();
+    rpcPort = ioTDBConfig.getRpcPort();
+    address = ioTDBConfig.getRpcAddress();
+    serviceProvider = IoTDB.serviceProvider;
+  }
+
+  @Override
+  protected void publish() {
+    getMeters()
+        .forEach(
+            meter -> {
+              Meter.Id id = meter.getId();
+              String name = id.getName();
+              List<Tag> tags = id.getTags();
+              Map<String, String> labels = tagsConvertToMap(tags);
+              meter.use(
+                  gauge -> {
+                    updateValue(name, labels, gauge.value());
+                  },
+                  counter -> {
+                    updateValue(name, labels, counter.count());
+                  },
+                  timer -> {
+                    writeSnapshotAndCount(name, labels, timer.takeSnapshot());
+                  },
+                  summary -> {
+                    writeSnapshotAndCount(name, labels, summary.takeSnapshot());
+                  },
+                  longTaskTimer -> {
+                    updateValue(name, labels, (double) longTaskTimer.activeTasks());
+                  },
+                  timeGauge -> {
+                    updateValue(name, labels, timeGauge.value(getBaseTimeUnit()));
+                  },
+                  functionCounter -> {
+                    updateValue(name, labels, functionCounter.count());
+                  },
+                  functionTimer -> {
+                    updateValue(name, labels, functionTimer.count());
+                  },
+                  m -> {
+                    logger.debug("unknown meter:" + meter);
+                  });
+            });
+  }
+
+  private void writeSnapshotAndCount(
+      String name, Map<String, String> labels, HistogramSnapshot snapshot) {
+    updateValue(name + "_max", labels, snapshot.max());
+    updateValue(name + "_mean", labels, snapshot.mean());
+    updateValue(name + "_total", labels, snapshot.total());
+    updateValue(name + "_count", labels, (double) snapshot.count());
+  }
+
+  private Map<String, String> tagsConvertToMap(List<Tag> tags) {
+    Map<String, String> labels = new HashMap<>();
+    for (Tag tag : tags) {
+      labels.put(tag.getKey(), tag.getValue());
+    }
+    return labels;
+  }
+
+  private void updateValue(String name, Map<String, String> labels, Double value) {
+    if (value != null) {
+      try {
+        InsertRowPlan insertRowPlan =
+            new InsertRowPlan(
+                new PartialPath(metricsUtils.generatePath(address, rpcPort, name, labels)),
+                System.currentTimeMillis(),
+                new String[] {"value"},
+                DataTypeUtils.getValueBuffer(
+                    new ArrayList<>(Arrays.asList(TSDataType.DOUBLE)),
+                    new ArrayList<>(Arrays.asList(value))),
+                false);
+        serviceProvider.executeNonQuery(insertRowPlan);
+      } catch (IllegalPathException
+          | IoTDBConnectionException
+          | QueryProcessException
+          | StorageGroupNotSetException
+          | StorageEngineException e) {
+        logger.error("illegal insertRowPlan,reason:" + e.getMessage());
+      }
+    }
+  }
+
+  @Override
+  protected TimeUnit getBaseTimeUnit() {
+    return TimeUnit.MILLISECONDS;
+  }
+}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBRegistryConfig.java
similarity index 74%
copy from metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
copy to server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBRegistryConfig.java
index 06792ba..3546726 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/ReporterType.java
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/registry/IoTDBRegistryConfig.java
@@ -17,17 +17,15 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.utils;
+package org.apache.iotdb.db.metrics.micrometer.registry;
 
-public enum ReporterType {
-  // The name of ReporterType should same as value of metricReporterList in iotdb-metric.yml, that's
-  // why all below are in lower case.
-  jmx,
-  prometheus,
-  internal;
+import io.micrometer.core.instrument.step.StepRegistryConfig;
+
+public interface IoTDBRegistryConfig extends StepRegistryConfig {
+  IoTDBRegistryConfig DEFAULT = k -> null;
 
   @Override
-  public String toString() {
-    return name();
+  default String prefix() {
+    return "iotdb";
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/reporter/MicrometerIoTDBReporter.java b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
new file mode 100644
index 0000000..dc8be1b
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
@@ -0,0 +1,94 @@
+/*
+ * 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.iotdb.db.metrics.micrometer.reporter;
+
+import org.apache.iotdb.db.metrics.micrometer.registry.IoTDBMeterRegistry;
+import org.apache.iotdb.db.metrics.micrometer.registry.IoTDBRegistryConfig;
+import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.Reporter;
+import org.apache.iotdb.metrics.utils.ReporterType;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Metrics;
+import io.micrometer.core.instrument.util.NamedThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class MicrometerIoTDBReporter implements Reporter {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(MicrometerIoTDBReporter.class);
+  private MetricManager metricManager;
+
+  @Override
+  public boolean start() {
+    try {
+      Set<MeterRegistry> meterRegistrySet =
+          Metrics.globalRegistry.getRegistries().stream()
+              .filter(reporter -> reporter instanceof IoTDBMeterRegistry)
+              .collect(Collectors.toSet());
+      IoTDBMeterRegistry ioTDBMeterRegistry;
+      if (meterRegistrySet.size() == 0) {
+        ioTDBMeterRegistry = new IoTDBMeterRegistry(IoTDBRegistryConfig.DEFAULT, Clock.SYSTEM);
+        Metrics.addRegistry(ioTDBMeterRegistry);
+      } else {
+        ioTDBMeterRegistry = (IoTDBMeterRegistry) meterRegistrySet.toArray()[0];
+      }
+      ioTDBMeterRegistry.start(new NamedThreadFactory("iotdb-metrics-publisher"));
+    } catch (Exception e) {
+      LOGGER.error("Failed to start Micrometer IoTDBReporter, because {}", e.getMessage());
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public boolean stop() {
+    try {
+      Set<MeterRegistry> meterRegistrySet =
+          Metrics.globalRegistry.getRegistries().stream()
+              .filter(reporter -> reporter instanceof IoTDBMeterRegistry)
+              .collect(Collectors.toSet());
+      for (MeterRegistry meterRegistry : meterRegistrySet) {
+        if (!meterRegistry.isClosed()) {
+          meterRegistry.close();
+          Metrics.removeRegistry(meterRegistry);
+        }
+      }
+    } catch (Exception e) {
+      LOGGER.error("Failed to stop Micrometer IoTDBReporter, because {}", e.getMessage());
+      return false;
+    }
+    return true;
+  }
+
+  @Override
+  public ReporterType getReporterType() {
+    return ReporterType.iotdb;
+  }
+
+  @Override
+  public void setMetricManager(MetricManager metricManager) {
+    this.metricManager = metricManager;
+  }
+}
diff --git a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager b/server/src/main/resources/META-INF/services/org.apache.iotdb.metrics.Reporter
similarity index 84%
copy from metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
copy to server/src/main/resources/META-INF/services/org.apache.iotdb.metrics.Reporter
index 235ab43..13407ce 100644
--- a/metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
+++ b/server/src/main/resources/META-INF/services/org.apache.iotdb.metrics.Reporter
@@ -15,4 +15,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-org.apache.iotdb.metrics.micrometer.MicrometerMetricManager
\ No newline at end of file
+org.apache.iotdb.db.metrics.micrometer.reporter.MicrometerIoTDBReporter
+org.apache.iotdb.db.metrics.dropwizard.reporter.DropwizardIoTDBReporter