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

[iotdb] branch rel/0.13 updated: [IOTDB-5173][To rel/0.13] Support internal report and add statistic of flush point (#8415)

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

qiaojialin pushed a commit to branch rel/0.13
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/rel/0.13 by this push:
     new a63fbaffae [IOTDB-5173][To rel/0.13] Support internal report and add statistic of flush point (#8415)
a63fbaffae is described below

commit a63fbaffaef31c414b5e6b3e34eeddc563a5a43f
Author: ZhangHongYin <46...@users.noreply.github.com>
AuthorDate: Fri Dec 16 13:12:15 2022 +0800

    [IOTDB-5173][To rel/0.13] Support internal report and add statistic of flush point (#8415)
---
 docs/UserGuide/Maintenance-Tools/Metric-Tool.md    |   6 +-
 docs/zh/UserGuide/Maintenance-Tools/Metric-Tool.md |   8 +-
 .../dropwizard/type/DropwizardAutoGauge.java       |   4 +-
 .../main/assembly/resources/conf/iotdb-metric.yml  |   3 +
 .../iotdb/metrics/AbstractMetricManager.java       |  96 +++-----------
 .../iotdb/metrics/AbstractMetricService.java       | 105 +++++++++++++--
 .../iotdb/metrics/DoNothingMetricService.java      |   6 +
 .../apache/iotdb/metrics/config/MetricConfig.java  |  19 ++-
 .../metrics/config/MetricConfigDescriptor.java     |  17 +--
 .../iotdb/metrics/impl/DoNothingCounter.java       |   2 +-
 .../apache/iotdb/metrics/impl/DoNothingGauge.java  |   2 +-
 .../iotdb/metrics/impl/DoNothingHistogram.java     |   2 +-
 .../apache/iotdb/metrics/impl/DoNothingMetric.java |  13 +-
 .../apache/iotdb/metrics/impl/DoNothingRate.java   |   2 +-
 .../apache/iotdb/metrics/impl/DoNothingTimer.java  |   2 +-
 .../metrics/reporter/InternalIoTDBReporter.java    | 137 ++++++++++++++++++++
 .../MemoryInternalIoTDBReporter.java}              |  37 +++---
 .../org/apache/iotdb/metrics/type/AutoGauge.java   |  13 +-
 .../org/apache/iotdb/metrics/type/Counter.java     |   7 +
 .../java/org/apache/iotdb/metrics/type/Gauge.java  |   7 +
 .../org/apache/iotdb/metrics/type/Histogram.java   |   8 ++
 .../iotdb/metrics/type/HistogramSnapshot.java      |  16 ++-
 .../org/apache/iotdb/metrics/type/IMetric.java     |   8 +-
 .../java/org/apache/iotdb/metrics/type/Rate.java   |  11 ++
 .../java/org/apache/iotdb/metrics/type/Timer.java  |   7 +
 .../iotdb/metrics/utils/IoTDBMetricsUtils.java     |  53 ++++++--
 .../org/apache/iotdb/metrics/utils/MetricInfo.java |  19 ++-
 .../org/apache/iotdb/metrics/utils/MetricType.java |   1 +
 .../iotdb/metrics/config/MetricConfigTest.java     |   1 +
 .../interface/src/test/resources/iotdb-metric.yml  |   3 +
 .../micrometer/type/MicrometerAutoGauge.java       |   4 +-
 .../iotdb/db/engine/flush/MemTableFlushTask.java   |  17 +++
 .../java/org/apache/iotdb/db/service/IoTDB.java    |   5 +
 .../db/service/metrics/IoTDBInternalReporter.java  | 143 +++++++++++++++++++++
 .../iotdb/db/service/metrics/MetricService.java    |   9 ++
 .../iotdb/db/service/metrics/enums/Metric.java     |   1 +
 .../apache/iotdb/db/service/metrics/enums/Tag.java |   3 +-
 .../apache/iotdb/db/metric/MetricServiceTest.java  |  50 +++----
 38 files changed, 637 insertions(+), 210 deletions(-)

diff --git a/docs/UserGuide/Maintenance-Tools/Metric-Tool.md b/docs/UserGuide/Maintenance-Tools/Metric-Tool.md
index 482c717752..60fbdde000 100644
--- a/docs/UserGuide/Maintenance-Tools/Metric-Tool.md
+++ b/docs/UserGuide/Maintenance-Tools/Metric-Tool.md
@@ -113,8 +113,9 @@ Next, we will choose Prometheus format data as samples to describe each kind of
 #### 1.3.3.5. Business Data
 
 | Metric   | Tag                                                                 | level     | Description                                                   | Sample                                        |
-| -------- | ------------------------------------------------------------------- | --------- | ------------------------------------------------------------- | --------------------------------------------- |
+| -------- |---------------------------------------------------------------------|-----------|---------------------------------------------------------------|-----------------------------------------------|
 | quantity | name="timeSeries/storageGroup/device", type="total/normal/template" | important | The current count of timeSeries/storageGroup/devices in IoTDB | quantity{name="timeSeries",type="normal"} 1.0 |
+| quantity | sg="{{storageGroup}}", type="flush"                                 | core      | The point number of last flushed memtable                     | quantity{name="memtable",type="flush"} 1.0    |
 
 #### 1.3.3.6. Cluster
 
@@ -257,6 +258,9 @@ predefinedMetrics:
 # The http server's port for prometheus exporter to get metric data.
 prometheusExporterPort: 9091
 
+# whether store predefined metrics locally
+isStoreToLocal: false
+
 # The config of iotdb reporter
 ioTDBReporterConfig:
   host: 127.0.0.1
diff --git a/docs/zh/UserGuide/Maintenance-Tools/Metric-Tool.md b/docs/zh/UserGuide/Maintenance-Tools/Metric-Tool.md
index 75523908c6..fe03ffe83d 100644
--- a/docs/zh/UserGuide/Maintenance-Tools/Metric-Tool.md
+++ b/docs/zh/UserGuide/Maintenance-Tools/Metric-Tool.md
@@ -111,9 +111,10 @@ IoTDB对外提供JMX和Prometheus格式的监控指标,对于JMX,可以通
 
 #### 1.3.3.5. 业务数据
 
-| Metric   | Tag                                                                 | level     | 说明                                         | 示例                                          |
-| -------- | ------------------------------------------------------------------- | --------- | -------------------------------------------- | --------------------------------------------- |
+| Metric   | Tag                                                                 | level     | 说明                                    | 示例                                          |
+| -------- |---------------------------------------------------------------------| --------- |---------------------------------------| --------------------------------------------- |
 | quantity | name="timeSeries/storageGroup/device", type="total/normal/template" | important | 当前时间timeSeries/storageGroup/device的数量 | quantity{name="timeSeries",type="normal"} 1.0 |
+| quantity | sg="{{storageGroup}}", type="flush"                                 | core      | 最新一个刷盘的memtale的点数                     | quantity{name="memtable",type="flush"} 1.0    |
 
 #### 1.3.3.6. 集群
 
@@ -258,6 +259,9 @@ predefinedMetrics:
 # Prometheus Reporter 使用的端口
 prometheusExporterPort: 9091
 
+# 是否将预设置的监控指标写回 IoTDB
+isStoreToLocal: false
+
 # IoTDB Reporter相关的配置
 ioTDBReporterConfig:
   host: 127.0.0.1
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/type/DropwizardAutoGauge.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/type/DropwizardAutoGauge.java
index c1a92cd1a8..ccf6f21d54 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/type/DropwizardAutoGauge.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/type/DropwizardAutoGauge.java
@@ -19,12 +19,12 @@
 
 package org.apache.iotdb.metrics.dropwizard.type;
 
-import org.apache.iotdb.metrics.type.Gauge;
+import org.apache.iotdb.metrics.type.AutoGauge;
 
 import java.lang.ref.WeakReference;
 import java.util.function.ToLongFunction;
 
-public class DropwizardAutoGauge<T> implements Gauge, com.codahale.metrics.Gauge<Long> {
+public class DropwizardAutoGauge<T> implements AutoGauge, com.codahale.metrics.Gauge<Long> {
 
   private final WeakReference<T> refObject;
   private final ToLongFunction<T> mapper;
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 fa70b812f9..a0f90cf207 100644
--- a/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
+++ b/metrics/interface/src/main/assembly/resources/conf/iotdb-metric.yml
@@ -45,6 +45,9 @@ asyncCollectPeriodInSecond: 5
 # The http server's port for prometheus exporter to get metric data.
 prometheusExporterPort: 9091
 
+# whether store predefined metrics locally
+isStoreToLocal: false
+
 # The config of iotdb reporter
 ioTDBReporterConfig:
   host: 127.0.0.1
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricManager.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricManager.java
index ec1c764b67..de0c3f2ff0 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricManager.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricManager.java
@@ -31,6 +31,7 @@ import org.apache.iotdb.metrics.type.Timer;
 import org.apache.iotdb.metrics.utils.MetricInfo;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.metrics.utils.MetricType;
+import org.apache.iotdb.tsfile.utils.Pair;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -251,9 +252,10 @@ public abstract class AbstractMetricManager {
    * @param metricLevel the level of name
    * @param tags string pairs, like sg="ln" will be "sg", "ln"
    */
-  public void count(long delta, String name, MetricLevel metricLevel, String... tags) {
+  public Counter count(long delta, String name, MetricLevel metricLevel, String... tags) {
     Counter counter = getOrCreateCounter(name, metricLevel, tags);
     counter.inc(delta);
+    return counter;
   }
 
   /**
@@ -264,9 +266,10 @@ public abstract class AbstractMetricManager {
    * @param metricLevel the level of name
    * @param tags string pairs, like sg="ln" will be "sg", "ln"
    */
-  public void gauge(long value, String name, MetricLevel metricLevel, String... tags) {
+  public Gauge gauge(long value, String name, MetricLevel metricLevel, String... tags) {
     Gauge gauge = getOrCreateGauge(name, metricLevel, tags);
     gauge.set(value);
+    return gauge;
   }
 
   /**
@@ -277,9 +280,10 @@ public abstract class AbstractMetricManager {
    * @param metricLevel the level of name
    * @param tags string pairs, like sg="ln" will be "sg", "ln"
    */
-  public void rate(long value, String name, MetricLevel metricLevel, String... tags) {
+  public Rate rate(long value, String name, MetricLevel metricLevel, String... tags) {
     Rate rate = getOrCreateRate(name, metricLevel, tags);
     rate.mark(value);
+    return rate;
   }
 
   /**
@@ -290,9 +294,10 @@ public abstract class AbstractMetricManager {
    * @param metricLevel the level of name
    * @param tags string pairs, like sg="ln" will be "sg", "ln"
    */
-  public void histogram(long value, String name, MetricLevel metricLevel, String... tags) {
+  public Histogram histogram(long value, String name, MetricLevel metricLevel, String... tags) {
     Histogram histogram = getOrCreateHistogram(name, metricLevel, tags);
     histogram.update(value);
+    return histogram;
   }
 
   /**
@@ -305,10 +310,11 @@ public abstract class AbstractMetricManager {
    * @param metricLevel the level of name
    * @param tags string pairs, like sg="ln" will be "sg", "ln"
    */
-  public void timer(
+  public Timer timer(
       long delta, TimeUnit timeUnit, String name, MetricLevel metricLevel, String... tags) {
     Timer timer = getOrCreateTimer(name, metricLevel, tags);
     timer.update(delta, timeUnit);
+    return timer;
   }
 
   // endregion
@@ -320,85 +326,21 @@ public abstract class AbstractMetricManager {
    *
    * @return [[name, tags...], ..., [name, tags...]]
    */
-  protected List<String[]> getAllMetricKeys() {
-    List<String[]> keys = new ArrayList<>(metrics.size());
+  protected List<Pair<String, String[]>> getAllMetricKeys() {
+    List<Pair<String, String[]>> keys = new ArrayList<>(metrics.size());
     metrics.keySet().forEach(k -> keys.add(k.toStringArray()));
     return keys;
   }
 
-  /**
-   * Get all counters
-   *
-   * @return [name, tags...] -> counter
-   */
-  protected Map<String[], Counter> getAllCounters() {
-    Map<String[], Counter> counterMap = new HashMap<>();
-    for (Map.Entry<MetricInfo, IMetric> entry : metrics.entrySet()) {
-      if (entry.getValue() instanceof Counter) {
-        counterMap.put(entry.getKey().toStringArray(), (Counter) entry.getValue());
-      }
-    }
-    return counterMap;
-  }
-
-  /**
-   * Get all gauges
-   *
-   * @return [name, tags...] -> gauge
-   */
-  protected Map<String[], Gauge> getAllGauges() {
-    Map<String[], Gauge> gaugeMap = new HashMap<>();
-    for (Map.Entry<MetricInfo, IMetric> entry : metrics.entrySet()) {
-      if (entry.getValue() instanceof Gauge) {
-        gaugeMap.put(entry.getKey().toStringArray(), (Gauge) entry.getValue());
-      }
-    }
-    return gaugeMap;
-  }
-
-  /**
-   * Get all rates
-   *
-   * @return [name, tags...] -> rate
-   */
-  protected Map<String[], Rate> getAllRates() {
-    Map<String[], Rate> rateMap = new HashMap<>();
-    for (Map.Entry<MetricInfo, IMetric> entry : metrics.entrySet()) {
-      if (entry.getValue() instanceof Rate) {
-        rateMap.put(entry.getKey().toStringArray(), (Rate) entry.getValue());
-      }
-    }
-    return rateMap;
-  }
-
-  /**
-   * Get all histograms
-   *
-   * @return [name, tags...] -> histogram
-   */
-  protected Map<String[], Histogram> getAllHistograms() {
-    Map<String[], Histogram> histogramMap = new HashMap<>();
-    for (Map.Entry<MetricInfo, IMetric> entry : metrics.entrySet()) {
-      if (entry.getValue() instanceof Histogram) {
-        histogramMap.put(entry.getKey().toStringArray(), (Histogram) entry.getValue());
-      }
-    }
-    return histogramMap;
-  }
-
-  /**
-   * Get all timers
-   *
-   * @return [name, tags...] -> timer
-   */
-  protected Map<String[], Timer> getAllTimers() {
-    Map<String[], Timer> timerMap = new HashMap<>();
+  /** Get metric by type */
+  public Map<MetricInfo, IMetric> getMetricsByType(MetricType metricType) {
+    Map<MetricInfo, IMetric> metricInfoIMetricMap = new HashMap<>();
     for (Map.Entry<MetricInfo, IMetric> entry : metrics.entrySet()) {
-      if (entry.getValue() instanceof Timer) {
-        timerMap.put(entry.getKey().toStringArray(), (Timer) entry.getValue());
+      if (entry.getKey().getMetaInfo().getType() == metricType) {
+        metricInfoIMetricMap.put(entry.getKey(), entry.getValue());
       }
     }
-    return timerMap;
+    return metricInfoIMetricMap;
   }
 
   // endregion
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
index bd610bc3fc..91a297647b 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
@@ -26,15 +26,20 @@ import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
 import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.reporter.CompositeReporter;
+import org.apache.iotdb.metrics.reporter.InternalIoTDBReporter;
+import org.apache.iotdb.metrics.reporter.MemoryInternalIoTDBReporter;
 import org.apache.iotdb.metrics.reporter.Reporter;
 import org.apache.iotdb.metrics.type.Counter;
 import org.apache.iotdb.metrics.type.Gauge;
 import org.apache.iotdb.metrics.type.Histogram;
+import org.apache.iotdb.metrics.type.IMetric;
 import org.apache.iotdb.metrics.type.Rate;
 import org.apache.iotdb.metrics.type.Timer;
+import org.apache.iotdb.metrics.utils.MetricInfo;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.metrics.utils.MetricType;
 import org.apache.iotdb.metrics.utils.ReporterType;
+import org.apache.iotdb.tsfile.utils.Pair;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,6 +61,8 @@ public abstract class AbstractMetricService {
   protected AbstractMetricManager metricManager = new DoNothingMetricManager();
   /** The metric reporter of metric service */
   protected CompositeReporter compositeReporter = new CompositeReporter();
+  /** The internal reporter of metric service */
+  protected InternalIoTDBReporter internalReporter = new MemoryInternalIoTDBReporter();
   /** Is metric service enabled */
   protected boolean isEnableMetric = metricConfig.getEnableMetric();
   /** The list of metric sets */
@@ -249,28 +256,102 @@ public abstract class AbstractMetricService {
     metricManager.timer(delta, timeUnit, metric, metricLevel, tags);
   }
 
-  public List<String[]> getAllMetricKeys() {
-    return metricManager.getAllMetricKeys();
+  /** GetOrCreateCounter with internal report */
+  public Counter getOrCreateCounterWithInternalReport(
+      String metric, MetricLevel metricLevel, String... tags) {
+    Counter counter = metricManager.getOrCreateCounter(metric, metricLevel, tags);
+    internalReporter.writeMetricToIoTDB(counter, metric, tags);
+    return counter;
+  }
+
+  public <T> Gauge getOrCreateAutoGaugeWithInternalReport(
+      String metric, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags) {
+    Gauge gauge = metricManager.getOrCreateAutoGauge(metric, metricLevel, obj, mapper, tags);
+    internalReporter.addAutoGauge(gauge, metric, tags);
+    return gauge;
+  }
+
+  /** GetOrCreateGauge with internal report */
+  public Gauge getOrCreateGaugeWithInternalReport(
+      String metric, MetricLevel metricLevel, String... tags) {
+    Gauge gauge = metricManager.getOrCreateGauge(metric, metricLevel, tags);
+    internalReporter.writeMetricToIoTDB(gauge, metric, tags);
+
+    return gauge;
+  }
+
+  /** GetOrCreateRate with internal report */
+  public Rate getOrCreateRateWithInternalReport(
+      String metric, MetricLevel metricLevel, String... tags) {
+    Rate rate = metricManager.getOrCreateRate(metric, metricLevel, tags);
+    internalReporter.writeMetricToIoTDB(rate, metric, tags);
+    return rate;
+  }
+
+  /** GetOrCreateHistogram with internal report */
+  public Histogram getOrCreateHistogramWithInternalReport(
+      String metric, MetricLevel metricLevel, String... tags) {
+    Histogram histogram = metricManager.getOrCreateHistogram(metric, metricLevel, tags);
+    internalReporter.writeMetricToIoTDB(histogram, metric, tags);
+    return histogram;
+  }
+
+  /** GetOrCreateTimer with internal report */
+  public Timer getOrCreateTimerWithInternalReport(
+      String metric, MetricLevel metricLevel, String... tags) {
+    Timer timer = metricManager.getOrCreateTimer(metric, metricLevel, tags);
+    internalReporter.writeMetricToIoTDB(timer, metric, tags);
+    return timer;
+  }
+
+  /** Count with internal report */
+  public void countWithInternalReport(
+      long delta, String metric, MetricLevel metricLevel, String... tags) {
+    internalReporter.writeMetricToIoTDB(
+        metricManager.count(delta, metric, metricLevel, tags), metric, tags);
   }
 
-  public Map<String[], Counter> getAllCounters() {
-    return metricManager.getAllCounters();
+  /** Gauge value with internal report */
+  public void gaugeWithInternalReport(
+      long value, String metric, MetricLevel metricLevel, String... tags) {
+    internalReporter.writeMetricToIoTDB(
+        metricManager.gauge(value, metric, metricLevel, tags), metric, tags);
   }
 
-  public Map<String[], Gauge> getAllGauges() {
-    return metricManager.getAllGauges();
+  /** Rate with internal report */
+  public void rateWithInternalReport(
+      long value, String metric, MetricLevel metricLevel, String... tags) {
+    internalReporter.writeMetricToIoTDB(
+        metricManager.rate(value, metric, metricLevel, tags), metric, tags);
   }
 
-  public Map<String[], Rate> getAllRates() {
-    return metricManager.getAllRates();
+  /** Histogram with internal report */
+  public void histogramWithInternalReport(
+      long value, String metric, MetricLevel metricLevel, String... tags) {
+    internalReporter.writeMetricToIoTDB(
+        metricManager.histogram(value, metric, metricLevel, tags), metric, tags);
   }
 
-  public Map<String[], Histogram> getAllHistograms() {
-    return metricManager.getAllHistograms();
+  /** Timer with internal report */
+  public void timerWithInternalReport(
+      long delta, TimeUnit timeUnit, String metric, MetricLevel metricLevel, String... tags) {
+    internalReporter.writeMetricToIoTDB(
+        metricManager.timer(delta, timeUnit, metric, metricLevel, tags), metric, tags);
+  }
+
+  /**
+   * Reload internal reporter
+   *
+   * @param internalReporter the new internal reporter
+   */
+  public abstract void reloadInternalReporter(InternalIoTDBReporter internalReporter);
+
+  public List<Pair<String, String[]>> getAllMetricKeys() {
+    return metricManager.getAllMetricKeys();
   }
 
-  public Map<String[], Timer> getAllTimers() {
-    return metricManager.getAllTimers();
+  public Map<MetricInfo, IMetric> getMetricsByType(MetricType metricType) {
+    return metricManager.getMetricsByType(metricType);
   }
 
   public void remove(MetricType type, String metric, String... tags) {
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/DoNothingMetricService.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/DoNothingMetricService.java
index b6e4baf066..0c87b710f3 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/DoNothingMetricService.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/DoNothingMetricService.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.metrics;
 
 import org.apache.iotdb.metrics.config.ReloadLevel;
 import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.reporter.InternalIoTDBReporter;
 
 public class DoNothingMetricService extends AbstractMetricService {
 
@@ -33,4 +34,9 @@ public class DoNothingMetricService extends AbstractMetricService {
   protected void reloadProperties(ReloadLevel reloadLevel) {
     // do nothing
   }
+
+  @Override
+  public void reloadInternalReporter(InternalIoTDBReporter internalReporter) {
+    // do nothing
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
index df74e5e002..ef4c0625ec 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfig.java
@@ -57,6 +57,9 @@ public class MetricConfig {
   /** The config for iotdb reporter to push metric data */
   private IoTDBReporterConfig ioTDBReporterConfig = new IoTDBReporterConfig();
 
+  /** Whether store predefined metrics locally */
+  private Boolean isStoreToLocal = false;
+
   public static class IoTDBReporterConfig {
     /** The host of iotdb that store metric value */
     private String host = "127.0.0.1";
@@ -159,13 +162,15 @@ public class MetricConfig {
 
   public void copy(MetricConfig newMetricConfig) {
     enableMetric = newMetricConfig.getEnableMetric();
+    enablePerformanceStat = newMetricConfig.getEnablePerformanceStat();
     monitorType = newMetricConfig.getMonitorType();
     metricReporterList = newMetricConfig.getMetricReporterList();
     metricLevel = newMetricConfig.getMetricLevel();
     predefinedMetrics = newMetricConfig.getPredefinedMetrics();
     asyncCollectPeriodInSecond = newMetricConfig.getAsyncCollectPeriodInSecond();
     prometheusExporterPort = newMetricConfig.getPrometheusExporterPort();
-    ioTDBReporterConfig = newMetricConfig.ioTDBReporterConfig;
+    ioTDBReporterConfig = newMetricConfig.getIoTDBReporterConfig();
+    isStoreToLocal = newMetricConfig.isStoreToLocal();
   }
 
   public void updateRpcInstance(String rpcAddress, int rpcPort) {
@@ -253,6 +258,14 @@ public class MetricConfig {
     return rpcPort;
   }
 
+  public boolean isStoreToLocal() {
+    return isStoreToLocal;
+  }
+
+  public void setIsStoreToLocal(boolean storeToLocal) {
+    isStoreToLocal = storeToLocal;
+  }
+
   @Override
   public boolean equals(Object obj) {
     if (!(obj instanceof MetricConfig)) {
@@ -260,12 +273,14 @@ public class MetricConfig {
     }
     MetricConfig anotherMetricConfig = (MetricConfig) obj;
     return enableMetric.equals(anotherMetricConfig.getEnableMetric())
+        && enablePerformanceStat.equals(anotherMetricConfig.getEnablePerformanceStat())
         && monitorType.equals(anotherMetricConfig.getMonitorType())
         && metricReporterList.equals(anotherMetricConfig.getMetricReporterList())
         && metricLevel.equals(anotherMetricConfig.getMetricLevel())
         && predefinedMetrics.equals(anotherMetricConfig.getPredefinedMetrics())
         && asyncCollectPeriodInSecond.equals(anotherMetricConfig.getAsyncCollectPeriodInSecond())
         && prometheusExporterPort.equals(anotherMetricConfig.getPrometheusExporterPort())
-        && ioTDBReporterConfig.equals(anotherMetricConfig.getIoTDBReporterConfig());
+        && ioTDBReporterConfig.equals(anotherMetricConfig.getIoTDBReporterConfig())
+        && isStoreToLocal.equals(anotherMetricConfig.isStoreToLocal());
   }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
index d729f0d02e..871fdf1e53 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/MetricConfigDescriptor.java
@@ -102,7 +102,7 @@ public class MetricConfigDescriptor {
 
   /** get the path of metric config file. */
   private String getPropsUrl() {
-    // first, try to get conf folder of standalone iotdb or datanode
+    // try to get conf folder of standalone iotdb or datanode
     String url = System.getProperty(MetricConstant.IOTDB_CONF, null);
     if (url == null) {
       // try to get conf folder from IOTDB_HOME
@@ -111,21 +111,10 @@ public class MetricConfigDescriptor {
         url += File.separator + "conf";
       }
     }
-    // second, try to get conf folder of datanode
-    if (url == null) {
-      url = System.getProperty(MetricConstant.CONFIGNODE_CONF, null);
-      if (url == null) {
-        // try to get conf folder from CONFIGNODE_HOME
-        url = System.getProperty(MetricConstant.CONFIGNODE_HOME, null);
-        if (url != null) {
-          url += File.separator + "conf";
-        }
-      }
-    }
-    // finally, return null when not find
+    // return null when not find
     if (url == null) {
       logger.warn(
-          "Cannot find IOTDB_CONF and CONFIGNODE_CONF environment variable when loading "
+          "Cannot find IOTDB_CONF environment variable when loading "
               + "config file {}, use default configuration",
           MetricConstant.CONFIG_NAME);
       return null;
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingCounter.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingCounter.java
index e9047bd34c..942ce0c238 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingCounter.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingCounter.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.metrics.impl;
 
 import org.apache.iotdb.metrics.type.Counter;
 
-public class DoNothingCounter implements Counter {
+public class DoNothingCounter implements Counter, DoNothingMetric {
   @Override
   public void inc() {
     // do nothing
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingGauge.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingGauge.java
index 10e917d093..c1519f1a70 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingGauge.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingGauge.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.metrics.impl;
 
 import org.apache.iotdb.metrics.type.Gauge;
 
-public class DoNothingGauge implements Gauge {
+public class DoNothingGauge implements Gauge, DoNothingMetric {
   @Override
   public long value() {
     return 0;
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingHistogram.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingHistogram.java
index a95ca800d1..05f7833534 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingHistogram.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingHistogram.java
@@ -22,7 +22,7 @@ package org.apache.iotdb.metrics.impl;
 import org.apache.iotdb.metrics.type.Histogram;
 import org.apache.iotdb.metrics.type.HistogramSnapshot;
 
-public class DoNothingHistogram implements Histogram {
+public class DoNothingHistogram implements Histogram, DoNothingMetric {
 
   @Override
   public void update(long value) {
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetric.java
similarity index 81%
copy from server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
copy to metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetric.java
index cb2db3a578..7aae89c15f 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetric.java
@@ -17,15 +17,8 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.service.metrics.enums;
+package org.apache.iotdb.metrics.impl;
 
-public enum Tag {
-  TYPE,
-  NAME,
-  STATUS;
+import org.apache.iotdb.metrics.type.IMetric;
 
-  @Override
-  public String toString() {
-    return super.toString().toLowerCase();
-  }
-}
+public interface DoNothingMetric extends IMetric {}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java
index 533947bf62..5e58154faa 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java
@@ -21,7 +21,7 @@ package org.apache.iotdb.metrics.impl;
 
 import org.apache.iotdb.metrics.type.Rate;
 
-public class DoNothingRate implements Rate {
+public class DoNothingRate implements Rate, DoNothingMetric {
   @Override
   public long getCount() {
     return 0;
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingTimer.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingTimer.java
index a52b47460b..b5896b800e 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingTimer.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingTimer.java
@@ -25,7 +25,7 @@ import org.apache.iotdb.metrics.type.Timer;
 
 import java.util.concurrent.TimeUnit;
 
-public class DoNothingTimer implements Timer {
+public class DoNothingTimer implements Timer, DoNothingMetric {
   @Override
   public void update(long duration, TimeUnit unit) {
     // do nothing
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/InternalIoTDBReporter.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/InternalIoTDBReporter.java
new file mode 100644
index 0000000000..922e48a139
--- /dev/null
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/InternalIoTDBReporter.java
@@ -0,0 +1,137 @@
+/*
+ * 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.metrics.reporter;
+
+import org.apache.iotdb.metrics.impl.DoNothingMetric;
+import org.apache.iotdb.metrics.type.Gauge;
+import org.apache.iotdb.metrics.type.IMetric;
+import org.apache.iotdb.metrics.utils.IoTDBMetricsUtils;
+import org.apache.iotdb.metrics.utils.MetricInfo;
+import org.apache.iotdb.metrics.utils.MetricType;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public abstract class InternalIoTDBReporter implements Reporter {
+  protected final Map<MetricInfo, IMetric> autoGauges = new ConcurrentHashMap<>();
+
+  /**
+   * Add autoGauge into internal reporter
+   *
+   * @param autoGauge autoGauge
+   * @param name the name of autoGauge
+   * @param tags the tags of autoGauge
+   */
+  public void addAutoGauge(Gauge autoGauge, String name, String... tags) {
+    MetricInfo metricInfo = new MetricInfo(MetricType.AUTO_GAUGE, name, tags);
+    autoGauges.put(metricInfo, autoGauge);
+  }
+
+  /**
+   * Add autoGauges into internal reporter
+   *
+   * @param gauges the map of autoGauge
+   */
+  public void addAutoGauge(Map<MetricInfo, IMetric> gauges) {
+    autoGauges.putAll(gauges);
+  }
+
+  /** Get all autoGauges */
+  public Map<MetricInfo, IMetric> getAllAutoGauge() {
+    return autoGauges;
+  }
+
+  /** Clear all autoGauges */
+  public void clear() {
+    autoGauges.clear();
+  }
+
+  /**
+   * Write metric into IoTDB
+   *
+   * @param metric the target metric
+   * @param name the name of metric
+   * @param tags the tags of metric
+   */
+  public void writeMetricToIoTDB(IMetric metric, String name, String... tags) {
+    if (!(metric instanceof DoNothingMetric)) {
+      Map<String, Object> values = new HashMap<>();
+      metric.constructValueMap(values);
+      writeMetricToIoTDB(
+          values, IoTDBMetricsUtils.generatePath(name, tags), System.currentTimeMillis());
+    }
+  }
+
+  /**
+   * Write metric into IoTDB
+   *
+   * @param valueMap sensor -> value
+   * @param prefix device
+   * @param time write time
+   */
+  protected abstract void writeMetricToIoTDB(
+      Map<String, Object> valueMap, String prefix, long time);
+
+  /**
+   * Write metrics into IoTDB
+   *
+   * @param metricMap metricInfo -> IMetric
+   */
+  public void writeMetricToIoTDB(Map<MetricInfo, IMetric> metricMap) {
+    Map<String, Map<String, Object>> values = new HashMap<>();
+    for (Map.Entry<MetricInfo, IMetric> metricEntry : metricMap.entrySet()) {
+      String prefix = IoTDBMetricsUtils.generatePath(metricEntry.getKey());
+      IMetric metric = metricEntry.getValue();
+      if (!(metric instanceof DoNothingMetric)) {
+        Map<String, Object> value = new HashMap<>();
+        metric.constructValueMap(value);
+        values.put(prefix, value);
+      }
+    }
+    writeMetricsToIoTDB(values, System.currentTimeMillis());
+  }
+
+  /**
+   * Write metrics into IoTDB
+   *
+   * @param valueMap device -> sensor -> value
+   * @param time write time
+   */
+  protected abstract void writeMetricsToIoTDB(Map<String, Map<String, Object>> valueMap, long time);
+
+  /** Infer type from object */
+  protected TSDataType inferType(Object value) {
+    TSDataType dataType;
+    if (value instanceof Boolean) {
+      dataType = TSDataType.BOOLEAN;
+    } else if (value instanceof Integer) {
+      dataType = TSDataType.INT32;
+    } else if (value instanceof Long) {
+      dataType = TSDataType.INT64;
+    } else if (value instanceof Double) {
+      dataType = TSDataType.DOUBLE;
+    } else {
+      dataType = TSDataType.TEXT;
+    }
+    return dataType;
+  }
+}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/MemoryInternalIoTDBReporter.java
similarity index 55%
copy from metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java
copy to metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/MemoryInternalIoTDBReporter.java
index 533947bf62..2f089a36f1 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingRate.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/MemoryInternalIoTDBReporter.java
@@ -7,7 +7,7 @@
  * "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
+ *     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
@@ -17,43 +17,42 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.impl;
+package org.apache.iotdb.metrics.reporter;
 
-import org.apache.iotdb.metrics.type.Rate;
+import org.apache.iotdb.metrics.AbstractMetricManager;
+import org.apache.iotdb.metrics.utils.ReporterType;
 
-public class DoNothingRate implements Rate {
-  @Override
-  public long getCount() {
-    return 0;
-  }
+import java.util.Map;
+
+public class MemoryInternalIoTDBReporter extends InternalIoTDBReporter {
 
   @Override
-  public double getOneMinuteRate() {
-    return 0;
+  protected void writeMetricToIoTDB(Map<String, Object> valueMap, String prefix, long time) {
+    // do nothing
   }
 
   @Override
-  public double getMeanRate() {
-    return 0;
+  protected void writeMetricsToIoTDB(Map<String, Map<String, Object>> valueMap, long time) {
+    // do nothing
   }
 
   @Override
-  public double getFiveMinuteRate() {
-    return 0;
+  public boolean start() {
+    return false;
   }
 
   @Override
-  public double getFifteenMinuteRate() {
-    return 0;
+  public boolean stop() {
+    return false;
   }
 
   @Override
-  public void mark() {
-    // do nothing
+  public ReporterType getReporterType() {
+    return ReporterType.IOTDB;
   }
 
   @Override
-  public void mark(long n) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     // do nothing
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/AutoGauge.java
similarity index 81%
copy from server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
copy to metrics/interface/src/main/java/org/apache/iotdb/metrics/type/AutoGauge.java
index cb2db3a578..4f6c0a443f 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/AutoGauge.java
@@ -17,15 +17,6 @@
  * under the License.
  */
 
-package org.apache.iotdb.db.service.metrics.enums;
+package org.apache.iotdb.metrics.type;
 
-public enum Tag {
-  TYPE,
-  NAME,
-  STATUS;
-
-  @Override
-  public String toString() {
-    return super.toString().toLowerCase();
-  }
-}
+public interface AutoGauge extends Gauge {}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Counter.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Counter.java
index dc01ba6b20..1ec34a69e0 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Counter.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Counter.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.metrics.type;
 
+import java.util.Map;
+
 public interface Counter extends IMetric {
 
   /** counter add 1 */
@@ -29,4 +31,9 @@ public interface Counter extends IMetric {
 
   /** get the value of counter */
   long count();
+
+  @Override
+  default void constructValueMap(Map<String, Object> result) {
+    result.put("value", count());
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Gauge.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Gauge.java
index 9c4c5b768b..e373a564cb 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Gauge.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Gauge.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.metrics.type;
 
+import java.util.Map;
+
 public interface Gauge extends IMetric {
 
   /** set value */
@@ -32,4 +34,9 @@ public interface Gauge extends IMetric {
 
   /** decrease the value stored in gauge */
   void decr(long value);
+
+  @Override
+  default void constructValueMap(Map<String, Object> result) {
+    result.put("value", value());
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Histogram.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Histogram.java
index ac782cde06..9d62808857 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Histogram.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Histogram.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.metrics.type;
 
+import java.util.Map;
+
 public interface Histogram extends IMetric {
 
   /** update histogram by value */
@@ -29,4 +31,10 @@ public interface Histogram extends IMetric {
 
   /** take snapshot of histogram */
   HistogramSnapshot takeSnapshot();
+
+  @Override
+  default void constructValueMap(Map<String, Object> result) {
+    result.put("count", count());
+    takeSnapshot().constructValueMap(result);
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/HistogramSnapshot.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/HistogramSnapshot.java
index 0bfe7ff4f7..213469a211 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/HistogramSnapshot.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/HistogramSnapshot.java
@@ -20,9 +20,11 @@
 package org.apache.iotdb.metrics.type;
 
 import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Map;
 
 /** used by timer and histogram. */
-public interface HistogramSnapshot {
+public interface HistogramSnapshot extends IMetric {
 
   /** get value by quantile */
   double getValue(double quantile);
@@ -47,4 +49,16 @@ public interface HistogramSnapshot {
 
   /** writes the values of the snapshot to the given stream */
   void dump(OutputStream output);
+
+  @Override
+  default void constructValueMap(Map<String, Object> result) {
+    result.put("max", getMax());
+    result.put("sum", Arrays.stream(getValues()).sum());
+
+    result.put("p0", getValue(0.0));
+    result.put("p25", getValue(0.25));
+    result.put("p50", getValue(0.5));
+    result.put("p75", getValue(0.75));
+    result.put("p100", getValue(1.0));
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/IMetric.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/IMetric.java
index 1d5c2cd9a7..0b13de743c 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/IMetric.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/IMetric.java
@@ -19,12 +19,8 @@
 
 package org.apache.iotdb.metrics.type;
 
-import org.apache.iotdb.metrics.utils.OutPutFormat;
+import java.util.Map;
 
 public interface IMetric {
-
-  /** format metric into string */
-  default StringBuffer toString(OutPutFormat format) {
-    return new StringBuffer();
-  }
+  void constructValueMap(Map<String, Object> result);
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Rate.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Rate.java
index a68e003da2..0120ba4c6e 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Rate.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Rate.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.metrics.type;
 
+import java.util.Map;
+
 public interface Rate extends IMetric {
 
   /** get the value of rate */
@@ -41,4 +43,13 @@ public interface Rate extends IMetric {
 
   /** mark n in rate */
   void mark(long n);
+
+  @Override
+  default void constructValueMap(Map<String, Object> result) {
+    result.put("count", getCount());
+    result.put("mean", getMeanRate());
+    result.put("m1", getOneMinuteRate());
+    result.put("m5", getFiveMinuteRate());
+    result.put("m15", getFifteenMinuteRate());
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Timer.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Timer.java
index 986df3a8e1..5a696b5d3f 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Timer.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/type/Timer.java
@@ -19,6 +19,7 @@
 
 package org.apache.iotdb.metrics.type;
 
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 public interface Timer extends IMetric {
@@ -46,4 +47,10 @@ public interface Timer extends IMetric {
 
   /** It's not safe to use the update interface of this rate */
   Rate getImmutableRate();
+
+  @Override
+  default void constructValueMap(Map<String, Object> result) {
+    takeSnapshot().constructValueMap(result);
+    getImmutableRate().constructValueMap(result);
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/IoTDBMetricsUtils.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/IoTDBMetricsUtils.java
index 553b39c52c..e3c488dd15 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/IoTDBMetricsUtils.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/IoTDBMetricsUtils.java
@@ -27,12 +27,48 @@ import java.util.Map;
 public class IoTDBMetricsUtils {
   private static final MetricConfig metricConfig =
       MetricConfigDescriptor.getInstance().getMetricConfig();
-  private static final String STORAGE_GROUP = "root.__system";
+  public static final String DATABASE = "root.__system";
 
-  public static String generatePath(String name, Map<String, String> labels) {
+  /** Generate the path of metric by metricInfo */
+  public static String generatePath(MetricInfo metricInfo) {
+    return generatePath(metricInfo.getName(), metricInfo.getTags());
+  }
+
+  /** Generate the path of metric with tags array */
+  public static String generatePath(String name, String... tags) {
+    StringBuilder stringBuilder = generateMetric(name);
+    for (int i = 0; i < tags.length; i += 2) {
+      stringBuilder
+          .append(".")
+          .append("\"")
+          .append(tags[i])
+          .append("=")
+          .append(tags[i + 1])
+          .append("\"");
+    }
+    return stringBuilder.toString();
+  }
+
+  /** Generate the path of metric with tags map */
+  public static String generatePath(String name, Map<String, String> tags) {
+    StringBuilder stringBuilder = generateMetric(name);
+    for (Map.Entry<String, String> entry : tags.entrySet()) {
+      stringBuilder
+          .append(".")
+          .append("\"")
+          .append(entry.getKey())
+          .append("=")
+          .append(entry.getValue())
+          .append("\"");
+    }
+    return stringBuilder.toString();
+  }
+
+  /** Generate the path of metric */
+  private static StringBuilder generateMetric(String name) {
     StringBuilder stringBuilder = new StringBuilder();
     stringBuilder
-        .append(STORAGE_GROUP)
+        .append(DATABASE)
         .append(".")
         .append(metricConfig.getIoTDBReporterConfig().getDatabase())
         .append(".\"")
@@ -44,15 +80,6 @@ public class IoTDBMetricsUtils {
         .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();
+    return stringBuilder;
   }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
index 333604cbc7..bd7cc7f117 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
@@ -19,6 +19,8 @@
 
 package org.apache.iotdb.metrics.utils;
 
+import org.apache.iotdb.tsfile.utils.Pair;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -30,12 +32,14 @@ import java.util.Objects;
 import java.util.Set;
 
 public class MetricInfo {
-
   private static final Logger logger = LoggerFactory.getLogger(MetricInfo.class);
   private static final Integer PAIR_SIZE = 2;
+  /** The name of metric */
   private final String name;
-  private final MetaInfo metaInfo;
+  /** The tags of metric */
   private final Map<String, String> tags = new LinkedHashMap<>();
+  /** The metaInfo of metric */
+  private final MetaInfo metaInfo;
 
   public MetricInfo(MetricType type, String name, String... tags) {
     this.name = name;
@@ -71,16 +75,15 @@ public class MetricInfo {
     return metaInfo;
   }
 
-  /** convert the metric name to string array. */
-  public String[] toStringArray() {
+  /** Convert the metric name and tag into pair */
+  public Pair<String, String[]> toStringArray() {
     List<String> allNames = new ArrayList<>();
-    allNames.add(name);
     tags.forEach(
         (k, v) -> {
           allNames.add(k);
           allNames.add(v);
         });
-    return allNames.toArray(new String[0]);
+    return new Pair<>(name, allNames.toArray(new String[0]));
   }
 
   @Override
@@ -129,7 +132,9 @@ public class MetricInfo {
   }
 
   public static class MetaInfo {
+    /** The type of metric */
     private final MetricType type;
+    /** The tag keys of metric */
     private final Set<String> tagNames;
 
     public MetaInfo(MetricType type, Set<String> tagNames) {
@@ -137,7 +142,7 @@ public class MetricInfo {
       this.tagNames = tagNames;
     }
 
-    /** check whether the keys of tags are same */
+    /** Check whether the keys of tags are same */
     public boolean hasSameKey(String... tags) {
       if (tags.length != tagNames.size() * 2) {
         return false;
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java
index 14651c1674..68b5266928 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.metrics.utils;
 
 public enum MetricType {
   COUNTER,
+  AUTO_GAUGE,
   GAUGE,
   RATE,
   HISTOGRAM,
diff --git a/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java b/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
index 065347f2ef..f22c8f375a 100644
--- a/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
+++ b/metrics/interface/src/test/java/org/apache/iotdb/metrics/config/MetricConfigTest.java
@@ -59,6 +59,7 @@ public class MetricConfigTest {
     assertEquals(5, metricConfig.getPredefinedMetrics().size());
     assertEquals(10, (int) metricConfig.getAsyncCollectPeriodInSecond());
     assertEquals(9090, (int) metricConfig.getPrometheusExporterPort());
+    assertTrue(metricConfig.isStoreToLocal());
 
     MetricConfig.IoTDBReporterConfig reporterConfig = metricConfig.getIoTDBReporterConfig();
     assertEquals("0.0.0.0", reporterConfig.getHost());
diff --git a/metrics/interface/src/test/resources/iotdb-metric.yml b/metrics/interface/src/test/resources/iotdb-metric.yml
index e84ec80bdb..a211b834d4 100644
--- a/metrics/interface/src/test/resources/iotdb-metric.yml
+++ b/metrics/interface/src/test/resources/iotdb-metric.yml
@@ -49,6 +49,9 @@ asyncCollectPeriodInSecond: 10
 # The http server's port for prometheus exporter to get metric data.
 prometheusExporterPort: 9090
 
+# whether store predefined metrics locally
+isStoreToLocal: true
+
 # The config of iotdb reporter
 ioTDBReporterConfig:
   host: 0.0.0.0
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerAutoGauge.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerAutoGauge.java
index d9ac771322..83e592f046 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerAutoGauge.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerAutoGauge.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.metrics.micrometer.type;
 
-import org.apache.iotdb.metrics.type.Gauge;
+import org.apache.iotdb.metrics.type.AutoGauge;
 
 import io.micrometer.core.instrument.Tags;
 import org.slf4j.LoggerFactory;
@@ -27,7 +27,7 @@ import org.slf4j.LoggerFactory;
 import java.lang.ref.WeakReference;
 import java.util.function.ToLongFunction;
 
-public class MicrometerAutoGauge<T> implements Gauge {
+public class MicrometerAutoGauge<T> implements AutoGauge {
   private final WeakReference<T> refObject;
   private final ToLongFunction<T> mapper;
 
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/flush/MemTableFlushTask.java b/server/src/main/java/org/apache/iotdb/db/engine/flush/MemTableFlushTask.java
index f4caf0efaa..d1e502115d 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/flush/MemTableFlushTask.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/flush/MemTableFlushTask.java
@@ -19,6 +19,7 @@
 package org.apache.iotdb.db.engine.flush;
 
 import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.engine.flush.pool.FlushSubTaskPoolManager;
 import org.apache.iotdb.db.engine.memtable.IMemTable;
@@ -296,6 +297,22 @@ public class MemTableFlushTask {
           }
           ioTime += System.currentTimeMillis() - starTime;
         }
+        if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()
+            && !storageGroup.startsWith(IoTDBConstant.SYSTEM_STORAGE_GROUP)) {
+          int lastIndex = storageGroup.lastIndexOf("/");
+          if (lastIndex == -1) {
+            lastIndex = storageGroup.length();
+          }
+          MetricService.getInstance()
+              .gaugeWithInternalReport(
+                  memTable.getTotalPointsNum(),
+                  Metric.POINTS.toString(),
+                  MetricLevel.CORE,
+                  Tag.SG.toString(),
+                  storageGroup.substring(0, lastIndex),
+                  Tag.TYPE.toString(),
+                  "flush");
+        }
         LOGGER.debug(
             "flushing a memtable to file {} in storage group {}, io cost {}ms",
             writer.getFile().getName(),
diff --git a/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java b/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java
index 4a7c4b3b8f..385449047a 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/IoTDB.java
@@ -45,9 +45,11 @@ import org.apache.iotdb.db.rescon.PrimitiveArrayManager;
 import org.apache.iotdb.db.rescon.SystemInfo;
 import org.apache.iotdb.db.service.basic.ServiceProvider;
 import org.apache.iotdb.db.service.basic.StandaloneServiceProvider;
+import org.apache.iotdb.db.service.metrics.IoTDBInternalReporter;
 import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.sync.receiver.SyncServerManager;
 import org.apache.iotdb.db.writelog.manager.MultiFileLogNodeManager;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -192,6 +194,9 @@ public class IoTDB implements IoTDBMBean {
     registerManager.register(SettleService.getINSTANCE());
     registerManager.register(TriggerRegistrationService.getInstance());
     registerManager.register(ContinuousQueryService.getInstance());
+    if (MetricConfigDescriptor.getInstance().getMetricConfig().isStoreToLocal()) {
+      MetricService.getInstance().reloadInternalReporter(new IoTDBInternalReporter());
+    }
     registerManager.register(MetricService.getInstance());
     logger.info("Congratulation, IoTDB is set up successfully. Now, enjoy yourself!");
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/IoTDBInternalReporter.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/IoTDBInternalReporter.java
new file mode 100644
index 0000000000..ca499a6e88
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/IoTDBInternalReporter.java
@@ -0,0 +1,143 @@
+/*
+ * 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.service.metrics;
+
+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.qp.physical.crud.InsertRowPlan;
+import org.apache.iotdb.db.service.IoTDB;
+import org.apache.iotdb.metrics.AbstractMetricManager;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.reporter.InternalIoTDBReporter;
+import org.apache.iotdb.metrics.utils.ReporterType;
+import org.apache.iotdb.rpc.IoTDBConnectionException;
+import org.apache.iotdb.service.rpc.thrift.TSInsertRecordReq;
+import org.apache.iotdb.session.util.SessionUtils;
+import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class IoTDBInternalReporter extends InternalIoTDBReporter {
+  private static final Logger LOGGER = LoggerFactory.getLogger(IoTDBInternalReporter.class);
+  private Future<?> currentServiceFuture;
+  private final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
+
+  public IoTDBInternalReporter() {
+    // Empty constructor
+  }
+
+  @Override
+  protected void writeMetricToIoTDB(Map<String, Object> valueMap, String prefix, long time) {
+    try {
+      TSInsertRecordReq request = new TSInsertRecordReq();
+      List<String> measurements = new ArrayList<>();
+      List<TSDataType> types = new ArrayList<>();
+      List<Object> values = new ArrayList<>();
+      for (Map.Entry<String, Object> entry : valueMap.entrySet()) {
+        String measurement = entry.getKey();
+        Object value = entry.getValue();
+        measurements.add(measurement);
+        types.add(inferType(value));
+        values.add(value);
+      }
+      ByteBuffer buffer = SessionUtils.getValueBuffer(types, values);
+
+      request.setPrefixPath(prefix);
+      request.setTimestamp(time);
+      request.setMeasurements(measurements);
+      request.setValues(buffer);
+      request.setIsAligned(false);
+
+      InsertRowPlan plan =
+          new InsertRowPlan(
+              new PartialPath(request.getPrefixPath()),
+              request.getTimestamp(),
+              request.getMeasurements().toArray(new String[0]),
+              request.values,
+              request.isAligned);
+
+      if (!IoTDB.serviceProvider.executeNonQuery(plan)) {
+        LOGGER.error("Failed to update the value of metric with status.");
+      }
+    } catch (IoTDBConnectionException e1) {
+      LOGGER.error("Failed to update the value of metric because of unknown type", e1);
+    } catch (IllegalPathException
+        | QueryProcessException
+        | StorageGroupNotSetException
+        | StorageEngineException e2) {
+      LOGGER.error("Failed to update the value of metric because of internal error", e2);
+    }
+  }
+
+  @Override
+  protected void writeMetricsToIoTDB(Map<String, Map<String, Object>> valueMap, long time) {
+    for (Map.Entry<String, Map<String, Object>> value : valueMap.entrySet()) {
+      writeMetricToIoTDB(value.getValue(), value.getKey(), time);
+    }
+  }
+
+  @Override
+  public boolean start() {
+    if (currentServiceFuture == null) {
+      currentServiceFuture =
+          service.scheduleAtFixedRate(
+              () -> {
+                writeMetricToIoTDB(autoGauges);
+              },
+              1,
+              MetricConfigDescriptor.getInstance()
+                  .getMetricConfig()
+                  .getAsyncCollectPeriodInSecond(),
+              TimeUnit.SECONDS);
+    }
+    return true;
+  }
+
+  @Override
+  public boolean stop() {
+    if (currentServiceFuture != null) {
+      currentServiceFuture.cancel(true);
+      currentServiceFuture = null;
+    }
+    clear();
+    return true;
+  }
+
+  @Override
+  public ReporterType getReporterType() {
+    return ReporterType.IOTDB;
+  }
+
+  @Override
+  public void setMetricManager(AbstractMetricManager metricManager) {}
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
index 923e23e304..13d8a441d8 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
@@ -33,6 +33,7 @@ import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.metricsets.predefined.jvm.JvmMetrics;
 import org.apache.iotdb.metrics.metricsets.predefined.logback.LogbackMetrics;
+import org.apache.iotdb.metrics.reporter.InternalIoTDBReporter;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,6 +53,7 @@ public class MetricService extends AbstractMetricService implements MetricServic
         logger.info("Start to start metric Service.");
         JMXService.registerMBean(getInstance(), mbeanName);
         startService();
+        internalReporter.start();
         logger.info("Finish start metric Service");
       }
     } catch (Exception e) {
@@ -62,6 +64,7 @@ public class MetricService extends AbstractMetricService implements MetricServic
 
   public void restart() {
     logger.info("Restart metric service.");
+    internalReporter.clear();
     restartService();
     logger.info("Finish restart metric service.");
   }
@@ -70,6 +73,7 @@ public class MetricService extends AbstractMetricService implements MetricServic
   public void stop() {
     if (isEnable()) {
       logger.info("Stop metric Service.");
+      internalReporter.stop();
       stopService();
       JMXService.deregisterMBean(mbeanName);
       logger.info("Finish stop metric Service");
@@ -138,6 +142,11 @@ public class MetricService extends AbstractMetricService implements MetricServic
     }
   }
 
+  @Override
+  public void reloadInternalReporter(InternalIoTDBReporter internalReporter) {
+    this.internalReporter = internalReporter;
+  }
+
   @Override
   public ServiceType getID() {
     return ServiceType.METRICS_SERVICE;
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Metric.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Metric.java
index 88efa07155..578008e43d 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Metric.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Metric.java
@@ -29,6 +29,7 @@ public enum Metric {
   CACHE_HIT,
   ERROR_LOG,
   QUANTITY,
+  POINTS,
   DATA_WRITTEN,
   DATA_READ,
   COMPACTION_TASK_COUNT,
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
index cb2db3a578..66dd734ffa 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/enums/Tag.java
@@ -22,7 +22,8 @@ package org.apache.iotdb.db.service.metrics.enums;
 public enum Tag {
   TYPE,
   NAME,
-  STATUS;
+  STATUS,
+  SG;
 
   @Override
   public String toString() {
diff --git a/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java b/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
index a034e2d0d5..a596127076 100644
--- a/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
@@ -102,13 +102,13 @@ public class MetricServiceTest {
     assertNotEquals(counter1, counter2);
     counter2 = metricService.getOrCreateCounter("counter5", MetricLevel.NORMAL, "tag", "value");
     assertEquals(DoNothingMetricManager.doNothingCounter, counter2);
-    assertEquals(4, metricService.getAllCounters().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.COUNTER).size());
     metricService.count(10, "counter6", MetricLevel.IMPORTANT, "tag", "value");
-    assertEquals(5, metricService.getAllCounters().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.COUNTER).size());
     metricService.remove(MetricType.COUNTER, "counter6");
-    assertEquals(5, metricService.getAllCounters().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.COUNTER).size());
     metricService.remove(MetricType.COUNTER, "counter6", "tag", "value");
-    assertEquals(4, metricService.getAllCounters().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.COUNTER).size());
     assertEquals(4, metricService.getAllMetricKeys().size());
 
     // test gauge
@@ -128,13 +128,13 @@ public class MetricServiceTest {
     assertNotEquals(gauge1, gauge2);
     gauge2 = metricService.getOrCreateGauge("gauge5", MetricLevel.NORMAL, "tag", "value");
     assertEquals(DoNothingMetricManager.doNothingGauge, gauge2);
-    assertEquals(4, metricService.getAllGauges().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.GAUGE).size());
     metricService.gauge(10, "gauge6", MetricLevel.IMPORTANT, "tag", "value");
-    assertEquals(5, metricService.getAllGauges().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.GAUGE).size());
     metricService.remove(MetricType.GAUGE, "gauge6");
-    assertEquals(5, metricService.getAllGauges().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.GAUGE).size());
     metricService.remove(MetricType.GAUGE, "gauge6", "tag", "value");
-    assertEquals(4, metricService.getAllGauges().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.GAUGE).size());
     assertEquals(8, metricService.getAllMetricKeys().size());
 
     // test auto gauge
@@ -152,9 +152,9 @@ public class MetricServiceTest {
     list = null;
     System.gc();
     assertEquals(0L, autoGauge.value());
-    assertEquals(5, metricService.getAllGauges().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.GAUGE).size());
     metricService.remove(MetricType.GAUGE, "autoGauge", "tag", "value");
-    assertEquals(4, metricService.getAllGauges().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.GAUGE).size());
     assertEquals(8, metricService.getAllMetricKeys().size());
 
     // test rate
@@ -175,14 +175,14 @@ public class MetricServiceTest {
             "rate4", MetricLevel.IMPORTANT, "tag", "value", "tag2", "value");
     assertNotEquals(rate1, rate2);
     rate2 = metricService.getOrCreateRate("rate5", MetricLevel.NORMAL, "tag", "value");
-    assertEquals(4, metricService.getAllRates().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.RATE).size());
     assertEquals(DoNothingMetricManager.doNothingRate, rate2);
     metricService.rate(10, "rate6", MetricLevel.IMPORTANT, "tag", "value");
-    assertEquals(5, metricService.getAllRates().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.RATE).size());
     metricService.remove(MetricType.RATE, "rate6");
-    assertEquals(5, metricService.getAllRates().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.RATE).size());
     metricService.remove(MetricType.RATE, "rate6", "tag", "value");
-    assertEquals(4, metricService.getAllRates().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.RATE).size());
     assertEquals(12, metricService.getAllMetricKeys().size());
 
     // test histogram
@@ -213,13 +213,13 @@ public class MetricServiceTest {
     histogram2 =
         metricService.getOrCreateHistogram("histogram5", MetricLevel.NORMAL, "tag", "value");
     assertEquals(DoNothingMetricManager.doNothingHistogram, histogram2);
-    assertEquals(4, metricService.getAllHistograms().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.HISTOGRAM).size());
     metricService.histogram(10, "histogram6", MetricLevel.IMPORTANT, "tag", "value");
-    assertEquals(5, metricService.getAllHistograms().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.HISTOGRAM).size());
     metricService.remove(MetricType.HISTOGRAM, "histogram6");
-    assertEquals(5, metricService.getAllHistograms().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.HISTOGRAM).size());
     metricService.remove(MetricType.HISTOGRAM, "histogram6", "tag", "value");
-    assertEquals(4, metricService.getAllHistograms().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.HISTOGRAM).size());
     assertEquals(16, metricService.getAllMetricKeys().size());
 
     // test timer
@@ -244,13 +244,13 @@ public class MetricServiceTest {
     assertNotEquals(timer1, timer2);
     timer2 = metricService.getOrCreateTimer("timer5", MetricLevel.NORMAL, "tag", "value");
     assertNotEquals(timer1, timer2);
-    assertEquals(4, metricService.getAllTimers().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.TIMER).size());
     metricService.timer(10, TimeUnit.MILLISECONDS, "timer6", MetricLevel.IMPORTANT, "tag", "value");
-    assertEquals(5, metricService.getAllTimers().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.TIMER).size());
     metricService.remove(MetricType.TIMER, "timer6");
-    assertEquals(5, metricService.getAllTimers().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.TIMER).size());
     metricService.remove(MetricType.TIMER, "timer6", "tag", "value");
-    assertEquals(4, metricService.getAllTimers().size());
+    assertEquals(4, metricService.getMetricsByType(MetricType.TIMER).size());
     assertEquals(20, metricService.getAllMetricKeys().size());
 
     // test remove same key and different value counter
@@ -260,15 +260,15 @@ public class MetricServiceTest {
     Counter removeCounter2 =
         metricService.getOrCreateCounter("remove", MetricLevel.IMPORTANT, "tag", "value2");
     assertNotNull(removeCounter2);
-    assertEquals(6, metricService.getAllCounters().size());
+    assertEquals(6, metricService.getMetricsByType(MetricType.COUNTER).size());
     assertEquals(22, metricService.getAllMetricKeys().size());
     metricService.remove(MetricType.COUNTER, "remove", "tag", "value1");
-    assertEquals(5, metricService.getAllCounters().size());
+    assertEquals(5, metricService.getMetricsByType(MetricType.COUNTER).size());
     assertEquals(21, metricService.getAllMetricKeys().size());
     removeCounter2 =
         metricService.getOrCreateCounter("remove", MetricLevel.IMPORTANT, "tag", "value1");
     assertNotNull(removeCounter2);
-    assertEquals(6, metricService.getAllCounters().size());
+    assertEquals(6, metricService.getMetricsByType(MetricType.COUNTER).size());
     assertEquals(22, metricService.getAllMetricKeys().size());
   }