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/08/14 13:48:00 UTC

[iotdb] branch master updated: [IOTDB-4096] Optimize metric module and Fix inconsistency between dropwizard and micrometer. (#6951)

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

qiaojialin 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 02416f4e6c [IOTDB-4096] Optimize metric module and Fix inconsistency between dropwizard and micrometer. (#6951)
02416f4e6c is described below

commit 02416f4e6c7f4081109a72dca4f08aa5cfd9e960
Author: ZhangHongYin <46...@users.noreply.github.com>
AuthorDate: Sun Aug 14 21:47:55 2022 +0800

    [IOTDB-4096] Optimize metric module and Fix inconsistency between dropwizard and micrometer. (#6951)
---
 .../manager/load/LoadManagerMetrics.java           | 129 +++---
 .../iotdb/confignode/persistence/NodeInfo.java     |  47 +-
 .../persistence/partition/PartitionInfo.java       |  67 ++-
 .../partition/StorageGroupPartitionTable.java      |  91 ++--
 .../iotdb/confignode/service/ConfigNode.java       |   8 +-
 .../service/thrift/ConfigNodeRPCService.java       |   5 +-
 .../thrift/ConfigNodeRPCServiceHandler.java        |   8 +-
 .../src/test/resources/logback-test.xml            |   2 +-
 integration/src/test/resources/logback-test.xml    |   2 +-
 metrics/ReadMe.md                                  | 103 ++---
 metrics/dropwizard-metrics/pom.xml                 |   4 +-
 .../dropwizard/DropwizardMetricManager.java        | 375 ++--------------
 .../dropwizard/DropwizardMetricNameTool.java       |  66 +++
 .../iotdb/metrics/dropwizard/MetricName.java       | 174 --------
 .../reporter/DropwizardIoTDBReporter.java          |  34 +-
 .../dropwizard/reporter/DropwizardJmxReporter.java |  14 +-
 .../{MetricType.java => DropwizardMetricType.java} |   4 +-
 .../reporter/DropwizardMetricsExporter.java        |  71 ++-
 .../reporter/DropwizardPrometheusReporter.java     |  15 +-
 .../metrics/dropwizard/reporter/IoTDBReporter.java |  31 +-
 .../dropwizard/reporter/PrometheusTextWriter.java  |   2 +-
 ...org.apache.iotdb.metrics.AbstractMetricManager} |   0
 .../dropwizard/DropwizardMetricManagerTest.java    | 339 --------------
 .../iotdb/metrics/AbstractMetricManager.java       | 490 +++++++++++++++++++++
 .../iotdb/metrics/AbstractMetricService.java       | 262 +++++++++++
 .../iotdb/metrics/DoNothingMetricService.java      |   8 +-
 .../org/apache/iotdb/metrics/MetricManager.java    | 170 -------
 .../org/apache/iotdb/metrics/MetricService.java    | 176 --------
 .../apache/iotdb/metrics/config/MetricConfig.java  |  23 +-
 .../metrics/config/MetricConfigDescriptor.java     | 104 +++--
 .../apache/iotdb/metrics/config/ReloadLevel.java   |   5 +
 .../apache/iotdb/metrics/impl/DoNothingGauge.java  |   8 +-
 .../iotdb/metrics/impl/DoNothingMetricManager.java | 111 +----
 .../iotdb/metrics/predefined/IMetricSet.java       |   5 +-
 .../{utils => predefined}/PredefinedMetric.java    |   2 +-
 .../predefined/jvm/JvmClassLoaderMetrics.java      |   6 +-
 .../metrics/predefined/jvm/JvmCompileMetrics.java  |   6 +-
 .../iotdb/metrics/predefined/jvm/JvmGcMetrics.java |   7 +-
 .../metrics/predefined/jvm/JvmMemoryMetrics.java   |   7 +-
 .../iotdb/metrics/predefined/jvm/JvmMetrics.java   |   6 +-
 .../metrics/predefined/jvm/JvmThreadMetrics.java   |   6 +-
 .../{utils => predefined/jvm}/JvmUtils.java        |   4 +-
 .../metrics/predefined/logback/LogbackMetrics.java |  11 +-
 .../iotdb/metrics/reporter/CompositeReporter.java  |  31 +-
 .../apache/iotdb/metrics/reporter/Reporter.java    |  12 +-
 .../org/apache/iotdb/metrics/type/Counter.java     |   7 +-
 .../java/org/apache/iotdb/metrics/type/Gauge.java  |   9 +-
 .../org/apache/iotdb/metrics/type/Histogram.java   |   3 +-
 .../iotdb/metrics/type/HistogramSnapshot.java      |  26 +-
 .../org/apache/iotdb/metrics/type/IMetric.java     |   1 +
 .../java/org/apache/iotdb/metrics/type/Rate.java   |  11 +-
 .../java/org/apache/iotdb/metrics/type/Timer.java  |   6 +-
 .../org/apache/iotdb/metrics/utils/MetricInfo.java | 191 ++++++++
 .../apache/iotdb/metrics/utils/MetricLevel.java    |   2 +-
 .../{PredefinedMetric.java => MetricType.java}     |  12 +-
 .../iotdb/metrics/config/MetricConfigTest.java     |  33 +-
 .../interface/src/test/resources/iotdb-metric.yml  |  35 +-
 metrics/micrometer-metrics/pom.xml                 |   6 +-
 .../iotdb/metrics/micrometer/MetricName.java       |  66 ---
 .../micrometer/MicrometerMetricManager.java        | 422 +++---------------
 .../reporter/MicrometerIoTDBReporter.java          |   6 +-
 .../micrometer/reporter/MicrometerJmxReporter.java |   6 +-
 .../reporter/MicrometerPrometheusReporter.java     |   8 +-
 .../metrics/micrometer/type/MicrometerRate.java    |   2 +-
 .../metrics/micrometer/type/MicrometerTimer.java   |   2 +-
 ...org.apache.iotdb.metrics.AbstractMetricManager} |   0
 .../micrometer/MicrometerMetricManagerTest.java    | 106 -----
 .../apache/iotdb/commons/service/ServiceType.java  |   2 +-
 pom.xml                                            |   3 +-
 .../org/apache/iotdb/db/conf/IoTDBDescriptor.java  |   6 +-
 .../apache/iotdb/db/engine/cache/ChunkCache.java   |  22 +-
 .../db/engine/cache/TimeSeriesMetadataCache.java   |  54 +--
 .../utils/SingleSeriesCompactionExecutor.java      |   3 -
 .../writer/AbstractCompactionWriter.java           |   3 -
 .../apache/iotdb/db/engine/flush/FlushManager.java |  48 +-
 .../iotdb/db/engine/flush/MemTableFlushTask.java   |  22 +-
 .../iotdb/db/engine/memtable/AbstractMemTable.java | 139 +++---
 .../iotdb/db/engine/storagegroup/DataRegion.java   |  22 +-
 .../engine/storagegroup/TsFileProcessorInfo.java   |  42 +-
 .../db/metadata/cache/DataNodeSchemaCache.java     |  23 +-
 .../db/metadata/rescon/TimeseriesStatistics.java   |  22 +-
 .../execution/exchange/MPPDataExchangeService.java |   5 +-
 .../MPPDataExchangeServiceThriftHandler.java       |   8 +-
 .../db/query/pool/RawQueryReadTaskPoolManager.java |  47 +-
 .../java/org/apache/iotdb/db/service/DataNode.java |   8 +-
 .../db/service/DataNodeInternalRPCService.java     |   5 +-
 .../java/org/apache/iotdb/db/service/IoTDB.java    |   6 +-
 .../java/org/apache/iotdb/db/service/NewIoTDB.java |   6 +-
 .../org/apache/iotdb/db/service/RPCService.java    |   5 +-
 .../{MetricsService.java => MetricService.java}    |  18 +-
 ...csServiceMBean.java => MetricServiceMBean.java} |   2 +-
 .../db/service/metrics/predefined/FileMetrics.java |   6 +-
 .../service/metrics/predefined/ProcessMetrics.java |  14 +-
 .../service/metrics/predefined/SystemMetrics.java  |  12 +-
 .../metrics/recorder/CacheMetricsRecorder.java     |  36 +-
 .../recorder/CompactionMetricsRecorder.java        |  42 +-
 .../db/service/thrift/ProcessorWithMetrics.java    |   5 +-
 .../handler/InternalServiceThriftHandler.java      |   8 +-
 .../thrift/handler/RPCServiceThriftHandler.java    |   8 +-
 .../service/thrift/impl/ClientRPCServiceImpl.java  |   8 +-
 .../impl/DataNodeInternalRPCServiceImpl.java       |  11 +-
 .../db/service/thrift/impl/TSServiceImpl.java      |   8 +-
 .../transport/server/TransportServerManager.java   |   5 +-
 .../server/TransportServerThriftHandler.java       |   8 +-
 .../apache/iotdb/db/metric/MetricServiceTest.java  | 276 ++++++++++++
 server/src/test/resources/logback-test.xml         |   2 +-
 .../apache/iotdb/spark/db/EnvironmentUtils.java    |   4 +-
 107 files changed, 2177 insertions(+), 2808 deletions(-)

diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/LoadManagerMetrics.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/LoadManagerMetrics.java
index 4611230c5c..d1547f8e76 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/LoadManagerMetrics.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/load/LoadManagerMetrics.java
@@ -26,11 +26,11 @@ import org.apache.iotdb.commons.utils.NodeUrlUtils;
 import org.apache.iotdb.confignode.manager.IManager;
 import org.apache.iotdb.confignode.manager.NodeManager;
 import org.apache.iotdb.confignode.manager.PartitionManager;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import java.util.List;
 import java.util.Map;
@@ -59,8 +59,7 @@ public class LoadManagerMetrics {
     for (TConfigNodeLocation configNodeLocation : runningConfigNodes) {
       String name = NodeUrlUtils.convertTEndPointUrl(configNodeLocation.getInternalEndPoint());
 
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .getOrCreateGauge(
               Metric.CLUSTER_NODE_STATUS.toString(),
               MetricLevel.IMPORTANT,
@@ -83,8 +82,7 @@ public class LoadManagerMetrics {
       TDataNodeLocation dataNodeLocation = dataNodeInfo.getLocation();
       String name = NodeUrlUtils.convertTEndPointUrl(dataNodeLocation.getClientRpcEndPoint());
 
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .getOrCreateGauge(
               Metric.CLUSTER_NODE_STATUS.toString(),
               MetricLevel.IMPORTANT,
@@ -106,8 +104,7 @@ public class LoadManagerMetrics {
     for (TConfigNodeLocation configNodeLocation : unknownConfigNodes) {
       String name = NodeUrlUtils.convertTEndPointUrl(configNodeLocation.getInternalEndPoint());
 
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .getOrCreateGauge(
               Metric.CLUSTER_NODE_STATUS.toString(),
               MetricLevel.IMPORTANT,
@@ -130,8 +127,7 @@ public class LoadManagerMetrics {
       TDataNodeLocation dataNodeLocation = dataNodeInfo.getLocation();
       String name = NodeUrlUtils.convertTEndPointUrl(dataNodeLocation.getClientRpcEndPoint());
 
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .getOrCreateGauge(
               Metric.CLUSTER_NODE_STATUS.toString(),
               MetricLevel.IMPORTANT,
@@ -145,55 +141,49 @@ public class LoadManagerMetrics {
   }
 
   public void addNodeMetrics() {
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CONFIG_NODE.toString(),
-              MetricLevel.CORE,
-              this,
-              o -> getRunningConfigNodesNum(),
-              Tag.NAME.toString(),
-              "total",
-              Tag.STATUS.toString(),
-              NodeStatus.Online.toString());
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CONFIG_NODE.toString(),
+            MetricLevel.CORE,
+            this,
+            o -> getRunningConfigNodesNum(),
+            Tag.NAME.toString(),
+            "total",
+            Tag.STATUS.toString(),
+            NodeStatus.Online.toString());
 
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.DATA_NODE.toString(),
-              MetricLevel.CORE,
-              this,
-              o -> getRunningDataNodesNum(),
-              Tag.NAME.toString(),
-              "total",
-              Tag.STATUS.toString(),
-              NodeStatus.Online.toString());
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.DATA_NODE.toString(),
+            MetricLevel.CORE,
+            this,
+            o -> getRunningDataNodesNum(),
+            Tag.NAME.toString(),
+            "total",
+            Tag.STATUS.toString(),
+            NodeStatus.Online.toString());
 
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CONFIG_NODE.toString(),
-              MetricLevel.CORE,
-              this,
-              o -> getUnknownConfigNodesNum(),
-              Tag.NAME.toString(),
-              "total",
-              Tag.STATUS.toString(),
-              NodeStatus.Unknown.toString());
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CONFIG_NODE.toString(),
+            MetricLevel.CORE,
+            this,
+            o -> getUnknownConfigNodesNum(),
+            Tag.NAME.toString(),
+            "total",
+            Tag.STATUS.toString(),
+            NodeStatus.Unknown.toString());
 
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.DATA_NODE.toString(),
-              MetricLevel.CORE,
-              this,
-              o -> getUnknownDataNodesNum(),
-              Tag.NAME.toString(),
-              "total",
-              Tag.STATUS.toString(),
-              NodeStatus.Unknown.toString());
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.DATA_NODE.toString(),
+            MetricLevel.CORE,
+            this,
+            o -> getUnknownDataNodesNum(),
+            Tag.NAME.toString(),
+            "total",
+            Tag.STATUS.toString(),
+            NodeStatus.Unknown.toString());
   }
 
   /**
@@ -220,8 +210,7 @@ public class LoadManagerMetrics {
               String name =
                   NodeUrlUtils.convertTEndPointUrl(dataNodeLocation.getClientRpcEndPoint());
 
-              MetricsService.getInstance()
-                  .getMetricManager()
+              MetricService.getInstance()
                   .getOrCreateAutoGauge(
                       Metric.CLUSTER_NODE_LEADER_COUNT.toString(),
                       MetricLevel.IMPORTANT,
@@ -233,33 +222,33 @@ public class LoadManagerMetrics {
   }
 
   public void removeMetrics() {
-    MetricsService.getInstance()
-        .getMetricManager()
-        .removeGauge(
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
             Metric.CONFIG_NODE.toString(),
             Tag.NAME.toString(),
             "total",
             Tag.STATUS.toString(),
             NodeStatus.Online.toString());
-    MetricsService.getInstance()
-        .getMetricManager()
-        .removeGauge(
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
             Metric.DATA_NODE.toString(),
             Tag.NAME.toString(),
             "total",
             Tag.STATUS.toString(),
             NodeStatus.Online.toString());
-    MetricsService.getInstance()
-        .getMetricManager()
-        .removeGauge(
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
             Metric.CONFIG_NODE.toString(),
             Tag.NAME.toString(),
             "total",
             Tag.STATUS.toString(),
             NodeStatus.Unknown.toString());
-    MetricsService.getInstance()
-        .getMetricManager()
-        .removeGauge(
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
             Metric.DATA_NODE.toString(),
             Tag.NAME.toString(),
             "total",
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/NodeInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/NodeInfo.java
index 73016a12f6..c749f2d5b2 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/NodeInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/NodeInfo.java
@@ -33,10 +33,9 @@ import org.apache.iotdb.confignode.consensus.request.write.RegisterDataNodePlan;
 import org.apache.iotdb.confignode.consensus.request.write.RemoveConfigNodePlan;
 import org.apache.iotdb.confignode.consensus.request.write.RemoveDataNodePlan;
 import org.apache.iotdb.confignode.consensus.response.DataNodeConfigurationResp;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.rpc.TSStatusCode;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
@@ -103,30 +102,26 @@ public class NodeInfo implements SnapshotProcessor {
   }
 
   public void addMetrics() {
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CONFIG_NODE.toString(),
-              MetricLevel.CORE,
-              registeredConfigNodes,
-              o -> getRegisteredConfigNodeCount(),
-              Tag.NAME.toString(),
-              "total",
-              Tag.STATUS.toString(),
-              NodeStatus.Registered.toString());
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.DATA_NODE.toString(),
-              MetricLevel.CORE,
-              registeredDataNodes,
-              Map::size,
-              Tag.NAME.toString(),
-              "total",
-              Tag.STATUS.toString(),
-              NodeStatus.Registered.toString());
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CONFIG_NODE.toString(),
+            MetricLevel.CORE,
+            registeredConfigNodes,
+            o -> getRegisteredConfigNodeCount(),
+            Tag.NAME.toString(),
+            "total",
+            Tag.STATUS.toString(),
+            NodeStatus.Registered.toString());
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.DATA_NODE.toString(),
+            MetricLevel.CORE,
+            registeredDataNodes,
+            Map::size,
+            Tag.NAME.toString(),
+            "total",
+            Tag.STATUS.toString(),
+            NodeStatus.Registered.toString());
   }
 
   /**
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
index 2e8414cadc..b454aa7750 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/PartitionInfo.java
@@ -47,10 +47,9 @@ import org.apache.iotdb.confignode.exception.StorageGroupNotExistsException;
 import org.apache.iotdb.confignode.rpc.thrift.TRegionInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
 import org.apache.iotdb.consensus.common.DataSet;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -113,39 +112,34 @@ public class PartitionInfo implements SnapshotProcessor {
   }
 
   public void addMetrics() {
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.STORAGE_GROUP.toString(),
-              MetricLevel.CORE,
-              storageGroupPartitionTables,
-              ConcurrentHashMap::size,
-              Tag.NAME.toString(),
-              "number");
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.REGION.toString(),
-              MetricLevel.IMPORTANT,
-              this,
-              o -> o.updateRegionGroupMetric(TConsensusGroupType.SchemaRegion),
-              Tag.NAME.toString(),
-              "total",
-              Tag.TYPE.toString(),
-              TConsensusGroupType.SchemaRegion.toString());
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.REGION.toString(),
-              MetricLevel.IMPORTANT,
-              this,
-              o -> o.updateRegionGroupMetric(TConsensusGroupType.DataRegion),
-              Tag.NAME.toString(),
-              "total",
-              Tag.TYPE.toString(),
-              TConsensusGroupType.DataRegion.toString());
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.STORAGE_GROUP.toString(),
+            MetricLevel.CORE,
+            storageGroupPartitionTables,
+            ConcurrentHashMap::size,
+            Tag.NAME.toString(),
+            "number");
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.REGION.toString(),
+            MetricLevel.IMPORTANT,
+            this,
+            o -> o.updateRegionGroupMetric(TConsensusGroupType.SchemaRegion),
+            Tag.NAME.toString(),
+            "total",
+            Tag.TYPE.toString(),
+            TConsensusGroupType.SchemaRegion.toString());
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.REGION.toString(),
+            MetricLevel.IMPORTANT,
+            this,
+            o -> o.updateRegionGroupMetric(TConsensusGroupType.DataRegion),
+            Tag.NAME.toString(),
+            "total",
+            Tag.TYPE.toString(),
+            TConsensusGroupType.DataRegion.toString());
   }
 
   public int generateNextRegionGroupId() {
@@ -656,8 +650,7 @@ public class PartitionInfo implements SnapshotProcessor {
               + ":"
               + dataNodeLocation.getClientRpcEndPoint().port
               + ")";
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .getOrCreateGauge(
               Metric.REGION.toString(),
               MetricLevel.IMPORTANT,
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java
index 9b22112529..37690984b0 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/persistence/partition/StorageGroupPartitionTable.java
@@ -30,10 +30,9 @@ import org.apache.iotdb.commons.partition.SchemaPartitionTable;
 import org.apache.iotdb.confignode.consensus.request.read.GetRegionInfoListPlan;
 import org.apache.iotdb.confignode.rpc.thrift.TRegionInfo;
 import org.apache.iotdb.confignode.rpc.thrift.TShowRegionReq;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.utils.Pair;
 import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
@@ -88,53 +87,47 @@ public class StorageGroupPartitionTable {
   }
 
   private void addMetrics() {
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.REGION.toString(),
-              MetricLevel.NORMAL,
-              this,
-              o -> o.getRegionGroupCount(TConsensusGroupType.SchemaRegion),
-              Tag.NAME.toString(),
-              storageGroupName,
-              Tag.TYPE.toString(),
-              TConsensusGroupType.SchemaRegion.toString());
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.REGION.toString(),
-              MetricLevel.NORMAL,
-              this,
-              o -> o.getRegionGroupCount(TConsensusGroupType.DataRegion),
-              Tag.NAME.toString(),
-              storageGroupName,
-              Tag.TYPE.toString(),
-              TConsensusGroupType.DataRegion.toString());
-      // TODO slot will be updated in the future
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.SLOT.toString(),
-              MetricLevel.NORMAL,
-              schemaPartitionTable,
-              o -> o.getSchemaPartitionMap().size(),
-              Tag.NAME.toString(),
-              storageGroupName,
-              Tag.TYPE.toString(),
-              "schemaSlotNumber");
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.SLOT.toString(),
-              MetricLevel.NORMAL,
-              dataPartitionTable,
-              o -> o.getDataPartitionMap().size(),
-              Tag.NAME.toString(),
-              storageGroupName,
-              Tag.TYPE.toString(),
-              "dataSlotNumber");
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.REGION.toString(),
+            MetricLevel.NORMAL,
+            this,
+            o -> o.getRegionGroupCount(TConsensusGroupType.SchemaRegion),
+            Tag.NAME.toString(),
+            storageGroupName,
+            Tag.TYPE.toString(),
+            TConsensusGroupType.SchemaRegion.toString());
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.REGION.toString(),
+            MetricLevel.NORMAL,
+            this,
+            o -> o.getRegionGroupCount(TConsensusGroupType.DataRegion),
+            Tag.NAME.toString(),
+            storageGroupName,
+            Tag.TYPE.toString(),
+            TConsensusGroupType.DataRegion.toString());
+    // TODO slot will be updated in the future
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.SLOT.toString(),
+            MetricLevel.NORMAL,
+            schemaPartitionTable,
+            o -> o.getSchemaPartitionMap().size(),
+            Tag.NAME.toString(),
+            storageGroupName,
+            Tag.TYPE.toString(),
+            "schemaSlotNumber");
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.SLOT.toString(),
+            MetricLevel.NORMAL,
+            dataPartitionTable,
+            o -> o.getDataPartitionMap().size(),
+            Tag.NAME.toString(),
+            storageGroupName,
+            Tag.TYPE.toString(),
+            "dataSlotNumber");
   }
 
   public boolean isPredeleted() {
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNode.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNode.java
index 3c3e595a06..fd3ad986f8 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNode.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/ConfigNode.java
@@ -38,7 +38,7 @@ import org.apache.iotdb.confignode.manager.ConfigManager;
 import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
 import org.apache.iotdb.confignode.service.thrift.ConfigNodeRPCService;
 import org.apache.iotdb.confignode.service.thrift.ConfigNodeRPCServiceProcessor;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.slf4j.Logger;
@@ -177,9 +177,9 @@ public class ConfigNode implements ConfigNodeMBean {
     registerManager.register(UDFClassLoaderManager.setupAndGetInstance(conf.getUdfLibDir()));
     registerManager.register(UDFRegistrationService.setupAndGetInstance(conf.getSystemUdfDir()));
 
-    // Setup MetricsService
-    registerManager.register(MetricsService.getInstance());
-    MetricsService.getInstance().startAllReporter();
+    // Setup MetricService
+    registerManager.register(MetricService.getInstance());
+    MetricService.getInstance().startAllReporter();
 
     LOGGER.info("Successfully setup internal services.");
   }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCService.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCService.java
index 33d3036b5a..eb0ccb8c5f 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCService.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCService.java
@@ -30,7 +30,7 @@ import org.apache.iotdb.commons.service.ThriftServiceThread;
 import org.apache.iotdb.confignode.conf.ConfigNodeConfig;
 import org.apache.iotdb.confignode.conf.ConfigNodeDescriptor;
 import org.apache.iotdb.confignode.rpc.thrift.IConfigNodeRPCService;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -83,8 +83,7 @@ public class ConfigNodeRPCService extends ThriftService implements ConfigNodeRPC
       throw new IllegalAccessException(e.getMessage());
     }
     thriftServiceThread.setName(ThreadName.CONFIG_NODE_RPC_SERVER.getName());
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateAutoGauge(
             Metric.THRIFT_ACTIVE_THREADS.toString(),
             MetricLevel.CORE,
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceHandler.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceHandler.java
index 04640bc9b5..9fd02b55d6 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceHandler.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceHandler.java
@@ -16,7 +16,7 @@
  */
 package org.apache.iotdb.confignode.service.thrift;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -35,8 +35,7 @@ public class ConfigNodeRPCServiceHandler implements TServerEventHandler {
 
   @Override
   public ServerContext createContext(TProtocol arg0, TProtocol arg1) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(),
             MetricLevel.CORE,
@@ -50,8 +49,7 @@ public class ConfigNodeRPCServiceHandler implements TServerEventHandler {
   public void deleteContext(ServerContext arg0, TProtocol arg1, TProtocol arg2) {
     // release query resources.
     processor.handleClientExit();
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(),
             MetricLevel.CORE,
diff --git a/integration-test/src/test/resources/logback-test.xml b/integration-test/src/test/resources/logback-test.xml
index 1b26a07fd5..433fffc0f5 100644
--- a/integration-test/src/test/resources/logback-test.xml
+++ b/integration-test/src/test/resources/logback-test.xml
@@ -44,7 +44,7 @@
     <logger name="org.apache.iotdb.db.engine.merge" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.ThriftServiceThread" level="INFO"/>
     <logger name="org.eclipse.jetty.util.thread.QueuedThreadPool" level="INFO"/>
-    <logger name="org.apache.iotdb.db.service.metrics.MetricsService" level="INFO"/>
+    <logger name="org.apache.iotdb.db.service.metrics.MetricService" level="INFO"/>
     <logger name="org.apache.iotdb.db.engine.flush.FlushManager" level="INFO"/>
     <logger name="org.apache.iotdb.db.integration.IoTDBCompactionIT" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.RegisterManager" level="INFO"/>
diff --git a/integration/src/test/resources/logback-test.xml b/integration/src/test/resources/logback-test.xml
index a5177a7f55..a5ec897bb8 100644
--- a/integration/src/test/resources/logback-test.xml
+++ b/integration/src/test/resources/logback-test.xml
@@ -44,7 +44,7 @@
     <logger name="org.apache.iotdb.db.engine.merge" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.ThriftServiceThread" level="INFO"/>
     <logger name="org.eclipse.jetty.util.thread.QueuedThreadPool" level="INFO"/>
-    <logger name="org.apache.iotdb.db.service.metrics.MetricsService" level="INFO"/>
+    <logger name="org.apache.iotdb.db.service.metrics.MetricService" level="INFO"/>
     <logger name="org.apache.iotdb.db.engine.flush.FlushManager" level="INFO"/>
     <logger name="org.apache.iotdb.db.integration.IoTDBCompactionIT" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.RegisterManager" level="INFO"/>
diff --git a/metrics/ReadMe.md b/metrics/ReadMe.md
index 2b2ea63b40..74147f5b16 100644
--- a/metrics/ReadMe.md
+++ b/metrics/ReadMe.md
@@ -24,7 +24,7 @@ Metric Module
   - metrics-interface
   - dropwizard metric
   - micrometer metric
-- In each implementation, you can use many types of reporter to report the details of metric
+- In each implementation, you can use several types of reporter to report metric
   - Jmx Reporter
   - Prometheus Reporter
   - IoTDB Reporter
@@ -37,29 +37,26 @@ Metric Module
   - [2.4. Test Result](#24-test-result)
 - [3. How to use?](#3-how-to-use)
   - [3.1. Configuration](#31-configuration)
-  - [3.2. Module Use Guide](#32-module-use-guide)
-  - [3.3. Use Guide in IoTDB Server Module](#33-use-guide-in-iotdb-server-module)
+  - [3.2. Use Guide in IoTDB Server Module](#32-use-guide-in-iotdb-server-module)
 - [4. How to implement your own metric framework?](#4-how-to-implement-your-own-metric-framework)
 - [5. Some docs](#5-some-docs)
 
 # 1. Design
-1. The acquisition system consists of following four parts.
-   1. Metrics:Provide tools for collecting metric in different scenarios, including Counter, Gauge, Meter, Histogram, Timer, each with tags.
-   2. MetricManager
-      1. Provide functions such as creating, finding, updating, and deleting metrics.
-      2. Provide the ability to introduce default metrics(Known Metric).
-      3. Provide its own start and stop methods.
-   3. CompositeReporter
-      1. Provide management of reporter, including starting and stopping reporter.
-      2. Push the collector's data to other systems, such as Prometheus, JMX, etc.
-      3. Provide its own start and stop methods.
-   4. MetricService
-      1. Provide the start and stop method of metric module.
-      2. Provide the ability to hot load some properties.
-      3. Provide the access of metricManager and the control of reporters.
-2. The structure of acquisition system
-
-![](https://cwiki.apache.org/confluence/download/attachments/184616789/image2021-11-3_10-49-3.png?version=1&modificationDate=1635907745000&api=v2)
+> The acquisition system consists of following four parts.
+
+1. Metrics:Provide tools for collecting metric in different scenarios, including Counter, Gauge, Histogram, Timer and Rate, each with tags.
+2. MetricManager
+   1. Provide functions such as create, query, update and remove metrics.
+   2. Provide its own start and stop methods.
+3. CompositeReporter
+   1. Provide management of reporter.
+   2. Provide metric value to other systems, such as Jmx, Prometheus, IoTDB, etc.
+   3. Provide its own start and stop methods.
+4. MetricService
+   1. Provide the start and stop method of metric service.
+   2. Provide the ability to reload properties when running.
+   3. Provide the ability to load predefined metric sets.
+   4. Provide the access of metricManager and CompositeReporter.
 
 # 2. Test Report
 We implemented the monitoring framework using Dropwizard and Micrometer respectively, and tested the results as follows:
@@ -101,58 +98,32 @@ System.setProperty("IOTDB_CONF", "metrics/dropwizard-metrics/src/test/resources"
 
 2. Then, you can modify `iotdb-metric.yml` as you like, some details:
 
-| properties         | meaning                                               | example                |
-| ------------------ | ----------------------------------------------------- | ---------------------- |
-| enableMetric       | whether enable the module                             | true                   |
-| metricReporterList | the list of reporter                                  | JMX, PROMETHEUS        |
-| predefinedMetrics  | predefined set of metrics                             | JMX, LOGBACK           |
-| metricLevel | the init level of metrics| ALL, NORMAL, IMPORTANT, CORE |
-| monitorType        | The type of monitor manager                           | DROPWIZARD, MICROMETER |
-| pushPeriodInSecond | the period time of push(used for prometheus, unit: s) | 5                      |
-
-## 3.2. Module Use Guide
-1. After all above, you can use it in the following way
-   1. use `startService` method to load manager and reporters.
-   2. use `MetricService.getMetricManager()` to get metric manager.
-   3. use the method in metric manager, method details in `metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricManager`
-2. example code
+| properties                 | meaning                                                                                | example                             |
+| -------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------- |
+| enableMetric               | whether enable the module                                                              | true                                |
+| enablePerformanceStat      | Is stat performance of operation latency                                               | true                                |
+| metricReporterList         | the list of reporter                                                                   | JMX, PROMETHEUS, IOTDB              |
+| monitorType                | The type of metric manager                                                             | DROPWIZARD, MICROMETER              |
+| metricLevel                | the init level of metrics                                                              | ALL, NORMAL, IMPORTANT, CORE        |
+| predefinedMetrics          | predefined set of metrics                                                              | JVM, LOGBACK, FILE, PROCESS, SYSTEM |
+| asyncCollectPeriodInSecond | The period of the collection of some metrics in asynchronous way, such as tsfile size. | 5                                   |
+| pushPeriodInSecond         | the period time of push(used for prometheus, unit: s)                                  | 5                                   |
+
+## 3.2. Use Guide in IoTDB Server Module
+1. Now, MetricService is registered as IService in server and confignode module, you can simple set properties: `enableMetric: true` to use metric service.
+2. In server module you can easily use these metric by `MetricService.getInstance()`, for example:
 
 ```java
-public class PrometheusRunTest {
-  static MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
-  static MetricService metricService = new DoNothingMetricService();
-  static MetricManager metricManager;
-
-  public static void main(String[] args) throws InterruptedException {
-    metricConfig.setMonitorType(MonitorType.dropwizard);
-    metricConfig.setPredefinedMetrics(new ArrayList<>());
-    metricService.startService();
-    metricManager = metricService.getMetricManager();
-    Counter counter = metricManager.getOrCreateCounter("counter", MetricLevel.IMPORTANT);
-    while (true) {
-      counter.inc();
-      TimeUnit.SECONDS.sleep(1);
-    }
-  }
-}
-```
-
-## 3.3. Use Guide in IoTDB Server Module
-1. Now, MetricsService is registered as IService in server module, you can simple set properties: `enableMetric: true` to get a instance of MetricsService.
-2. In server module you can easily use these metric by `MetricsService.getInstance().getMetricManager()`, for example:
-
-```java
-MetricsService.getInstance()
-   .count(1, "operation_count", MetricLevel.IMPORTANT, "name", operation.getName());
+MetricService.getInstance().count(1, "operation_count", MetricLevel.IMPORTANT, "name", operation.getName());
 ```
 
 # 4. How to implement your own metric framework?
 1. implement your MetricService
-   1. You need to implement `collectFileSystemInfo` to collect file system info as you like.
-   2. You need to implement `reloadProperties` to support hot load.
+   1. You need to implement `enablePredefinedMetrics` to load predefined metrics.
+   2. You need to implement `reloadProperties` to reload properties when running.
 2. implement your MetricManager
    1. The name of MetricManager should start with `monitorType`, MetricService will init manager according to the prefix of class name.
-   2. You need to create `src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager`,and record your MetricManager class name in this file, such as `org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager`
+   2. You need to create `src/main/resources/META-INF/services/org.apache.iotdb.metrics.AbstractMetricManager`,and record your MetricManager class name in this file, such as `org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager`
 3. implement your reporter
    1. You need to implement jmx reporter and prometheus reporter, notice that your jmx bean name should be unified as `org.apache.iotdb.metrics`
    2. The name of your reporter should also start with `monitorType`
@@ -165,5 +136,5 @@ MetricsService.getInstance()
    2. then you need to fix the implementation of `enablePredefinedMetric(PredefinedMetric metric)` in your manager.
 
 # 5. Some docs
-1. <a href = "https://cwiki.apache.org/confluence/display/IOTDB/Monitor+Module">Monitor Module</a>
-2. <a href = "https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=184616789">Monitor Module(zh)</a>
\ No newline at end of file
+1. <a href = "https://iotdb.apache.org/UserGuide/Master/Maintenance-Tools/Metric-Tool.html">Metric Tool</a>
+2. <a href = "https://iotdb.apache.org/zh/UserGuide/Master/Maintenance-Tools/Metric-Tool.html">Metric Tool(zh)</a>
\ No newline at end of file
diff --git a/metrics/dropwizard-metrics/pom.xml b/metrics/dropwizard-metrics/pom.xml
index 650677f1ba..51b7b65af7 100644
--- a/metrics/dropwizard-metrics/pom.xml
+++ b/metrics/dropwizard-metrics/pom.xml
@@ -36,12 +36,12 @@
         <dependency>
             <groupId>io.dropwizard.metrics</groupId>
             <artifactId>metrics-jvm</artifactId>
-            <version>${metrics.version}</version>
+            <version>${dropwizard.metrics.version}</version>
         </dependency>
         <dependency>
             <groupId>io.dropwizard.metrics</groupId>
             <artifactId>metrics-jmx</artifactId>
-            <version>${metrics.version}</version>
+            <version>${dropwizard.metrics.version}</version>
         </dependency>
         <dependency>
             <groupId>com.sun.jersey</groupId>
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManager.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManager.java
index 294a771346..693c10f506 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManager.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManager.java
@@ -19,389 +19,80 @@
 
 package org.apache.iotdb.metrics.dropwizard;
 
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.config.MetricConfig;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.dropwizard.type.DropwizardAutoGauge;
 import org.apache.iotdb.metrics.dropwizard.type.DropwizardCounter;
 import org.apache.iotdb.metrics.dropwizard.type.DropwizardGauge;
 import org.apache.iotdb.metrics.dropwizard.type.DropwizardHistogram;
 import org.apache.iotdb.metrics.dropwizard.type.DropwizardRate;
 import org.apache.iotdb.metrics.dropwizard.type.DropwizardTimer;
-import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
 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.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricInfo;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import com.codahale.metrics.MetricFilter;
 import com.codahale.metrics.MetricRegistry;
-import com.codahale.metrics.UniformReservoir;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
 import java.util.function.ToLongFunction;
 
 /**
  * Metric manager based on dropwizard metrics. More details in https://metrics.dropwizard.io/4.1.2/.
  */
 @SuppressWarnings("common-java:DuplicatedBlocks")
-public class DropwizardMetricManager implements MetricManager {
-  private static final Logger logger = LoggerFactory.getLogger(DropwizardMetricManager.class);
-
-  Map<MetricName, IMetric> currentMeters;
-  /** whether is able to monitor */
-  boolean isEnable;
-
+public class DropwizardMetricManager extends AbstractMetricManager {
   com.codahale.metrics.MetricRegistry metricRegistry;
-  MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
-  MetricRegistry.MetricSupplier<com.codahale.metrics.Timer> timerMetricSupplier =
-      () -> new com.codahale.metrics.Timer(new UniformReservoir());
-  MetricRegistry.MetricSupplier<com.codahale.metrics.Histogram> histogramMetricSupplier =
-      () -> new com.codahale.metrics.Histogram(new UniformReservoir());
 
-  /** init the field with dropwizard library. */
   public DropwizardMetricManager() {
     metricRegistry = new MetricRegistry();
-    isEnable = metricConfig.getEnableMetric();
-    currentMeters = new ConcurrentHashMap<>();
-  }
-
-  @Override
-  public Counter getOrCreateCounter(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingCounter;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name, key -> new DropwizardCounter(metricRegistry.counter(name.toFlatString())));
-    if (m instanceof Counter) {
-      return (Counter) m;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public <T> Gauge getOrCreateAutoGauge(
-      String metric, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingGauge;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key -> {
-              DropwizardAutoGauge<T> dropwizardGauge = new DropwizardAutoGauge<>(obj, mapper);
-              metricRegistry.register(name.toFlatString(), dropwizardGauge);
-              return dropwizardGauge;
-            });
-    if (m instanceof Gauge) {
-      return (Gauge) m;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Gauge getOrCreateGauge(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingGauge;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key -> {
-              DropwizardGauge dropwizardGauge = new DropwizardGauge();
-              metricRegistry.register(
-                  name.toFlatString(), dropwizardGauge.getDropwizardCachedGauge());
-              return dropwizardGauge;
-            });
-    if (m instanceof Gauge) {
-      return (Gauge) m;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Rate getOrCreateRate(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingRate;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name, key -> new DropwizardRate(metricRegistry.meter(name.toFlatString())));
-    if (m instanceof Rate) {
-      return (Rate) m;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Histogram getOrCreateHistogram(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingHistogram;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key ->
-                new DropwizardHistogram(
-                    metricRegistry.histogram(name.toFlatString(), histogramMetricSupplier)));
-    if (m instanceof Histogram) {
-      return (Histogram) m;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Timer getOrCreateTimer(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable()) {
-      return DoNothingMetricManager.doNothingTimer;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key ->
-                new DropwizardTimer(
-                    metricRegistry.timer(name.toFlatString(), timerMetricSupplier)));
-    if (m instanceof Timer) {
-      return (Timer) m;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void count(long delta, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name, key -> new DropwizardCounter(metricRegistry.counter(name.toFlatString())));
-    if (m instanceof Counter) {
-      ((Counter) m).inc(delta);
-      return;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void gauge(long value, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key -> {
-              DropwizardGauge dropwizardGauge = new DropwizardGauge();
-              metricRegistry.register(
-                  name.toFlatString(), dropwizardGauge.getDropwizardCachedGauge());
-              return dropwizardGauge;
-            });
-    if (m instanceof Gauge) {
-      ((Gauge) m).set(value);
-      return;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void rate(long value, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name, key -> new DropwizardRate(metricRegistry.meter(name.toFlatString())));
-    if (m instanceof Rate) {
-      ((Rate) m).mark(value);
-      return;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
   }
 
   @Override
-  public void histogram(long value, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key ->
-                new DropwizardHistogram(
-                    metricRegistry.histogram(name.toFlatString(), histogramMetricSupplier)));
-    if (m instanceof Histogram) {
-      ((Histogram) m).update(value);
-      return;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
+  public Counter createCounter(MetricInfo metricInfo) {
+    return new DropwizardCounter(
+        metricRegistry.counter(DropwizardMetricNameTool.toFlatString(metricInfo)));
   }
 
   @Override
-  public void timer(
-      long delta, TimeUnit timeUnit, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName name = new MetricName(metric, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            name,
-            key ->
-                new DropwizardTimer(
-                    metricRegistry.timer(name.toFlatString(), timerMetricSupplier)));
-
-    if (m instanceof Timer) {
-      ((Timer) m).update(delta, timeUnit);
-      return;
-    }
-    throw new IllegalArgumentException(name + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void removeCounter(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName name = new MetricName(metric, tags);
-    metricRegistry.remove(name.toFlatString());
-    currentMeters.remove(name);
+  public <T> Gauge createAutoGauge(MetricInfo metricInfo, T obj, ToLongFunction<T> mapper) {
+    DropwizardAutoGauge<T> dropwizardGauge = new DropwizardAutoGauge<>(obj, mapper);
+    metricRegistry.register(DropwizardMetricNameTool.toFlatString(metricInfo), dropwizardGauge);
+    return dropwizardGauge;
   }
 
   @Override
-  public void removeGauge(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName name = new MetricName(metric, tags);
-    metricRegistry.remove(name.toFlatString());
-    currentMeters.remove(name);
+  public Gauge createGauge(MetricInfo metricInfo) {
+    DropwizardGauge dropwizardGauge = new DropwizardGauge();
+    metricRegistry.register(
+        DropwizardMetricNameTool.toFlatString(metricInfo),
+        dropwizardGauge.getDropwizardCachedGauge());
+    return dropwizardGauge;
   }
 
   @Override
-  public void removeRate(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName name = new MetricName(metric, tags);
-    metricRegistry.remove(name.toFlatString());
-    currentMeters.remove(name);
+  public Rate createRate(MetricInfo metricInfo) {
+    return new DropwizardRate(
+        metricRegistry.meter(DropwizardMetricNameTool.toFlatString(metricInfo)));
   }
 
   @Override
-  public void removeHistogram(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName name = new MetricName(metric, tags);
-    metricRegistry.remove(name.toFlatString());
-    currentMeters.remove(name);
+  public Histogram createHistogram(MetricInfo metricInfo) {
+    return new DropwizardHistogram(
+        metricRegistry.histogram(DropwizardMetricNameTool.toFlatString(metricInfo)));
   }
 
   @Override
-  public void removeTimer(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName name = new MetricName(metric, tags);
-    metricRegistry.remove(name.toFlatString());
-    currentMeters.remove(name);
+  public Timer createTimer(MetricInfo metricInfo) {
+    return new DropwizardTimer(
+        metricRegistry.timer(DropwizardMetricNameTool.toFlatString(metricInfo)));
   }
 
   @Override
-  public List<String[]> getAllMetricKeys() {
-    if (!isEnable()) {
-      return Collections.emptyList();
-    }
-    List<String[]> keys = new ArrayList<>(currentMeters.size());
-    currentMeters.keySet().forEach(k -> keys.add(k.toStringArray()));
-    return keys;
-  }
-
-  @Override
-  public Map<String[], Counter> getAllCounters() {
-    Map<String[], Counter> counterMap = new HashMap<>();
-    for (Map.Entry<MetricName, IMetric> entry : currentMeters.entrySet()) {
-      if (entry.getValue() instanceof Counter) {
-        counterMap.put(entry.getKey().toStringArray(), (Counter) entry.getValue());
-      }
-    }
-    return counterMap;
-  }
-
-  @Override
-  public Map<String[], Gauge> getAllGauges() {
-    Map<String[], Gauge> gaugeMap = new HashMap<>();
-    for (Map.Entry<MetricName, IMetric> entry : currentMeters.entrySet()) {
-      if (entry.getValue() instanceof Gauge) {
-        gaugeMap.put(entry.getKey().toStringArray(), (Gauge) entry.getValue());
-      }
-    }
-    return gaugeMap;
-  }
-
-  @Override
-  public Map<String[], Rate> getAllRates() {
-    Map<String[], Rate> rateMap = new HashMap<>();
-    for (Map.Entry<MetricName, IMetric> entry : currentMeters.entrySet()) {
-      if (entry.getValue() instanceof Rate) {
-        rateMap.put(entry.getKey().toStringArray(), (Rate) entry.getValue());
-      }
-    }
-    return rateMap;
-  }
-
-  @Override
-  public Map<String[], Histogram> getAllHistograms() {
-    Map<String[], Histogram> histogramMap = new HashMap<>();
-    for (Map.Entry<MetricName, IMetric> entry : currentMeters.entrySet()) {
-      if (entry.getValue() instanceof Histogram) {
-        histogramMap.put(entry.getKey().toStringArray(), (Histogram) entry.getValue());
-      }
-    }
-    return histogramMap;
-  }
-
-  @Override
-  public Map<String[], Timer> getAllTimers() {
-    Map<String[], Timer> timerMap = new HashMap<>();
-    for (Map.Entry<MetricName, IMetric> entry : currentMeters.entrySet()) {
-      if (entry.getValue() instanceof Timer) {
-        timerMap.put(entry.getKey().toStringArray(), (Timer) entry.getValue());
-      }
-    }
-    return timerMap;
-  }
-
-  @Override
-  public boolean isEnable() {
-    return isEnable;
-  }
-
-  @Override
-  public boolean isEnable(MetricLevel metricLevel) {
-    return isEnable() && MetricLevel.higherOrEqual(metricLevel, metricConfig.getMetricLevel());
+  protected void remove(MetricType type, MetricInfo metricInfo) {
+    metricRegistry.remove(DropwizardMetricNameTool.toFlatString(metricInfo));
   }
 
   public MetricRegistry getMetricRegistry() {
@@ -409,16 +100,8 @@ public class DropwizardMetricManager implements MetricManager {
   }
 
   @Override
-  public boolean init() {
-    // init something
-    return true;
-  }
-
-  @Override
-  public boolean stop() {
-    isEnable = metricConfig.getEnableMetric();
+  public boolean stopFramework() {
     metricRegistry.removeMatching(MetricFilter.ALL);
-    currentMeters = new ConcurrentHashMap<>();
     return true;
   }
 }
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricNameTool.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricNameTool.java
new file mode 100644
index 0000000000..049ca46c94
--- /dev/null
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricNameTool.java
@@ -0,0 +1,66 @@
+/*
+ * 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.dropwizard;
+
+import org.apache.iotdb.metrics.utils.MetricInfo;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class DropwizardMetricNameTool {
+  private static final String TAG_SEPARATOR = ".";
+
+  public static MetricInfo transformFromString(MetricType metricType, String flatString) {
+    MetricInfo metricInfo;
+    String name;
+    int firstIndex = flatString.indexOf("{");
+    int lastIndex = flatString.indexOf("}");
+    if (firstIndex == -1 || lastIndex == -1) {
+      name = flatString.replaceAll("[^a-zA-Z0-9:_\\]\\[]", "_");
+      metricInfo = new MetricInfo(metricType, name);
+    } else {
+      name = flatString.substring(0, firstIndex).replaceAll("[^a-zA-Z0-9:_\\]\\[]", "_");
+      String tagsPart = flatString.substring(firstIndex + 1, lastIndex);
+      if (0 == tagsPart.length()) {
+        metricInfo = new MetricInfo(metricType, name);
+      } else {
+        metricInfo = new MetricInfo(metricType, name, tagsPart.split("\\."));
+      }
+    }
+    return metricInfo;
+  }
+
+  public static String toFlatString(MetricInfo metricInfo) {
+    String name = metricInfo.getName();
+    Map<String, String> tags = metricInfo.getTags();
+    return name.replaceAll("\\{|\\}", "")
+        + "{"
+        + tags.entrySet().stream()
+            .map(
+                t ->
+                    t.getKey().replace(TAG_SEPARATOR, "")
+                        + TAG_SEPARATOR
+                        + t.getValue().replace(TAG_SEPARATOR, ""))
+            .collect(Collectors.joining(TAG_SEPARATOR))
+            .replaceAll("\\{|\\}", "")
+        + "}";
+  }
+}
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/MetricName.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/MetricName.java
deleted file mode 100644
index 50186e6ba5..0000000000
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/MetricName.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * 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.dropwizard;
-
-import org.apache.iotdb.metrics.utils.MetricLevel;
-
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/** the unique identifier of a metric, include a name and some tags. */
-public class MetricName {
-  private String name;
-  private MetricLevel metricLevel;
-  private Map<String, String> tags = new LinkedHashMap<>();
-  private static final String TAG_SEPARATOR = ".";
-
-  public MetricName(String name, String... tags) {
-    this.name = name;
-    if (tags.length % 2 == 0) {
-      for (int i = 0; i < tags.length; i += 2) {
-        this.tags.put(tags[i], tags[i + 1]);
-      }
-    }
-  }
-  /**
-   * the unique identifier of a metric, include a name and some tags.
-   *
-   * @param name metric name
-   * @param metricLevel metric level
-   * @param tags string appear in pairs, like sg="ln",user="user1" will be "sg", "ln", "user",
-   *     "user1"
-   */
-  public MetricName(String name, MetricLevel metricLevel, String... tags) {
-    this(name, tags);
-    this.metricLevel = metricLevel;
-  }
-
-  /** Create metric name from flatString */
-  public MetricName(String flatString) {
-    int firstIndex = flatString.indexOf("{");
-    int lastIndex = flatString.indexOf("}");
-    if (firstIndex == -1 || lastIndex == -1) {
-      String sanitizeMetricName = flatString.replaceAll("[^a-zA-Z0-9:_\\]\\[]", "_");
-      this.name = sanitizeMetricName;
-    } else {
-      String[] labelsFlat = flatString.substring(firstIndex + 1, lastIndex).split("\\.");
-      String sanitizeMetricName =
-          flatString.substring(0, firstIndex).replaceAll("[^a-zA-Z0-9:_\\]\\[]", "_");
-      if (labelsFlat.length == 0) {
-        this.name = sanitizeMetricName;
-      } else {
-        this.name = sanitizeMetricName;
-        if (labelsFlat.length % 2 == 0) {
-          for (int i = 0; i < labelsFlat.length; i += 2) {
-            this.tags.put(labelsFlat[i], labelsFlat[i + 1]);
-          }
-        }
-      }
-    }
-  }
-
-  /**
-   * convert the metric name to flat string
-   *
-   * @return the flat string
-   */
-  public String toFlatString() {
-    StringBuilder stringBuilder = new StringBuilder(name.replaceAll("\\{|\\}", ""));
-    stringBuilder.append("{");
-    stringBuilder.append(
-        tags.entrySet().stream()
-            .map(
-                t ->
-                    t.getKey().replace(TAG_SEPARATOR, "")
-                        + TAG_SEPARATOR
-                        + t.getValue().replace(TAG_SEPARATOR, ""))
-            .collect(Collectors.joining(TAG_SEPARATOR))
-            .replaceAll("\\{|\\}", ""));
-    stringBuilder.append("}");
-    return stringBuilder.toString();
-  }
-
-  /** convert the metric name to string array. */
-  public 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]);
-  }
-
-  @Override
-  public String toString() {
-    return "MetricName{" + "name='" + name + "'" + ", tags=" + tags + '}';
-  }
-
-  public String getName() {
-    return name;
-  }
-
-  public void setName(String name) {
-    this.name = name;
-  }
-
-  public MetricLevel getMetricLevel() {
-    return metricLevel;
-  }
-
-  public void setMetricLevel(MetricLevel metricLevel) {
-    this.metricLevel = metricLevel;
-  }
-
-  public Map<String, String> getTags() {
-    return tags;
-  }
-
-  public void setTags(Map<String, String> tags) {
-    this.tags = tags;
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    // do not compare metricLevel
-    if (!(obj instanceof MetricName)) {
-      return false;
-    }
-    MetricName that = (MetricName) obj;
-    if (!this.name.equals(that.name)) {
-      return false;
-    }
-    if (that.getTags().size() != this.tags.size()) {
-      return false;
-    }
-    Map<String, String> thatTags = that.getTags();
-    for (Map.Entry<String, String> entry : this.tags.entrySet()) {
-      if (!thatTags.containsKey(entry.getKey())) {
-        return false;
-      }
-      if (!thatTags.get(entry.getKey()).equals(entry.getValue())) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @Override
-  public int hashCode() {
-    return Objects.hash(name, tags);
-  }
-}
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
index 81cc32841f..6020a1c6d8 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardIoTDBReporter.java
@@ -19,47 +19,51 @@
 
 package org.apache.iotdb.metrics.dropwizard.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager;
 import org.apache.iotdb.metrics.reporter.Reporter;
 import org.apache.iotdb.metrics.utils.ReporterType;
 
 import com.codahale.metrics.MetricFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.concurrent.TimeUnit;
 
 public class DropwizardIoTDBReporter implements Reporter {
+  private static final Logger LOGGER = LoggerFactory.getLogger(DropwizardIoTDBReporter.class);
 
-  private MetricManager dropwizardMetricManager = null;
-  private IoTDBReporter ioTDBReporter;
-
-  private static final MetricConfig metricConfig =
-      MetricConfigDescriptor.getInstance().getMetricConfig();
+  private AbstractMetricManager dropwizardMetricManager = null;
+  private IoTDBReporter reporter;
 
   @Override
   public boolean start() {
-    if (!metricConfig.getEnableMetric()) {
+    if (reporter != null) {
+      LOGGER.warn("Dropwizard IoTDBReporter already start!");
       return false;
     }
-    ioTDBReporter =
+    reporter =
         IoTDBReporter.forRegistry(
                 ((DropwizardMetricManager) dropwizardMetricManager).getMetricRegistry())
             .prefixedWith("dropwizard:")
             .filter(MetricFilter.ALL)
             .build();
-    ioTDBReporter.start(
-        metricConfig.getIoTDBReporterConfig().getPushPeriodInSecond(), TimeUnit.SECONDS);
+    reporter.start(
+        MetricConfigDescriptor.getInstance()
+            .getMetricConfig()
+            .getIoTDBReporterConfig()
+            .getPushPeriodInSecond(),
+        TimeUnit.SECONDS);
     return true;
   }
 
   @Override
   public boolean stop() {
-    if (ioTDBReporter == null) {
-      return false;
+    if (reporter != null) {
+      reporter.stop();
+      reporter = null;
     }
-    ioTDBReporter.stop();
     return true;
   }
 
@@ -69,7 +73,7 @@ public class DropwizardIoTDBReporter implements Reporter {
   }
 
   @Override
-  public void setMetricManager(MetricManager metricManager) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     this.dropwizardMetricManager = metricManager;
   }
 }
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardJmxReporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardJmxReporter.java
index 991d6aa917..f61cf2bd30 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardJmxReporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardJmxReporter.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.metrics.dropwizard.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager;
 import org.apache.iotdb.metrics.reporter.Reporter;
 import org.apache.iotdb.metrics.utils.ReporterType;
@@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory;
 public class DropwizardJmxReporter implements Reporter {
   private static final Logger LOGGER = LoggerFactory.getLogger(DropwizardJmxReporter.class);
 
-  private MetricManager dropwizardMetricManager = null;
+  private AbstractMetricManager dropwizardMetricManager = null;
   private JmxReporter jmxReporter = null;
 
   @Override
@@ -56,12 +56,10 @@ public class DropwizardJmxReporter implements Reporter {
 
   @Override
   public boolean stop() {
-    if (jmxReporter == null) {
-      LOGGER.warn("Dropwizard JmxReporter already stop!");
-      return false;
+    if (jmxReporter != null) {
+      jmxReporter.stop();
+      jmxReporter = null;
     }
-    jmxReporter.stop();
-    jmxReporter = null;
     return true;
   }
 
@@ -71,7 +69,7 @@ public class DropwizardJmxReporter implements Reporter {
   }
 
   @Override
-  public void setMetricManager(MetricManager metricManager) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     this.dropwizardMetricManager = metricManager;
   }
 }
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/MetricType.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricType.java
similarity index 93%
rename from metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/MetricType.java
rename to metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricType.java
index a07a8fd8fb..aa55bf6c57 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/MetricType.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricType.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.metrics.dropwizard.reporter;
 
-enum MetricType {
+public enum DropwizardMetricType {
   COUNTER("counter"),
   GAUGE("gauge"),
   SUMMARY("summary"),
@@ -28,7 +28,7 @@ enum MetricType {
 
   private final String text;
 
-  MetricType(String text) {
+  DropwizardMetricType(String text) {
     this.text = text;
   }
 
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricsExporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricsExporter.java
index eb6c88a7da..973a1cc155 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricsExporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardMetricsExporter.java
@@ -19,7 +19,9 @@
 
 package org.apache.iotdb.metrics.dropwizard.reporter;
 
-import org.apache.iotdb.metrics.dropwizard.MetricName;
+import org.apache.iotdb.metrics.dropwizard.DropwizardMetricNameTool;
+import org.apache.iotdb.metrics.utils.MetricInfo;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import com.codahale.metrics.Counter;
 import com.codahale.metrics.Gauge;
@@ -32,6 +34,7 @@ import com.codahale.metrics.Snapshot;
 import com.codahale.metrics.Timer;
 
 import java.io.IOException;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -65,10 +68,11 @@ class DropwizardMetricsExporter {
 
   /** Export Gauge as Prometheus Gauge */
   public void writeGauge(String dropwizardName, Gauge<?> gauge) throws IOException {
-    MetricName metricName = new MetricName(dropwizardName);
-    String sanitizeName = metricName.getName();
+    MetricInfo metricInfo =
+        DropwizardMetricNameTool.transformFromString(MetricType.GAUGE, dropwizardName);
+    String sanitizeName = metricInfo.getName();
     writer.writeHelp(sanitizeName, getHelpMessage(dropwizardName, gauge));
-    writer.writeType(sanitizeName, MetricType.GAUGE);
+    writer.writeType(sanitizeName, DropwizardMetricType.GAUGE);
 
     Object obj = gauge.getValue();
     double value;
@@ -80,22 +84,23 @@ class DropwizardMetricsExporter {
       return;
     }
 
-    writer.writeSample(sanitizeName, metricName.getTags(), value);
+    writer.writeSample(sanitizeName, metricInfo.getTags(), value);
   }
 
   /** Export counter as Prometheus Gauge */
   public void writeCounter(String dropwizardName, Counter counter) throws IOException {
-    MetricName metricName = new MetricName(dropwizardName);
-    String sanitizeName = metricName.getName();
+    MetricInfo metricInfo =
+        DropwizardMetricNameTool.transformFromString(MetricType.COUNTER, dropwizardName);
+    String sanitizeName = metricInfo.getName() + "_total";
     writer.writeHelp(sanitizeName, getHelpMessage(dropwizardName, counter));
-    writer.writeType(sanitizeName, MetricType.GAUGE);
-    writer.writeSample(sanitizeName, metricName.getTags(), counter.getCount());
+    writer.writeType(sanitizeName, DropwizardMetricType.GAUGE);
+    writer.writeSample(sanitizeName, metricInfo.getTags(), counter.getCount());
   }
 
   /** Export histogram snapshot as Prometheus SUMMARY */
   public void writeHistogram(String dropwizardName, Histogram histogram) throws IOException {
     writeSnapshotAndCount(
-        new MetricName(dropwizardName),
+        DropwizardMetricNameTool.transformFromString(MetricType.HISTOGRAM, dropwizardName),
         histogram.getSnapshot(),
         histogram.getCount(),
         1.0,
@@ -104,59 +109,45 @@ class DropwizardMetricsExporter {
 
   /** Export histogram snapshot */
   private void writeSnapshotAndCount(
-      MetricName metricName, Snapshot snapshot, long count, double factor, String helpMessage)
+      MetricInfo metricInfo, Snapshot snapshot, long count, double factor, String helpMessage)
       throws IOException {
-    String sanitizeName = metricName.getName();
+    String sanitizeName = metricInfo.getName() + "_seconds";
     writer.writeHelp(sanitizeName, helpMessage);
-    writer.writeType(sanitizeName, MetricType.SUMMARY);
-    Map<String, String> tags = metricName.getTags();
+    writer.writeType(sanitizeName, DropwizardMetricType.SUMMARY);
+    Map<String, String> tags = metricInfo.getTags();
+    writer.writeSample(sanitizeName + "_max", tags, snapshot.getMax() * factor);
     writer.writeSample(
-        sanitizeName, addTags(tags, "quantile", "0.5"), snapshot.getMedian() * factor);
-    writer.writeSample(
-        sanitizeName, addTags(tags, "quantile", "0.75"), snapshot.get75thPercentile() * factor);
-    writer.writeSample(
-        sanitizeName, addTags(tags, "quantile", "0.95"), snapshot.get95thPercentile() * factor);
-    writer.writeSample(
-        sanitizeName, addTags(tags, "quantile", "0.98"), snapshot.get98thPercentile() * factor);
-    writer.writeSample(
-        sanitizeName, addTags(tags, "quantile", "0.99"), snapshot.get99thPercentile() * factor);
-    writer.writeSample(
-        sanitizeName, addTags(tags, "quantile", "0.999"), snapshot.get999thPercentile() * factor);
-    writer.writeSample(sanitizeName + "_min", tags, snapshot.getMin());
-    writer.writeSample(sanitizeName + "_max", tags, snapshot.getMax());
-    writer.writeSample(sanitizeName + "_median", tags, snapshot.getMedian());
-    writer.writeSample(sanitizeName + "_mean", tags, snapshot.getMean());
-    writer.writeSample(sanitizeName + "_stddev", tags, snapshot.getStdDev());
+        sanitizeName + "_sum", tags, Arrays.stream(snapshot.getValues()).sum() * factor);
     writer.writeSample(sanitizeName + "_count", tags, count);
   }
 
   /** Export Timer as Prometheus Summary */
   public void writeTimer(String dropwizardName, Timer timer) throws IOException {
     writeSnapshotAndCount(
-        new MetricName(dropwizardName),
+        DropwizardMetricNameTool.transformFromString(MetricType.TIMER, dropwizardName),
         timer.getSnapshot(),
         timer.getCount(),
         1.0D / TimeUnit.SECONDS.toNanos(1L),
         getHelpMessage(dropwizardName, timer));
-    writeMetered(new MetricName(dropwizardName), timer);
   }
 
   /** Export Meter as Prometheus Counter */
   public void writeMeter(String dropwizardName, Meter meter) throws IOException {
-    MetricName metricName = new MetricName(dropwizardName);
-    String sanitizeName = metricName.getName() + "_total";
+    MetricInfo metricInfo =
+        DropwizardMetricNameTool.transformFromString(MetricType.COUNTER, dropwizardName);
+    String sanitizeName = metricInfo.getName() + "_total";
 
     writer.writeHelp(sanitizeName, getHelpMessage(dropwizardName, meter));
-    writer.writeType(sanitizeName, MetricType.COUNTER);
-    writer.writeSample(sanitizeName, metricName.getTags(), meter.getCount());
+    writer.writeType(sanitizeName, DropwizardMetricType.COUNTER);
+    writer.writeSample(sanitizeName, metricInfo.getTags(), meter.getCount());
 
-    writeMetered(new MetricName(dropwizardName), meter);
+    writeMetered(metricInfo, meter);
   }
 
   /** Export meter for multi type */
-  private void writeMetered(MetricName metricName, Metered metered) throws IOException {
-    String sanitizeName = metricName.getName();
-    Map<String, String> tags = metricName.getTags();
+  private void writeMetered(MetricInfo metricInfo, Metered metered) throws IOException {
+    String sanitizeName = metricInfo.getName();
+    Map<String, String> tags = metricInfo.getTags();
     writer.writeSample(sanitizeName, addTags(tags, "rate", "m1"), metered.getOneMinuteRate());
     writer.writeSample(sanitizeName, addTags(tags, "rate", "m5"), metered.getFiveMinuteRate());
     writer.writeSample(sanitizeName, addTags(tags, "rate", "m15"), metered.getFifteenMinuteRate());
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardPrometheusReporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardPrometheusReporter.java
index 54bd86f806..4706dc0fa0 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardPrometheusReporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/DropwizardPrometheusReporter.java
@@ -19,8 +19,7 @@
 
 package org.apache.iotdb.metrics.dropwizard.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.dropwizard.DropwizardMetricManager;
 import org.apache.iotdb.metrics.reporter.Reporter;
@@ -41,10 +40,8 @@ import java.time.Duration;
 
 public class DropwizardPrometheusReporter implements Reporter {
   private static final Logger LOGGER = LoggerFactory.getLogger(DropwizardPrometheusReporter.class);
-  private static final MetricConfig metricConfig =
-      MetricConfigDescriptor.getInstance().getMetricConfig();
 
-  private MetricManager dropwizardMetricManager = null;
+  private AbstractMetricManager dropwizardMetricManager = null;
   private DisposableServer httpServer = null;
 
   @Override
@@ -53,11 +50,12 @@ public class DropwizardPrometheusReporter implements Reporter {
       LOGGER.warn("Dropwizard Prometheus Reporter already start!");
       return false;
     }
+    int port = MetricConfigDescriptor.getInstance().getMetricConfig().getPrometheusExporterPort();
     httpServer =
         HttpServer.create()
             .idleTimeout(Duration.ofMillis(30_000L))
             .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
-            .port(Integer.parseInt(metricConfig.getPrometheusExporterPort()))
+            .port(port)
             .route(
                 routes ->
                     routes.get(
@@ -65,8 +63,7 @@ public class DropwizardPrometheusReporter implements Reporter {
                         (request, response) -> response.sendString(Mono.just(scrape()))))
             .bindNow();
 
-    LOGGER.info(
-        "http server for metrics started, listen on {}", metricConfig.getPrometheusExporterPort());
+    LOGGER.info("http server for metrics started, listen on {}", port);
     return true;
   }
 
@@ -114,7 +111,7 @@ public class DropwizardPrometheusReporter implements Reporter {
   }
 
   @Override
-  public void setMetricManager(MetricManager metricManager) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     this.dropwizardMetricManager = metricManager;
   }
 }
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/IoTDBReporter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/IoTDBReporter.java
index feb335ea83..c93a78c631 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/IoTDBReporter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/IoTDBReporter.java
@@ -21,8 +21,10 @@ package org.apache.iotdb.metrics.dropwizard.reporter;
 
 import org.apache.iotdb.metrics.config.MetricConfig;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
-import org.apache.iotdb.metrics.dropwizard.MetricName;
+import org.apache.iotdb.metrics.dropwizard.DropwizardMetricNameTool;
 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.rpc.IoTDBConnectionException;
 import org.apache.iotdb.rpc.StatementExecutionException;
 import org.apache.iotdb.session.pool.SessionPool;
@@ -160,14 +162,14 @@ public class IoTDBReporter extends ScheduledReporter {
     if (null == gauge) {
       return;
     }
-    MetricName metricName = new MetricName(name);
+    MetricInfo metricInfo = DropwizardMetricNameTool.transformFromString(MetricType.GAUGE, name);
     Object obj = gauge.getValue();
     double value;
     if (obj instanceof Number) {
       value = ((Number) obj).doubleValue();
-      updateValue(prefixed(metricName.getName()), metricName.getTags(), value);
+      updateValue(prefixed(metricInfo.getName()), metricInfo.getTags(), value);
     } else if (obj instanceof Boolean) {
-      updateValue(prefixed(metricName.getName()), metricName.getTags(), obj);
+      updateValue(prefixed(metricInfo.getName()), metricInfo.getTags(), obj);
     }
   }
 
@@ -175,19 +177,20 @@ public class IoTDBReporter extends ScheduledReporter {
     if (null == counter) {
       return;
     }
-    MetricName metricName = new MetricName(name);
+    MetricInfo metricInfo = DropwizardMetricNameTool.transformFromString(MetricType.COUNTER, name);
     double value = counter.getCount();
-    updateValue(prefixed(metricName.getName()), metricName.getTags(), value);
+    updateValue(prefixed(metricInfo.getName()), metricInfo.getTags(), value);
   }
 
   private void sendHistogram(String name, Histogram histogram) {
     if (null == histogram) {
       return;
     }
-    MetricName metricName = new MetricName(name);
+    MetricInfo metricInfo =
+        DropwizardMetricNameTool.transformFromString(MetricType.HISTOGRAM, name);
     writeSnapshotAndCount(
-        prefixed(metricName.getName()),
-        metricName.getTags(),
+        prefixed(metricInfo.getName()),
+        metricInfo.getTags(),
         histogram.getSnapshot(),
         histogram.getCount(),
         1.0);
@@ -197,19 +200,19 @@ public class IoTDBReporter extends ScheduledReporter {
     if (null == meter) {
       return;
     }
-    MetricName metricName = new MetricName(name);
+    MetricInfo metricInfo = DropwizardMetricNameTool.transformFromString(MetricType.GAUGE, name);
     double value = meter.getCount();
-    updateValue(prefixed(metricName.getName()), metricName.getTags(), value);
+    updateValue(prefixed(metricInfo.getName()), metricInfo.getTags(), value);
   }
 
   private void sendTimer(String name, Timer timer) {
     if (null == timer) {
       return;
     }
-    MetricName metricName = new MetricName(name);
+    MetricInfo metricInfo = DropwizardMetricNameTool.transformFromString(MetricType.GAUGE, name);
     writeSnapshotAndCount(
-        prefixed(metricName.getName()),
-        metricName.getTags(),
+        prefixed(metricInfo.getName()),
+        metricInfo.getTags(),
         timer.getSnapshot(),
         timer.getCount(),
         1.0D / TimeUnit.SECONDS.toNanos(1L));
diff --git a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/PrometheusTextWriter.java b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/PrometheusTextWriter.java
index 2727eeee99..78ced26a2e 100644
--- a/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/PrometheusTextWriter.java
+++ b/metrics/dropwizard-metrics/src/main/java/org/apache/iotdb/metrics/dropwizard/reporter/PrometheusTextWriter.java
@@ -38,7 +38,7 @@ class PrometheusTextWriter extends FilterWriter {
     write('\n');
   }
 
-  public void writeType(String name, MetricType type) throws IOException {
+  public void writeType(String name, DropwizardMetricType type) throws IOException {
     write("# TYPE ");
     write(name);
     write(' ');
diff --git a/metrics/dropwizard-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager b/metrics/dropwizard-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.AbstractMetricManager
similarity index 100%
rename from metrics/dropwizard-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
rename to metrics/dropwizard-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.AbstractMetricManager
diff --git a/metrics/dropwizard-metrics/src/test/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManagerTest.java b/metrics/dropwizard-metrics/src/test/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManagerTest.java
deleted file mode 100644
index 6f391d9e7e..0000000000
--- a/metrics/dropwizard-metrics/src/test/java/org/apache/iotdb/metrics/dropwizard/DropwizardMetricManagerTest.java
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * 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.dropwizard;
-
-import org.apache.iotdb.metrics.DoNothingMetricService;
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.MetricService;
-import org.apache.iotdb.metrics.config.MetricConfig;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
-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.Rate;
-import org.apache.iotdb.metrics.type.Timer;
-import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.MonitorType;
-
-import org.junit.AfterClass;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-
-public class DropwizardMetricManagerTest {
-  static MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
-  static MetricService metricService = new DoNothingMetricService();
-  static MetricManager metricManager;
-
-  @BeforeClass
-  public static void init() {
-    metricConfig.setEnableMetric(true);
-    metricConfig.setMonitorType(MonitorType.DROPWIZARD);
-    metricConfig.setMetricLevel(MetricLevel.IMPORTANT);
-    metricConfig.setPredefinedMetrics(new ArrayList<>());
-    metricService.startService();
-    metricManager = metricService.getMetricManager();
-  }
-
-  @Test
-  public void getOrCreateCounter() {
-    Counter counter1 =
-        metricManager.getOrCreateCounter("counter_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(counter1);
-    Counter counter2 =
-        metricManager.getOrCreateCounter("counter_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(counter1, counter2);
-  }
-
-  private void getOrCreateDifferentMetricsWithSameName() {
-    Timer timer = metricManager.getOrCreateTimer("metric", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(timer);
-    metricManager.getOrCreateCounter("metric", MetricLevel.IMPORTANT, "tag1", "tag2");
-  }
-
-  @Test
-  public void getOrCreateDifferentMetricsWithSameNameTest() {
-    assertThrows(IllegalArgumentException.class, this::getOrCreateDifferentMetricsWithSameName);
-  }
-
-  @Test
-  public void getOrCreateGauge() {
-    Gauge gauge1 =
-        metricManager.getOrCreateGauge("gauge_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(gauge1);
-    Gauge gauge2 =
-        metricManager.getOrCreateGauge("gauge_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(gauge1, gauge2);
-  }
-
-  @Test
-  public void testAutoGauge() {
-    List<Integer> list = new ArrayList<>();
-    Gauge autoGauge =
-        metricManager.getOrCreateAutoGauge(
-            "autoGaugeMetric", MetricLevel.IMPORTANT, list, List::size, "tagk", "tagv");
-    assertEquals(0L, autoGauge.value());
-    list.add(1);
-    assertEquals(1L, autoGauge.value());
-    list.clear();
-    assertEquals(0L, autoGauge.value());
-    list.add(1);
-    assertEquals(1L, autoGauge.value());
-    list = null;
-    System.gc();
-    assertEquals(0L, autoGauge.value());
-  }
-
-  @Test
-  public void getOrCreateRate() {
-    Rate rate1 = metricManager.getOrCreateRate("rate_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(rate1);
-    Rate rate2 = metricManager.getOrCreateRate("rate_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(rate1, rate2);
-  }
-
-  @Test
-  public void getOrCreateHistogram() {
-    Histogram histogram1 =
-        metricManager.getOrCreateHistogram("histogram_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(histogram1);
-    Histogram histogram2 =
-        metricManager.getOrCreateHistogram("histogram_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(histogram1, histogram2);
-  }
-
-  @Test
-  public void getOrCreateTimer() {
-    Timer timer1 =
-        metricManager.getOrCreateTimer("timer_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(timer1);
-    Timer timer2 =
-        metricManager.getOrCreateTimer("timer_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(timer1, timer2);
-  }
-
-  @Test
-  public void count() {
-    Counter counter =
-        metricManager.getOrCreateCounter("count_inc", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(counter);
-    metricManager.count(10, "count_inc", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(counter.count(), 10);
-    metricManager.count(10L, "count_inc", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(counter.count(), 20);
-  }
-
-  @Test
-  public void gauge() {
-    Gauge gauge1 =
-        metricManager.getOrCreateGauge("gauge_set1", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(gauge1);
-    metricManager.gauge(10, "gauge_set1", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(10, gauge1.value());
-    Gauge gauge2 =
-        metricManager.getOrCreateGauge("gauge_set2", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.gauge(20L, "gauge_set2", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(20, gauge2.value());
-  }
-
-  @Test
-  public void rate() {
-    Rate rate = metricManager.getOrCreateRate("rate_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(rate);
-    metricManager.rate(10, "rate_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(10, rate.getCount());
-    metricManager.rate(20L, "rate_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(30, rate.getCount());
-  }
-
-  @Test
-  public void histogram() {
-    Histogram histogram =
-        metricManager.getOrCreateHistogram("history_count", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(histogram);
-    metricManager.histogram(10, "history_count", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.histogram(20L, "history_count", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.histogram(30, "history_count", MetricLevel.IMPORTANT, "tag1", "tag2");
-    try {
-      Thread.sleep(1000);
-    } catch (Exception e) {
-      // do nothing
-    }
-    metricManager.histogram(40L, "history_count", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.histogram(50, "history_count", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(5, histogram.count());
-    assertEquals(5, histogram.takeSnapshot().size());
-    assertEquals(10, histogram.takeSnapshot().getMin());
-    assertEquals(30.0, histogram.takeSnapshot().getMedian(), 1e-5);
-    assertEquals(30.0, histogram.takeSnapshot().getMean(), 1e-5);
-    assertEquals(50, histogram.takeSnapshot().getMax());
-  }
-
-  @Test
-  public void timer() {
-    Timer timer =
-        metricManager.getOrCreateTimer("timer_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.timer(2L, TimeUnit.MINUTES, "timer_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.timer(
-        4L, TimeUnit.MINUTES, "timer_" + "mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.timer(6L, TimeUnit.MINUTES, "timer_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    try {
-      Thread.sleep(1000);
-    } catch (Exception e) {
-      // do nothing
-    }
-    metricManager.timer(8L, TimeUnit.MINUTES, "timer_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.timer(10L, TimeUnit.MINUTES, "timer_mark", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertEquals(5, timer.getImmutableRate().getCount());
-    assertEquals(5, timer.takeSnapshot().size());
-    assertEquals(120000000000L, timer.takeSnapshot().getMin());
-    assertEquals(360000000000L, timer.takeSnapshot().getMedian(), 1e-5);
-    assertEquals(360000000000L, timer.takeSnapshot().getMean(), 1e-5);
-    assertEquals(600000000000L, timer.takeSnapshot().getMax());
-  }
-
-  @Test
-  public void removeCounter() {
-    Counter counter1 =
-        metricManager.getOrCreateCounter("counter_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.removeCounter("counter_remove", "tag1", "tag2");
-    Counter counter2 =
-        metricManager.getOrCreateCounter("counter_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotEquals(counter1, counter2);
-  }
-
-  @Test
-  public void removeGauge() {
-    Gauge gauge1 =
-        metricManager.getOrCreateGauge("gauge_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.removeGauge("gauge_remove", "tag1", "tag2");
-    Gauge gauge2 =
-        metricManager.getOrCreateGauge("gauge_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotEquals(gauge1, gauge2);
-  }
-
-  @Test
-  public void removeRate() {
-    Rate rate1 =
-        metricManager.getOrCreateRate("rate_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.removeRate("rate_remove", "tag1", "tag2");
-    Rate rate2 =
-        metricManager.getOrCreateRate("rate_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotEquals(rate1, rate2);
-  }
-
-  @Test
-  public void removeHistogram() {
-    Histogram histogram1 =
-        metricManager.getOrCreateHistogram(
-            "histogram_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.removeHistogram("histogram_remove", "tag1", "tag2");
-    Histogram histogram2 =
-        metricManager.getOrCreateHistogram(
-            "histogram_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotEquals(histogram1, histogram2);
-  }
-
-  @Test
-  public void removeTimer() {
-    Timer timer1 =
-        metricManager.getOrCreateTimer("timer_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.removeTimer("timer_remove", "tag1", "tag2");
-    Timer timer2 =
-        metricManager.getOrCreateTimer("timer_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotEquals(timer1, timer2);
-  }
-
-  @Test
-  public void getAllMetricKeys() {
-    metricManager.getOrCreateCounter("metric_test", MetricLevel.IMPORTANT, "tag1", "tag2");
-    List<String[]> result = metricManager.getAllMetricKeys();
-    assertNotNull(result);
-    boolean isContains = false;
-    for (String[] res : result) {
-      if (String.join(",", res).equals("metric_test,tag1,tag2")) {
-        isContains = true;
-        break;
-      }
-    }
-    assertTrue(isContains);
-  }
-
-  @Test
-  public void getAllCounters() {
-    metricManager.getOrCreateCounter("counters", MetricLevel.IMPORTANT);
-    Map<String[], Counter> counters = metricManager.getAllCounters();
-    assertNotNull(counters);
-    assertTrue(counters.size() > 0);
-  }
-
-  @Test
-  public void getAllGauges() {
-    metricManager.getOrCreateGauge("gauges", MetricLevel.IMPORTANT);
-    Map<String[], Gauge> gauges = metricManager.getAllGauges();
-    assertNotNull(gauges);
-    assertTrue(gauges.size() > 0);
-  }
-
-  @Test
-  public void getAllRates() {
-    metricManager.getOrCreateRate("rates", MetricLevel.IMPORTANT);
-    Map<String[], Rate> rates = metricManager.getAllRates();
-    assertNotNull(rates);
-    assertTrue(rates.size() > 0);
-  }
-
-  @Test
-  public void getAllHistograms() {
-    metricManager.getOrCreateHistogram("histograms", MetricLevel.IMPORTANT);
-    Map<String[], Histogram> histograms = metricManager.getAllHistograms();
-    assertNotNull(histograms);
-    assertTrue(histograms.size() > 0);
-  }
-
-  @Test
-  public void getAllTimers() {
-    metricManager.getOrCreateTimer("timers", MetricLevel.IMPORTANT);
-    Map<String[], Timer> timers = metricManager.getAllTimers();
-    assertNotNull(timers);
-    assertTrue(timers.size() > 0);
-  }
-
-  @Test
-  public void isEnable() {
-    assertTrue(metricManager.isEnable());
-    assertTrue(metricManager.isEnable(MetricLevel.IMPORTANT));
-  }
-
-  @AfterClass
-  public static void stop() {
-    metricManager.stop();
-  }
-}
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
new file mode 100644
index 0000000000..f1773c4106
--- /dev/null
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricManager.java
@@ -0,0 +1,490 @@
+/*
+ * 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;
+
+import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
+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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.function.ToLongFunction;
+
+public abstract class AbstractMetricManager {
+  protected static final MetricConfig METRIC_CONFIG =
+      MetricConfigDescriptor.getInstance().getMetricConfig();
+  /** Is metric service enabled */
+  protected static boolean isEnableMetric;
+  /** metric name -> tag keys */
+  protected Map<String, MetricInfo.MetaInfo> nameToTagInfo;
+  /** metric type -> metric name -> metric info */
+  protected Map<MetricInfo, IMetric> metrics;
+
+  public AbstractMetricManager() {
+    isEnableMetric = METRIC_CONFIG.getEnableMetric();
+    nameToTagInfo = new ConcurrentHashMap<>();
+    metrics = new ConcurrentHashMap<>();
+  }
+
+  // region get or create metric
+  /**
+   * Get counter. return if exists, create if not.
+   *
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public Counter getOrCreateCounter(String name, MetricLevel metricLevel, String... tags) {
+    if (!isValid(metricLevel, name, tags)) {
+      return DoNothingMetricManager.doNothingCounter;
+    }
+    MetricInfo metricInfo = new MetricInfo(MetricType.COUNTER, name, tags);
+    IMetric metric =
+        metrics.computeIfAbsent(
+            metricInfo,
+            key -> {
+              Counter counter = createCounter(metricInfo);
+              nameToTagInfo.put(name, metricInfo.getMetaInfo());
+              return counter;
+            });
+    if (metric instanceof Counter) {
+      return (Counter) metric;
+    }
+    throw new IllegalArgumentException(
+        metricInfo + " is already used for a different type of name");
+  }
+
+  protected abstract Counter createCounter(MetricInfo metricInfo);
+
+  /**
+   * Get autoGauge. return if exists, create if not.
+   *
+   * <p>AutoGauge keep a weak reference of the obj, so it will not prevent gc of the obj. Notice: if
+   * you call this gauge's value() when the obj has already been cleared by gc, then you will get
+   * 0L.
+   *
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param obj which will be monitored automatically
+   * @param mapper use which to map the obj to a long value
+   */
+  public <T> Gauge getOrCreateAutoGauge(
+      String name, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags) {
+    if (!isValid(metricLevel, name, tags)) {
+      return DoNothingMetricManager.doNothingGauge;
+    }
+    MetricInfo metricInfo = new MetricInfo(MetricType.GAUGE, name, tags);
+    IMetric metric =
+        metrics.computeIfAbsent(
+            metricInfo,
+            key -> {
+              Gauge gauge = createAutoGauge(metricInfo, obj, mapper);
+              nameToTagInfo.put(name, metricInfo.getMetaInfo());
+              return gauge;
+            });
+    if (metric instanceof Gauge) {
+      return (Gauge) metric;
+    }
+    throw new IllegalArgumentException(
+        metricInfo + " is already used for a different type of name");
+  }
+
+  protected abstract <T> Gauge createAutoGauge(
+      MetricInfo metricInfo, T obj, ToLongFunction<T> mapper);
+
+  /**
+   * Get counter. return if exists, create if not.
+   *
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public Gauge getOrCreateGauge(String name, MetricLevel metricLevel, String... tags) {
+    if (!isValid(metricLevel, name, tags)) {
+      return DoNothingMetricManager.doNothingGauge;
+    }
+    MetricInfo metricInfo = new MetricInfo(MetricType.GAUGE, name, tags);
+    IMetric metric =
+        metrics.computeIfAbsent(
+            metricInfo,
+            key -> {
+              Gauge gauge = createGauge(metricInfo);
+              nameToTagInfo.put(name, metricInfo.getMetaInfo());
+              return gauge;
+            });
+    if (metric instanceof Gauge) {
+      return (Gauge) metric;
+    }
+    throw new IllegalArgumentException(
+        metricInfo + " is already used for a different type of name");
+  }
+
+  protected abstract Gauge createGauge(MetricInfo metricInfo);
+
+  /**
+   * Get rate. return if exists, create if not.
+   *
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public Rate getOrCreateRate(String name, MetricLevel metricLevel, String... tags) {
+    if (!isValid(metricLevel, name, tags)) {
+      return DoNothingMetricManager.doNothingRate;
+    }
+    MetricInfo metricInfo = new MetricInfo(MetricType.RATE, name, tags);
+    IMetric metric =
+        metrics.computeIfAbsent(
+            metricInfo,
+            key -> {
+              Rate rate = createRate(metricInfo);
+              nameToTagInfo.put(name, metricInfo.getMetaInfo());
+              return rate;
+            });
+    if (metric instanceof Rate) {
+      return (Rate) metric;
+    }
+    throw new IllegalArgumentException(
+        metricInfo + " is already used for a different type of name");
+  }
+
+  protected abstract Rate createRate(MetricInfo metricInfo);
+
+  /**
+   * Get histogram. return if exists, create if not.
+   *
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public Histogram getOrCreateHistogram(String name, MetricLevel metricLevel, String... tags) {
+    if (!isValid(metricLevel, name, tags)) {
+      return DoNothingMetricManager.doNothingHistogram;
+    }
+    MetricInfo metricInfo = new MetricInfo(MetricType.HISTOGRAM, name, tags);
+    IMetric metric =
+        metrics.computeIfAbsent(
+            metricInfo,
+            key -> {
+              Histogram histogram = createHistogram(metricInfo);
+              nameToTagInfo.put(name, metricInfo.getMetaInfo());
+              return histogram;
+            });
+    if (metric instanceof Histogram) {
+      return (Histogram) metric;
+    }
+    throw new IllegalArgumentException(
+        metricInfo + " is already used for a different type of name");
+  }
+
+  protected abstract Histogram createHistogram(MetricInfo metricInfo);
+
+  /**
+   * Get timer. return if exists, create if not.
+   *
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public Timer getOrCreateTimer(String name, MetricLevel metricLevel, String... tags) {
+    if (!isValid(metricLevel, name, tags)) {
+      return DoNothingMetricManager.doNothingTimer;
+    }
+    MetricInfo metricInfo = new MetricInfo(MetricType.TIMER, name, tags);
+    IMetric metric =
+        metrics.computeIfAbsent(
+            metricInfo,
+            key -> {
+              Timer timer = createTimer(metricInfo);
+              nameToTagInfo.put(name, metricInfo.getMetaInfo());
+              return timer;
+            });
+    if (metric instanceof Timer) {
+      return (Timer) metric;
+    }
+    throw new IllegalArgumentException(
+        metricInfo + " is already used for a different type of name");
+  }
+
+  protected abstract Timer createTimer(MetricInfo metricInfo);
+
+  // endregion
+
+  // region update metric
+
+  /**
+   * Update counter. if exists, then update counter by delta. if not, then create and update.
+   *
+   * @param delta the value to update
+   * @param name the name of name
+   * @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) {
+    Counter counter = getOrCreateCounter(name, metricLevel, tags);
+    counter.inc(delta);
+  }
+
+  /**
+   * Set value of gauge. if exists, then set gauge by value. if not, then create and set.
+   *
+   * @param value the value of gauge
+   * @param name the name of name
+   * @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) {
+    Gauge gauge = getOrCreateGauge(name, metricLevel, tags);
+    gauge.set(value);
+  }
+
+  /**
+   * Mark rate. if exists, then mark rate by value. if not, then create and mark.
+   *
+   * @param value the value to mark
+   * @param name the name of name
+   * @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) {
+    Rate rate = getOrCreateRate(name, metricLevel, tags);
+    rate.mark(value);
+  }
+
+  /**
+   * Update histogram. if exists, then update histogram by value. if not, then create and update
+   *
+   * @param value the value to update
+   * @param name the name of name
+   * @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) {
+    Histogram histogram = getOrCreateHistogram(name, metricLevel, tags);
+    histogram.update(value);
+  }
+
+  /**
+   * Update timer. if exists, then update timer by delta and timeUnit. if not, then create and
+   * update
+   *
+   * @param delta the value to update
+   * @param timeUnit the unit of delta
+   * @param name the name of name
+   * @param metricLevel the level of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public void timer(
+      long delta, TimeUnit timeUnit, String name, MetricLevel metricLevel, String... tags) {
+    Timer timer = getOrCreateTimer(name, metricLevel, tags);
+    timer.update(delta, timeUnit);
+  }
+
+  // endregion
+
+  // region get metric
+
+  /**
+   * Get all metric keys.
+   *
+   * @return [[name, tags...], ..., [name, tags...]]
+   */
+  protected List<String[]> getAllMetricKeys() {
+    List<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<>();
+    for (Map.Entry<MetricInfo, IMetric> entry : metrics.entrySet()) {
+      if (entry.getValue() instanceof Timer) {
+        timerMap.put(entry.getKey().toStringArray(), (Timer) entry.getValue());
+      }
+    }
+    return timerMap;
+  }
+
+  // endregion
+
+  // region remove metric
+
+  /**
+   * remove name
+   *
+   * @param type the type of name
+   * @param name the name of name
+   * @param tags string pairs, like sg="ln" will be "sg", "ln"
+   */
+  public void remove(MetricType type, String name, String... tags) {
+    if (isEnableMetric()) {
+      MetricInfo metricInfo = new MetricInfo(type, name, tags);
+      if (nameToTagInfo.containsKey(metricInfo.getName())) {
+        MetricInfo.MetaInfo metaInfo = nameToTagInfo.get(metricInfo.getName());
+        if (metaInfo.hasSameKey(tags)) {
+          if (type == metaInfo.getType()) {
+            remove(metricInfo);
+            remove(type, metricInfo);
+          } else {
+            throw new IllegalArgumentException(
+                metricInfo + " failed to remove because the mismatch of type. ");
+          }
+        }
+      }
+    }
+  }
+
+  protected abstract void remove(MetricType type, MetricInfo metricInfo);
+
+  // endregion
+
+  /** Is metric service enabled */
+  public boolean isEnableMetric() {
+    return isEnableMetric;
+  }
+
+  /** Is metric service enabled in specific level */
+  public boolean isEnableMetricInGivenLevel(MetricLevel metricLevel) {
+    return isEnableMetric()
+        && MetricLevel.higherOrEqual(metricLevel, METRIC_CONFIG.getMetricLevel());
+  }
+
+  /** Stop and clear metric manager */
+  protected boolean stop() {
+    isEnableMetric = METRIC_CONFIG.getEnableMetric();
+    metrics = new ConcurrentHashMap<>();
+    nameToTagInfo = new ConcurrentHashMap<>();
+    return stopFramework();
+  }
+
+  protected abstract boolean stopFramework();
+
+  private boolean isValid(MetricLevel metricLevel, String name, String... tags) {
+    if (!isEnableMetricInGivenLevel(metricLevel)) {
+      return false;
+    }
+    if (!nameToTagInfo.containsKey(name)) {
+      return true;
+    }
+    MetricInfo.MetaInfo metaInfo = nameToTagInfo.get(name);
+    return metaInfo.hasSameKey(tags);
+  }
+
+  private void remove(MetricInfo metricInfo) {
+    nameToTagInfo.remove(metricInfo.getName());
+    metrics.remove(metricInfo);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    AbstractMetricManager that = (AbstractMetricManager) o;
+    return Objects.equals(metrics, that.metrics);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(metrics);
+  }
+}
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
new file mode 100644
index 0000000000..f00d7f1c4a
--- /dev/null
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
@@ -0,0 +1,262 @@
+/*
+ * 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;
+
+import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.config.ReloadLevel;
+import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
+import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.reporter.CompositeReporter;
+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.Rate;
+import org.apache.iotdb.metrics.type.Timer;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+import org.apache.iotdb.metrics.utils.ReporterType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.ToLongFunction;
+
+/** MetricService is the entry to get all metric features. */
+public abstract class AbstractMetricService {
+
+  private static final Logger logger = LoggerFactory.getLogger(AbstractMetricService.class);
+  /** The config of metric service */
+  private final MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
+  /** Is the first initialization of metric service */
+  private final AtomicBoolean isFirstInitialization = new AtomicBoolean(true);
+  /** The metric manager of metric service */
+  protected AbstractMetricManager metricManager = new DoNothingMetricManager();
+  /** The metric reporter of metric service */
+  protected CompositeReporter compositeReporter = new CompositeReporter();
+  /** Is metric service enabled */
+  protected boolean isEnableMetric = metricConfig.getEnableMetric();
+  /** The list of metric sets */
+  protected List<IMetricSet> metricSets = new ArrayList<>();
+
+  public AbstractMetricService() {}
+
+  /** start metric service */
+  public void startService() {
+    logger.info("Start metric service at level: {}", metricConfig.getMetricLevel().name());
+    // load metric manager
+    loadManager();
+    // load metric reporter
+    loadReporter();
+    // do start all reporter without first time
+    if (!isFirstInitialization.getAndSet(false)) {
+      startAllReporter();
+    }
+    for (PredefinedMetric predefinedMetric : metricConfig.getPredefinedMetrics()) {
+      enablePredefinedMetrics(predefinedMetric);
+    }
+    logger.info("Start predefined metrics: {}", metricConfig.getPredefinedMetrics());
+  }
+
+  /** stop metric service */
+  public void stopService() {
+    compositeReporter.stopAll();
+    metricManager.stop();
+    metricManager = new DoNothingMetricManager();
+    compositeReporter = new CompositeReporter();
+    for (IMetricSet metricSet : metricSets) {
+      metricSet.stopAsyncCollectedMetrics();
+    }
+    metricSets = new ArrayList<>();
+  }
+
+  /** Load metric manager according to configuration */
+  private void loadManager() {
+    logger.info("Load metricManager, type: {}", metricConfig.getMonitorType());
+    ServiceLoader<AbstractMetricManager> metricManagers =
+        ServiceLoader.load(AbstractMetricManager.class);
+    int size = 0;
+    for (AbstractMetricManager mf : metricManagers) {
+      size++;
+      if (mf.getClass()
+          .getName()
+          .toLowerCase()
+          .contains(metricConfig.getMonitorType().name().toLowerCase())) {
+        metricManager = mf;
+        break;
+      }
+    }
+
+    // if no more implementations, we use nothingManager.
+    if (size == 0 || metricManager == null) {
+      metricManager = new DoNothingMetricManager();
+    } else if (size > 1) {
+      logger.warn(
+          "Detect more than one MetricManager, will use {}", metricManager.getClass().getName());
+    }
+  }
+
+  /** Load metric reporters according to configuration */
+  protected void loadReporter() {
+    logger.info("Load metric reporters, type: {}", metricConfig.getMetricReporterList());
+    compositeReporter.clearReporter();
+    ServiceLoader<Reporter> reporters = ServiceLoader.load(Reporter.class);
+    for (Reporter reporter : reporters) {
+      if (metricConfig.getMetricReporterList() != null
+          && metricConfig.getMetricReporterList().contains(reporter.getReporterType())
+          && reporter
+              .getClass()
+              .getName()
+              .toLowerCase()
+              .contains(metricConfig.getMonitorType().name().toLowerCase())) {
+        reporter.setMetricManager(metricManager);
+        compositeReporter.addReporter(reporter);
+      }
+    }
+  }
+
+  /** Enable predefined Metrics */
+  protected abstract void enablePredefinedMetrics(PredefinedMetric metric);
+
+  /** Reload metric service according to reloadLevel */
+  protected abstract void reloadProperties(ReloadLevel reloadLevel);
+
+  // region interface from metric reporter
+
+  /** Start all reporters */
+  public void startAllReporter() {
+    if (!isEnable()) {
+      return;
+    }
+    compositeReporter.startAll();
+  }
+
+  /** Start reporter according to type */
+  public void start(ReporterType type) {
+    if (!isEnable()) {
+      return;
+    }
+    compositeReporter.start(type);
+  }
+
+  /** Stop reporter according to type */
+  public void stop(ReporterType type) {
+    if (!isEnable()) {
+      return;
+    }
+    compositeReporter.stop(type);
+  }
+
+  // endregion
+
+  // region interface from metric manager
+
+  public Counter getOrCreateCounter(String metric, MetricLevel metricLevel, String... tags) {
+    return metricManager.getOrCreateCounter(metric, metricLevel, tags);
+  }
+
+  public <T> Gauge getOrCreateAutoGauge(
+      String metric, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags) {
+    return metricManager.getOrCreateAutoGauge(metric, metricLevel, obj, mapper, tags);
+  }
+
+  public Gauge getOrCreateGauge(String metric, MetricLevel metricLevel, String... tags) {
+    return metricManager.getOrCreateGauge(metric, metricLevel, tags);
+  }
+
+  public Rate getOrCreateRate(String metric, MetricLevel metricLevel, String... tags) {
+    return metricManager.getOrCreateRate(metric, metricLevel, tags);
+  }
+
+  public Histogram getOrCreateHistogram(String metric, MetricLevel metricLevel, String... tags) {
+    return metricManager.getOrCreateHistogram(metric, metricLevel, tags);
+  }
+
+  public Timer getOrCreateTimer(String metric, MetricLevel metricLevel, String... tags) {
+    return metricManager.getOrCreateTimer(metric, metricLevel, tags);
+  }
+
+  public void count(long delta, String metric, MetricLevel metricLevel, String... tags) {
+    metricManager.count(delta, metric, metricLevel, tags);
+  }
+
+  public void gauge(long value, String metric, MetricLevel metricLevel, String... tags) {
+    metricManager.gauge(value, metric, metricLevel, tags);
+  }
+
+  public void rate(long value, String metric, MetricLevel metricLevel, String... tags) {
+    metricManager.rate(value, metric, metricLevel, tags);
+  }
+
+  public void histogram(long value, String metric, MetricLevel metricLevel, String... tags) {
+    metricManager.histogram(value, metric, metricLevel, tags);
+  }
+
+  public void timer(
+      long delta, TimeUnit timeUnit, String metric, MetricLevel metricLevel, String... tags) {
+    metricManager.timer(delta, timeUnit, metric, metricLevel, tags);
+  }
+
+  public List<String[]> getAllMetricKeys() {
+    return metricManager.getAllMetricKeys();
+  }
+
+  public Map<String[], Counter> getAllCounters() {
+    return metricManager.getAllCounters();
+  }
+
+  public Map<String[], Gauge> getAllGauges() {
+    return metricManager.getAllGauges();
+  }
+
+  public Map<String[], Rate> getAllRates() {
+    return metricManager.getAllRates();
+  }
+
+  public Map<String[], Histogram> getAllHistograms() {
+    return metricManager.getAllHistograms();
+  }
+
+  public Map<String[], Timer> getAllTimers() {
+    return metricManager.getAllTimers();
+  }
+
+  public void remove(MetricType type, String metric, String... tags) {
+    metricManager.remove(type, metric, tags);
+  }
+
+  // endregion
+
+  public AbstractMetricManager getMetricManager() {
+    return metricManager;
+  }
+
+  public boolean isEnable() {
+    return isEnableMetric;
+  }
+}
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 32cec0b1b7..8f07e299fb 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
@@ -20,12 +20,14 @@
 package org.apache.iotdb.metrics;
 
 import org.apache.iotdb.metrics.config.ReloadLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 
-public class DoNothingMetricService extends MetricService {
+public class DoNothingMetricService extends AbstractMetricService {
 
   @Override
-  public void enablePredefinedMetric(PredefinedMetric metric) {}
+  public void enablePredefinedMetrics(PredefinedMetric metric) {
+    // do nothing
+  }
 
   @Override
   protected void reloadProperties(ReloadLevel reloadLevel) {
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricManager.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricManager.java
deleted file mode 100644
index 4a293abcc4..0000000000
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricManager.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * 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;
-
-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.Rate;
-import org.apache.iotdb.metrics.type.Timer;
-import org.apache.iotdb.metrics.utils.MetricLevel;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.function.ToLongFunction;
-
-public interface MetricManager {
-  /**
-   * Get Counter If exists, then return or create one to return
-   *
-   * @param tags string appear in pairs, like sg="ln" will be "sg", "ln"
-   */
-  Counter getOrCreateCounter(String metric, MetricLevel metricLevel, String... tags);
-
-  /**
-   * Get Gauge If exists, then return or create one to return
-   *
-   * <p>This type of gauge will keep a weak reference of the obj, so it will not prevent the obj's
-   * gc. NOTICE: When the obj has already been cleared by gc when you call the gauge's value(), then
-   * you will get 0L;
-   *
-   * @param obj which will be monitored automatically
-   * @param mapper use which to map the obj to a long value
-   */
-  <T> Gauge getOrCreateAutoGauge(
-      String metric, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags);
-
-  /**
-   * Get Gauge If exists, then return or create one to return
-   *
-   * @param tags string appear in pairs, like sg="ln" will be "sg", "ln"
-   */
-  Gauge getOrCreateGauge(String metric, MetricLevel metricLevel, String... tags);
-
-  /**
-   * Get Rate If exists, then return or create one to return
-   *
-   * @param tags string appear in pairs, like sg="ln" will be "sg", "ln"
-   */
-  Rate getOrCreateRate(String metric, MetricLevel metricLevel, String... tags);
-
-  /**
-   * Get Histogram If exists, then return or create one to return
-   *
-   * @param tags string appear in pairs, like sg="ln" will be "sg", "ln"
-   */
-  Histogram getOrCreateHistogram(String metric, MetricLevel metricLevel, String... tags);
-
-  /**
-   * Get Timer If exists, then return or create one to return
-   *
-   * @param tags string appear in pairs, like sg="ln" will be "sg", "ln"
-   */
-  Timer getOrCreateTimer(String metric, MetricLevel metricLevel, String... tags);
-
-  /** update Counter. Create if not exists */
-  void count(long delta, String metric, MetricLevel metricLevel, String... tags);
-
-  /** set init value of Gauge. Create if not exists */
-  void gauge(long value, String metric, MetricLevel metricLevel, String... tags);
-
-  /** update Rate. Create if not exists */
-  void rate(long value, String metric, MetricLevel metricLevel, String... tags);
-
-  /** update Histogram. Create if not exists */
-  void histogram(long value, String metric, MetricLevel metricLevel, String... tags);
-
-  /** update Timer. Create if not exists */
-  void timer(long delta, TimeUnit timeUnit, String metric, MetricLevel metricLevel, String... tags);
-
-  /** remove counter */
-  void removeCounter(String metric, String... tags);
-
-  /** remove gauge */
-  void removeGauge(String metric, String... tags);
-
-  /** remove rate */
-  void removeRate(String metric, String... tags);
-
-  /** remove histogram */
-  void removeHistogram(String metric, String... tags);
-
-  /** update timer */
-  void removeTimer(String metric, String... tags);
-
-  /**
-   * get all metric keys.
-   *
-   * @return all MetricKeys, key is metric name, value is tags, which is a string array.
-   */
-  List<String[]> getAllMetricKeys();
-
-  /**
-   * Get all counters
-   *
-   * @return [name, tags...] -> counter
-   */
-  Map<String[], Counter> getAllCounters();
-
-  /**
-   * Get all gauges
-   *
-   * @return [name, tags...] -> gauge
-   */
-  Map<String[], Gauge> getAllGauges();
-
-  /**
-   * Get all rates
-   *
-   * @return [name, tags...] -> rate
-   */
-  Map<String[], Rate> getAllRates();
-
-  /**
-   * Get all histogram
-   *
-   * @return [name, tags...] -> histogram
-   */
-  Map<String[], Histogram> getAllHistograms();
-
-  /**
-   * Get all timers
-   *
-   * @return [name, tags...] -> timer
-   */
-  Map<String[], Timer> getAllTimers();
-
-  /** whether is enabled monitor */
-  boolean isEnable();
-
-  /** whether is enabled monitor in specific level */
-  boolean isEnable(MetricLevel metricLevel);
-
-  /**
-   * init something.
-   *
-   * @return whether success
-   */
-  boolean init();
-
-  /** clear metrics */
-  boolean stop();
-}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricService.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricService.java
deleted file mode 100644
index f462219f5b..0000000000
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/MetricService.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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;
-
-import org.apache.iotdb.metrics.config.MetricConfig;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
-import org.apache.iotdb.metrics.config.ReloadLevel;
-import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
-import org.apache.iotdb.metrics.predefined.IMetricSet;
-import org.apache.iotdb.metrics.reporter.CompositeReporter;
-import org.apache.iotdb.metrics.reporter.Reporter;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
-import org.apache.iotdb.metrics.utils.ReporterType;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ServiceLoader;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * MetricService is the entry to manage all Metric system, include MetricManager and MetricReporter.
- */
-public abstract class MetricService {
-
-  private static final Logger logger = LoggerFactory.getLogger(MetricService.class);
-  private final MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
-
-  protected MetricManager metricManager = new DoNothingMetricManager();
-
-  protected List<IMetricSet> metricSets = new ArrayList<>();
-
-  protected CompositeReporter compositeReporter = new CompositeReporter();
-
-  protected boolean isEnableMetric = metricConfig.getEnableMetric();
-
-  private final AtomicBoolean firstInit = new AtomicBoolean(true);
-
-  public MetricService() {}
-
-  /** Start metric service without start reporter. if is disabled, do nothing */
-  public void startService() {
-    // load manager
-    loadManager();
-    // load reporter
-    loadReporter();
-    // do some init work
-    metricManager.init();
-    // do start all reporter without first time
-
-    if (!firstInit.getAndSet(false)) {
-      startAllReporter();
-    }
-
-    logger.info("Start predefined metric:" + metricConfig.getPredefinedMetrics());
-    for (PredefinedMetric predefinedMetric : metricConfig.getPredefinedMetrics()) {
-      enablePredefinedMetric(predefinedMetric);
-    }
-    logger.info("Start metric at level: " + metricConfig.getMetricLevel().name());
-  }
-
-  /** Stop metric service. if is disabled, do nothing */
-  public void stopService() {
-    metricManager.stop();
-    compositeReporter.stopAll();
-    metricManager = new DoNothingMetricManager();
-    compositeReporter = new CompositeReporter();
-    for (IMetricSet metricSet : metricSets) {
-      metricSet.stopAsyncCollectedMetrics();
-    }
-    metricSets = new ArrayList<>();
-  }
-
-  protected void loadManager() {
-    logger.info("Load metricManager, type: {}", metricConfig.getMonitorType());
-    ServiceLoader<MetricManager> metricManagers = ServiceLoader.load(MetricManager.class);
-    int size = 0;
-    for (MetricManager mf : metricManagers) {
-      size++;
-      if (mf.getClass()
-          .getName()
-          .toLowerCase()
-          .contains(metricConfig.getMonitorType().name().toLowerCase())) {
-        metricManager = mf;
-        break;
-      }
-    }
-
-    // if no more implementations, we use nothingManager.
-    if (size == 0 || metricManager == null) {
-      metricManager = new DoNothingMetricManager();
-    } else if (size > 1) {
-      logger.warn(
-          "detect more than one MetricManager, will use {}", metricManager.getClass().getName());
-    }
-  }
-
-  protected void loadReporter() {
-    logger.info("Load metric reporter, reporters: {}", metricConfig.getMetricReporterList());
-    compositeReporter.clearReporter();
-    ServiceLoader<Reporter> reporters = ServiceLoader.load(Reporter.class);
-    for (Reporter reporter : reporters) {
-      if (metricConfig.getMetricReporterList() != null
-          && metricConfig.getMetricReporterList().contains(reporter.getReporterType())
-          && reporter
-              .getClass()
-              .getName()
-              .toLowerCase()
-              .contains(metricConfig.getMonitorType().name().toLowerCase())) {
-        reporter.setMetricManager(metricManager);
-        compositeReporter.addReporter(reporter);
-      }
-    }
-  }
-
-  public void startAllReporter() {
-    // start reporter
-    compositeReporter.startAll();
-  }
-
-  /** start reporter by name, values in jmx, prometheus, internal. if is disabled, do nothing */
-  public void start(ReporterType reporter) {
-    if (!isEnable()) {
-      return;
-    }
-    compositeReporter.start(reporter);
-  }
-
-  /** stop reporter by name, values in jmx, prometheus, internal. if is disabled, do nothing */
-  public void stop(ReporterType reporter) {
-    if (!isEnable()) {
-      return;
-    }
-    compositeReporter.stop(reporter);
-  }
-
-  /**
-   * Enable some predefined metric, now support jvm, logback. Notice: In dropwizard mode, logback
-   * metrics are not supported
-   */
-  public abstract void enablePredefinedMetric(PredefinedMetric metric);
-
-  /**
-   * support hot load of some properties
-   *
-   * @param reloadLevel
-   */
-  protected abstract void reloadProperties(ReloadLevel reloadLevel);
-
-  public MetricManager getMetricManager() {
-    return metricManager;
-  }
-
-  public boolean isEnable() {
-    return isEnableMetric;
-  }
-}
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 66f813c526..687e5ba627 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
@@ -19,9 +19,9 @@
 
 package org.apache.iotdb.metrics.config;
 
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.metrics.utils.MonitorType;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.ReporterType;
 
 import java.util.Arrays;
@@ -29,29 +29,32 @@ import java.util.List;
 import java.util.Objects;
 
 public class MetricConfig {
-  /** enable publishing data. */
+  /** Is metric service enabled */
   private Boolean enableMetric = false;
 
-  /** Is stat performance of sub-module enable */
+  /** Is stat performance of operations enabled */
   private Boolean enablePerformanceStat = false;
 
-  /** The of monitor frame */
-  private MonitorType monitorType = MonitorType.MICROMETER;
+  /** The type of the implementation of metric service */
+  private MonitorType monitorType = MonitorType.DROPWIZARD;
 
-  /** provide or push metric data to remote system, could be jmx, prometheus, iotdb, etc. */
+  /** The list of reporters provide data for external system */
   private List<ReporterType> metricReporterList =
       Arrays.asList(ReporterType.JMX, ReporterType.PROMETHEUS);
 
+  /** The level of metric service */
   private MetricLevel metricLevel = MetricLevel.IMPORTANT;
 
+  /** The list of predefined metrics in metric service */
   private List<PredefinedMetric> predefinedMetrics =
       Arrays.asList(PredefinedMetric.JVM, PredefinedMetric.FILE);
 
   private Integer asyncCollectPeriodInSecond = 5;
 
-  /** the http server's port for prometheus exporter to get metric data. */
-  private String prometheusExporterPort = "9091";
+  /** The http server's port for prometheus reporter to get metric data. */
+  private Integer prometheusExporterPort = 9091;
 
+  /** The config for iotdb reporter to push metric data */
   private IoTDBReporterConfig ioTDBReporterConfig = new IoTDBReporterConfig();
 
   public static class IoTDBReporterConfig {
@@ -226,11 +229,11 @@ public class MetricConfig {
     this.asyncCollectPeriodInSecond = asyncCollectPeriodInSecond;
   }
 
-  public String getPrometheusExporterPort() {
+  public Integer getPrometheusExporterPort() {
     return prometheusExporterPort;
   }
 
-  public void setPrometheusExporterPort(String prometheusExporterPort) {
+  public void setPrometheusExporterPort(Integer prometheusExporterPort) {
     this.prometheusExporterPort = prometheusExporterPort;
   }
 
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 520f8c3c5f..e531d8ebfb 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
@@ -32,84 +32,48 @@ import java.io.InputStream;
 /** The utils class to load configure. Read from yaml file. */
 public class MetricConfigDescriptor {
   private static final Logger logger = LoggerFactory.getLogger(MetricConfigDescriptor.class);
-  private MetricConfig metricConfig;
-
-  public MetricConfig getMetricConfig() {
-    return metricConfig;
-  }
+  /** the metric config of metric service */
+  private final MetricConfig metricConfig;
 
   private MetricConfigDescriptor() {
-    loadProps();
-  }
-
-  public static MetricConfigDescriptor getInstance() {
-    return MetricConfigDescriptorHolder.INSTANCE;
+    metricConfig = loadProps();
   }
 
   /**
-   * find the config file path.
+   * load property file into metric config. Use default values if not find.
    *
-   * @return the file path
+   * @return metric config
    */
-  private String getPropsUrl() {
-    String url = System.getProperty(MetricConstant.IOTDB_CONF, null);
-    // try to get config node conf
-    if (url == null) {
-      url = System.getProperty(MetricConstant.CONFIGNODE_CONF, null);
-    }
-    if (url == null) {
-      logger.warn(
-          "Cannot find IOTDB_CONF environment variable when loading "
-              + "config file {}, use default configuration",
-          MetricConstant.CONFIG_NAME);
-      return null;
-    } else {
-      url += (File.separatorChar + MetricConstant.CONFIG_NAME);
-    }
-
-    return url;
-  }
-
-  /** Load a property file and set MetricConfig variables. If not found file, use default value. */
-  public void loadProps() {
+  public MetricConfig loadProps() {
+    MetricConfig metricConfig;
     String url = getPropsUrl();
     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)) {
         logger.info("Start to read config file {}", url);
         metricConfig = (MetricConfig) yaml.load(inputStream);
-        return;
       } catch (IOException e) {
         logger.warn(
             "Fail to find config file : {} because of {}, use default config.",
             url,
             e.getMessage());
+        metricConfig = new MetricConfig();
       }
     } else {
-      logger.warn("Fail to find config file, use default");
+      logger.warn("Fail to find config file, use default config.");
+      metricConfig = new MetricConfig();
     }
-    metricConfig = new MetricConfig();
+    return metricConfig;
   }
 
-  public ReloadLevel loadHotProperties() {
-    String url = getPropsUrl();
-    Constructor constructor = new Constructor(MetricConfig.class);
-    Yaml yaml = new Yaml(constructor);
-    MetricConfig newMetricConfig = null;
-    if (url != null) {
-      try (InputStream inputStream = new FileInputStream(new File(url))) {
-        logger.info("Start to read config file {}", url);
-        newMetricConfig = (MetricConfig) yaml.load(inputStream);
-      } catch (IOException e) {
-        logger.warn(
-            "Fail to find config file : {} because of {}, use default config.",
-            url,
-            e.getMessage());
-      }
-    } else {
-      logger.warn("Fail to find config file, use default");
-    }
+  /**
+   * load property file into metric config, use default values if not find.
+   *
+   * @return reload level of metric service
+   */
+  public ReloadLevel loadHotProps() {
+    MetricConfig newMetricConfig = loadProps();
     ReloadLevel reloadLevel = ReloadLevel.NOTHING;
     if (newMetricConfig != null && !metricConfig.equals(newMetricConfig)) {
       if (!metricConfig.getEnableMetric().equals(newMetricConfig.getEnableMetric())) {
@@ -136,7 +100,37 @@ public class MetricConfigDescriptor {
     return reloadLevel;
   }
 
+  /** get the path of metric config file. */
+  private String getPropsUrl() {
+    // first, try to get conf folder of standalone iotdb or datanode
+    String url = System.getProperty(MetricConstant.IOTDB_CONF, null);
+    // second, try to get conf folder of datanode
+    if (url == null) {
+      url = System.getProperty(MetricConstant.CONFIGNODE_CONF, null);
+    }
+    // finally, return null when not find
+    if (url == null) {
+      logger.warn(
+          "Cannot find IOTDB_CONF and CONFIGNODE_CONF environment variable when loading "
+              + "config file {}, use default configuration",
+          MetricConstant.CONFIG_NAME);
+      return null;
+    } else {
+      url += (File.separatorChar + MetricConstant.CONFIG_NAME);
+    }
+
+    return url;
+  }
+
   private static class MetricConfigDescriptorHolder {
     private static final MetricConfigDescriptor INSTANCE = new MetricConfigDescriptor();
   }
+
+  public static MetricConfigDescriptor getInstance() {
+    return MetricConfigDescriptorHolder.INSTANCE;
+  }
+
+  public MetricConfig getMetricConfig() {
+    return metricConfig;
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/ReloadLevel.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/ReloadLevel.java
index 449266ee9c..974e6663b9 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/ReloadLevel.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/config/ReloadLevel.java
@@ -20,9 +20,14 @@
 package org.apache.iotdb.metrics.config;
 
 public enum ReloadLevel {
+  // start metric service
   START_METRIC,
+  // stop metric service
   STOP_METRIC,
+  // restart metric service
   RESTART_METRIC,
+  // restart metric service reporter
   RESTART_REPORTER,
+  // do nothing
   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 a90400e3e3..10e917d093 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
@@ -28,10 +28,14 @@ public class DoNothingGauge implements Gauge {
   }
 
   @Override
-  public void incr(long value) {}
+  public void incr(long value) {
+    // do nothing
+  }
 
   @Override
-  public void decr(long value) {}
+  public void decr(long value) {
+    // do nothing
+  }
 
   @Override
   public void set(long value) {
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetricManager.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetricManager.java
index 3a1d65bbbe..dbad7741fb 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetricManager.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/impl/DoNothingMetricManager.java
@@ -19,21 +19,19 @@
 
 package org.apache.iotdb.metrics.impl;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 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.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 java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
 import java.util.function.ToLongFunction;
 
-public class DoNothingMetricManager implements MetricManager {
+public class DoNothingMetricManager extends AbstractMetricManager {
 
   public static final DoNothingCounter doNothingCounter = new DoNothingCounter();
   public static final DoNothingHistogram doNothingHistogram = new DoNothingHistogram();
@@ -42,129 +40,52 @@ public class DoNothingMetricManager implements MetricManager {
   public static final DoNothingTimer doNothingTimer = new DoNothingTimer();
 
   @Override
-  public Counter getOrCreateCounter(String metric, MetricLevel metricLevel, String... tags) {
+  public Counter createCounter(MetricInfo metricInfo) {
     return doNothingCounter;
   }
 
   @Override
-  public <T> Gauge getOrCreateAutoGauge(
-      String metric, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags) {
+  public <T> Gauge createAutoGauge(MetricInfo metricInfo, T obj, ToLongFunction<T> mapper) {
     return doNothingGauge;
   }
 
   @Override
-  public Gauge getOrCreateGauge(String metric, MetricLevel metricLevel, String... tags) {
+  public Gauge createGauge(MetricInfo metricInfo) {
     return doNothingGauge;
   }
 
   @Override
-  public Histogram getOrCreateHistogram(String metric, MetricLevel metricLevel, String... tags) {
+  public Histogram createHistogram(MetricInfo metricInfo) {
     return doNothingHistogram;
   }
 
   @Override
-  public Rate getOrCreateRate(String metric, MetricLevel metricLevel, String... tags) {
+  public Rate createRate(MetricInfo metricInfo) {
     return doNothingRate;
   }
 
   @Override
-  public Timer getOrCreateTimer(String metric, MetricLevel metricLevel, String... tags) {
+  public Timer createTimer(MetricInfo metricInfo) {
     return doNothingTimer;
   }
 
   @Override
-  public void count(long delta, String metric, MetricLevel metricLevel, String... tags) {
-    // do nothing
-  }
-
-  @Override
-  public void histogram(long value, String metric, MetricLevel metricLevel, String... tags) {
-    // do nothing
-  }
-
-  @Override
-  public void gauge(long value, String metric, MetricLevel metricLevel, String... tags) {
-    // do nothing
-  }
-
-  @Override
-  public void rate(long value, String metric, MetricLevel metricLevel, String... tags) {
-    // do nothing
-  }
-
-  @Override
-  public void timer(
-      long delta, TimeUnit timeUnit, String metric, MetricLevel metricLevel, String... tags) {
-    // do nothing
-  }
-
-  @Override
-  public List<String[]> getAllMetricKeys() {
-    return Collections.emptyList();
-  }
-
-  @Override
-  public Map<String[], Counter> getAllCounters() {
-    return Collections.emptyMap();
-  }
-
-  @Override
-  public Map<String[], Gauge> getAllGauges() {
-    return Collections.emptyMap();
-  }
-
-  @Override
-  public Map<String[], Rate> getAllRates() {
-    return Collections.emptyMap();
-  }
-
-  @Override
-  public Map<String[], Histogram> getAllHistograms() {
-    return Collections.emptyMap();
-  }
-
-  @Override
-  public Map<String[], Timer> getAllTimers() {
-    return Collections.emptyMap();
-  }
-
-  @Override
-  public boolean isEnable() {
+  public boolean isEnableMetric() {
     return false;
   }
 
   @Override
-  public boolean isEnable(MetricLevel metricLevel) {
+  public boolean isEnableMetricInGivenLevel(MetricLevel metricLevel) {
     return false;
   }
 
   @Override
-  public boolean init() {
-    return false;
+  protected void remove(MetricType type, MetricInfo metricInfo) {
+    // do nothing
   }
 
   @Override
-  public void removeCounter(String metric, String... tags) {}
-
-  @Override
-  public void removeGauge(String metric, String... tags) {}
-
-  @Override
-  public void removeRate(String metric, String... tags) {}
-
-  @Override
-  public void removeHistogram(String metric, String... tags) {}
-
-  @Override
-  public void removeTimer(String metric, String... tags) {}
-
-  /**
-   * stop everything and clear
-   *
-   * @return
-   */
-  @Override
-  public boolean stop() {
-    return false;
+  protected boolean stopFramework() {
+    return true;
   }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/IMetricSet.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/IMetricSet.java
index b333cef0ab..b566d2dd53 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/IMetricSet.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/IMetricSet.java
@@ -19,12 +19,11 @@
 
 package org.apache.iotdb.metrics.predefined;
 
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 
 public interface IMetricSet {
   /** bind related metric to metric manager */
-  void bindTo(MetricManager metricManager);
+  void bindTo(AbstractMetricManager metricManager);
 
   /** get type of metric set */
   PredefinedMetric getType();
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/PredefinedMetric.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/PredefinedMetric.java
similarity index 95%
copy from metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/PredefinedMetric.java
copy to metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/PredefinedMetric.java
index e9484eb7aa..c6580f69e8 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/PredefinedMetric.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/PredefinedMetric.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.utils;
+package org.apache.iotdb.metrics.predefined;
 
 public enum PredefinedMetric {
   JVM,
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmClassLoaderMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmClassLoaderMetrics.java
index 007f4ba5b7..8579717f85 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmClassLoaderMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmClassLoaderMetrics.java
@@ -19,10 +19,10 @@
 
 package org.apache.iotdb.metrics.predefined.jvm;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import java.lang.management.ClassLoadingMXBean;
 import java.lang.management.ManagementFactory;
@@ -30,7 +30,7 @@ import java.lang.management.ManagementFactory;
 /** This file is modified from io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics */
 public class JvmClassLoaderMetrics implements IMetricSet {
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     ClassLoadingMXBean classLoadingBean = ManagementFactory.getClassLoadingMXBean();
 
     metricManager.getOrCreateAutoGauge(
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmCompileMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmCompileMetrics.java
index 5f59492964..86adf2dbad 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmCompileMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmCompileMetrics.java
@@ -19,10 +19,10 @@
 
 package org.apache.iotdb.metrics.predefined.jvm;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import java.lang.management.CompilationMXBean;
 import java.lang.management.ManagementFactory;
@@ -30,7 +30,7 @@ import java.lang.management.ManagementFactory;
 /** This file is modified from io.micrometer.core.instrument.binder.jvm.JvmCompilationMetrics */
 public class JvmCompileMetrics implements IMetricSet {
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     CompilationMXBean compilationBean = ManagementFactory.getCompilationMXBean();
     if (compilationBean != null && compilationBean.isCompilationTimeMonitoringSupported()) {
       metricManager.getOrCreateAutoGauge(
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmGcMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmGcMetrics.java
index 43f1adf0bd..27cd6a670b 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmGcMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmGcMetrics.java
@@ -19,13 +19,12 @@
 
 package org.apache.iotdb.metrics.predefined.jvm;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.type.Counter;
 import org.apache.iotdb.metrics.type.Timer;
-import org.apache.iotdb.metrics.utils.JvmUtils;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import com.sun.management.GarbageCollectionNotificationInfo;
 import com.sun.management.GcInfo;
@@ -72,7 +71,7 @@ public class JvmGcMetrics implements IMetricSet, AutoCloseable {
   }
 
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     if (ManagementFactory.getMemoryPoolMXBeans().isEmpty()) {
       logger.warn(
           "GC notifications will not be available because MemoryPoolMXBeans are not provided by the JVM");
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMemoryMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMemoryMetrics.java
index c8e337bd6c..1e28133961 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMemoryMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMemoryMetrics.java
@@ -19,11 +19,10 @@
 
 package org.apache.iotdb.metrics.predefined.jvm;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
-import org.apache.iotdb.metrics.utils.JvmUtils;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import java.lang.management.BufferPoolMXBean;
 import java.lang.management.ManagementFactory;
@@ -34,7 +33,7 @@ import java.lang.management.MemoryUsage;
 /** This file is modified from io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics */
 public class JvmMemoryMetrics implements IMetricSet {
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     for (BufferPoolMXBean bufferPoolBean :
         ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class)) {
       metricManager.getOrCreateAutoGauge(
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMetrics.java
index 66e81153e6..3d2a744861 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMetrics.java
@@ -19,13 +19,13 @@
 
 package org.apache.iotdb.metrics.predefined.jvm;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 
 public class JvmMetrics implements IMetricSet {
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     JvmClassLoaderMetrics jvmClassLoaderMetricSet = new JvmClassLoaderMetrics();
     jvmClassLoaderMetricSet.bindTo(metricManager);
 
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmThreadMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmThreadMetrics.java
index b599892076..8a7428942f 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmThreadMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmThreadMetrics.java
@@ -19,10 +19,10 @@
 
 package org.apache.iotdb.metrics.predefined.jvm;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadMXBean;
@@ -31,7 +31,7 @@ import java.util.Arrays;
 /** This file is modified from io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics */
 public class JvmThreadMetrics implements IMetricSet {
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
 
     metricManager.getOrCreateAutoGauge(
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/JvmUtils.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmUtils.java
similarity index 95%
rename from metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/JvmUtils.java
rename to metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmUtils.java
index 29f6e00680..4b7f9d3062 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/JvmUtils.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmUtils.java
@@ -17,14 +17,14 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.utils;
+package org.apache.iotdb.metrics.predefined.jvm;
 
 import java.lang.management.MemoryPoolMXBean;
 import java.lang.management.MemoryUsage;
 import java.util.function.ToLongFunction;
 
 public class JvmUtils {
-  public static double getUsageValue(
+  static double getUsageValue(
       MemoryPoolMXBean memoryPoolMXBean, ToLongFunction<MemoryUsage> getter) {
     MemoryUsage usage = getUsage(memoryPoolMXBean);
     if (usage == null) {
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/logback/LogbackMetrics.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/logback/LogbackMetrics.java
index aabcb542bd..b2dde91411 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/logback/LogbackMetrics.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/logback/LogbackMetrics.java
@@ -19,11 +19,11 @@
 
 package org.apache.iotdb.metrics.predefined.logback;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.type.Counter;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
@@ -41,7 +41,8 @@ import java.util.Map;
 public class LogbackMetrics implements IMetricSet, AutoCloseable {
   static ThreadLocal<Boolean> ignoreMetrics = new ThreadLocal<>();
   private final LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
-  private final Map<MetricManager, MetricsTurboFilter> metricsTurboFilters = new HashMap<>();
+  private final Map<AbstractMetricManager, MetricsTurboFilter> metricsTurboFilters =
+      new HashMap<>();
 
   public LogbackMetrics() {
     loggerContext.addListener(
@@ -79,7 +80,7 @@ public class LogbackMetrics implements IMetricSet, AutoCloseable {
   }
 
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     MetricsTurboFilter filter = new MetricsTurboFilter(metricManager);
     synchronized (metricsTurboFilters) {
       metricsTurboFilters.put(metricManager, filter);
@@ -118,7 +119,7 @@ class MetricsTurboFilter extends TurboFilter {
   private Counter debugCounter;
   private Counter traceCounter;
 
-  MetricsTurboFilter(MetricManager metricManager) {
+  MetricsTurboFilter(AbstractMetricManager metricManager) {
     errorCounter =
         metricManager.getOrCreateCounter("logback.events", MetricLevel.IMPORTANT, "level", "error");
 
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/CompositeReporter.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/CompositeReporter.java
index 4be07f7136..32b3e828cf 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/CompositeReporter.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/CompositeReporter.java
@@ -31,30 +31,30 @@ public class CompositeReporter {
   private static final Logger LOGGER = LoggerFactory.getLogger(CompositeReporter.class);
   private final List<Reporter> reporters = new ArrayList<>();
 
-  /** Start all reporter */
+  /** start all reporters */
   public boolean startAll() {
     boolean result = true;
     for (Reporter reporter : reporters) {
       if (!reporter.start()) {
-        LOGGER.warn("Failed to init {} reporter.", reporter.getReporterType());
+        LOGGER.warn("Failed to start {} reporter.", reporter.getReporterType());
         result = false;
       }
     }
     return result;
   }
 
-  /** Start reporter by name values in jmx, prometheus, iotdb */
+  /** start reporter by reporterType */
   public boolean start(ReporterType reporterType) {
     for (Reporter reporter : reporters) {
       if (reporter.getReporterType() == reporterType) {
         return reporter.start();
       }
     }
-    LOGGER.error("Failed to find {} reporter.", reporterType);
+    LOGGER.error("Failed to start {} reporter because not find.", reporterType);
     return false;
   }
 
-  /** Stop all reporter */
+  /** stop all reporters */
   public boolean stopAll() {
     boolean result = true;
     for (Reporter reporter : reporters) {
@@ -66,30 +66,31 @@ public class CompositeReporter {
     return result;
   }
 
-  /** Stop reporter by name, values in jmx, prometheus, iotdb */
+  /** stop reporter by reporterType */
   public boolean stop(ReporterType reporterType) {
     for (Reporter reporter : reporters) {
       if (reporter.getReporterType() == reporterType) {
         return reporter.stop();
       }
     }
-    LOGGER.error("Failed to stop reporter: {}", reporterType.name());
-    return true;
-  }
-
-  /** Clear reporter */
-  public void clearReporter() {
-    reporters.clear();
+    LOGGER.error("Failed to stop {} reporter because not find.", reporterType.name());
+    return false;
   }
 
-  /** Add reporter */
+  /** add reporter */
   public void addReporter(Reporter reporter) {
     for (Reporter originReporter : reporters) {
       if (originReporter.getReporterType() == reporter.getReporterType()) {
-        LOGGER.warn("Already exist reporter, type is " + reporter.getReporterType());
+        LOGGER.warn(
+            "Failed to load {} reporter because already existed", reporter.getReporterType());
         return;
       }
     }
     reporters.add(reporter);
   }
+
+  /** clear reporters */
+  public void clearReporter() {
+    reporters.clear();
+  }
 }
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/Reporter.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/Reporter.java
index 761c762f0d..cabacd987d 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/Reporter.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/reporter/Reporter.java
@@ -19,19 +19,19 @@
 
 package org.apache.iotdb.metrics.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.utils.ReporterType;
 
 public interface Reporter {
-  /** Start reporter */
+  /** start reporter */
   boolean start();
 
-  /** Stop reporter */
+  /** stop reporter */
   boolean stop();
 
-  /** Get type of reporter */
+  /** get the type of reporter */
   ReporterType getReporterType();
 
-  /** Set metric manager */
-  void setMetricManager(MetricManager metricManager);
+  /** set metric manager to get metrics❤ */
+  void setMetricManager(AbstractMetricManager metricManager);
 }
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 5708adadb3..dc01ba6b20 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
@@ -20,12 +20,13 @@
 package org.apache.iotdb.metrics.type;
 
 public interface Counter extends IMetric {
-  /** Counter add 1 */
+
+  /** counter add 1 */
   void inc();
 
-  /** Counter add n */
+  /** counter add n */
   void inc(long n);
 
-  /** Get value of counter */
+  /** get the value of counter */
   long 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 c6c4cc3a9b..9c4c5b768b 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
@@ -20,15 +20,16 @@
 package org.apache.iotdb.metrics.type;
 
 public interface Gauge extends IMetric {
-  /** Set value to gauge */
+
+  /** set value */
   void set(long value);
 
-  /** Get value stored in gauge */
+  /** get value stored in gauge */
   long value();
 
-  /** Increase gauge value */
+  /** increase the value stored in gauge */
   void incr(long value);
 
-  /** Decrease gauge value */
+  /** decrease the value stored in gauge */
   void decr(long 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 351a4fac6c..ac782cde06 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
@@ -20,10 +20,11 @@
 package org.apache.iotdb.metrics.type;
 
 public interface Histogram extends IMetric {
+
   /** update histogram by value */
   void update(long value);
 
-  /** get value of histogram */
+  /** get the value of histogram */
   long count();
 
   /** take snapshot of histogram */
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 02e01b5ea8..0bfe7ff4f7 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
@@ -21,34 +21,30 @@ package org.apache.iotdb.metrics.type;
 
 import java.io.OutputStream;
 
-/** used by Timer and Histogram. */
+/** used by timer and histogram. */
 public interface HistogramSnapshot {
 
-  /** Get value by quantile */
+  /** get value by quantile */
   double getValue(double quantile);
 
-  /** Get values in snapshot */
+  /** get values in snapshot */
   long[] getValues();
 
-  /** Get size of value in snapshot */
+  /** get the size of values in snapshot */
   int size();
 
-  /** Get median of values */
-  double getMedian();
-
-  /** Get min of values */
+  /** get min value in values */
   long getMin();
 
-  /** Get mean of values */
+  /** get median value in values */
+  double getMedian();
+
+  /** get mean value in values */
   double getMean();
 
-  /** Get max of values */
+  /** get max value of values */
   long getMax();
 
-  /**
-   * Writes the values of the snapshot to the given stream.
-   *
-   * @param output an output stream
-   */
+  /** writes the values of the snapshot to the given stream */
   void dump(OutputStream output);
 }
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 e8262edfd2..1d5c2cd9a7 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
@@ -22,6 +22,7 @@ package org.apache.iotdb.metrics.type;
 import org.apache.iotdb.metrics.utils.OutPutFormat;
 
 public interface IMetric {
+
   /** format metric into string */
   default StringBuffer toString(OutPutFormat format) {
     return new StringBuffer();
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 e7db9febbf..a68e003da2 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
@@ -20,19 +20,20 @@
 package org.apache.iotdb.metrics.type;
 
 public interface Rate extends IMetric {
-  /** Get value of Rate */
+
+  /** get the value of rate */
   long getCount();
 
-  /** Get one minute rate */
+  /** get one minute rate */
   double getOneMinuteRate();
 
-  /** Get mean rate */
+  /** get mean rate */
   double getMeanRate();
 
-  /** Get five minute rate */
+  /** get five minute rate */
   double getFiveMinuteRate();
 
-  /** Get fifteen minute rate */
+  /** get fifteen minute rate */
   double getFifteenMinuteRate();
 
   /** mark in rate */
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 049b5d994f..986df3a8e1 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
@@ -44,10 +44,6 @@ public interface Timer extends IMetric {
   /** take snapshot of timer */
   HistogramSnapshot takeSnapshot();
 
-  /**
-   * It's not safe to use the update interface.
-   *
-   * @return the getOrCreatRate related with the getOrCreateTimer
-   */
+  /** It's not safe to use the update interface of this rate */
   Rate getImmutableRate();
 }
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
new file mode 100644
index 0000000000..3439b5c9ff
--- /dev/null
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricInfo.java
@@ -0,0 +1,191 @@
+/*
+ * 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.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+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;
+  private final String name;
+  private final MetaInfo metaInfo;
+  private final Map<String, String> tags = new LinkedHashMap<>();
+
+  public MetricInfo(MetricType type, String name, String... tags) {
+    this.name = name;
+    if (tags.length % PAIR_SIZE == 0) {
+      for (int i = 0; i < tags.length; i += PAIR_SIZE) {
+        this.tags.put(tags[i], tags[i + 1]);
+      }
+    } else {
+      logger.error("The size of metric tags should be even, but was {}.", String.join(",", tags));
+    }
+    this.metaInfo = new MetaInfo(type, this.tags.keySet());
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String[] getTagsInArray() {
+    String[] tags = new String[this.tags.size() * 2];
+    int index = 0;
+    for (Map.Entry<String, String> entry : this.tags.entrySet()) {
+      tags[index++] = entry.getKey();
+      tags[index++] = entry.getValue();
+    }
+    return tags;
+  }
+
+  public Map<String, String> getTags() {
+    return tags;
+  }
+
+  public MetaInfo getMetaInfo() {
+    return metaInfo;
+  }
+
+  /** convert the metric name to string array. */
+  public 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]);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    MetricInfo that = (MetricInfo) o;
+    if (!this.name.equals(that.name)) {
+      return false;
+    }
+    if (that.getTags().size() != this.tags.size()) {
+      return false;
+    }
+    Map<String, String> thatTags = that.getTags();
+    for (Map.Entry<String, String> entry : this.tags.entrySet()) {
+      if (!thatTags.containsKey(entry.getKey())) {
+        return false;
+      }
+      if (!thatTags.get(entry.getKey()).equals(entry.getValue())) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(name, tags);
+  }
+
+  @Override
+  public String toString() {
+    return "MetricInfo{"
+        + "name='"
+        + name
+        + '\''
+        + ", metaInfo="
+        + metaInfo
+        + ", tags="
+        + tags
+        + '}';
+  }
+
+  public static class MetaInfo {
+    private final MetricType type;
+    private final Set<String> tagNames;
+
+    public MetaInfo(MetricType type, Set<String> tagNames) {
+      this.type = type;
+      this.tagNames = tagNames;
+    }
+
+    /** check whether the key in tags is same */
+    public boolean hasSameKey(String... tags) {
+      if (tags.length != tagNames.size() * 2) {
+        return false;
+      }
+      for (int i = 0; i < tags.length; i += PAIR_SIZE) {
+        if (!tagNames.contains(tags[i])) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    public MetricType getType() {
+      return type;
+    }
+
+    public Set<String> getTagNames() {
+      return tagNames;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+      MetaInfo that = (MetaInfo) o;
+      if (tagNames == null || that.tagNames == null) {
+        return false;
+      }
+      for (String tagName : that.tagNames) {
+        if (!tagNames.contains(tagName)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return Objects.hash(tagNames);
+    }
+
+    @Override
+    public String toString() {
+      return "MetaInfo{" + "type=" + type + ", tagNames=" + tagNames + '}';
+    }
+  }
+}
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricLevel.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricLevel.java
index af87050b3b..691f2ec285 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricLevel.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricLevel.java
@@ -25,7 +25,7 @@ public enum MetricLevel {
   IMPORTANT(2),
   CORE(3);
 
-  /** Level of metric */
+  /** Level of metric service */
   int level;
 
   MetricLevel(int level) {
diff --git a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/PredefinedMetric.java b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java
similarity index 92%
rename from metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/PredefinedMetric.java
rename to metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java
index e9484eb7aa..14651c1674 100644
--- a/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/PredefinedMetric.java
+++ b/metrics/interface/src/main/java/org/apache/iotdb/metrics/utils/MetricType.java
@@ -19,12 +19,12 @@
 
 package org.apache.iotdb.metrics.utils;
 
-public enum PredefinedMetric {
-  JVM,
-  LOGBACK,
-  FILE,
-  PROCESS,
-  SYSTEM;
+public enum MetricType {
+  COUNTER,
+  GAUGE,
+  RATE,
+  HISTOGRAM,
+  TIMER;
 
   @Override
   public String toString() {
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 eb3abea386..065347f2ef 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
@@ -20,8 +20,7 @@
 package org.apache.iotdb.metrics.config;
 
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
-import org.apache.iotdb.metrics.utils.ReporterType;
+import org.apache.iotdb.metrics.utils.MonitorType;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -31,14 +30,15 @@ import org.yaml.snakeyaml.constructor.Constructor;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 public class MetricConfigTest {
 
   @Test
-  public void yamlConfigTest() {
+  public void testYamlConfig() {
     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);
@@ -51,11 +51,22 @@ public class MetricConfigTest {
       }
     }
 
-    List<ReporterType> lists = metricConfig.getMetricReporterList();
-    Assert.assertEquals(lists.size(), 2);
-    Assert.assertEquals(metricConfig.getPrometheusExporterPort(), "9091");
-    Assert.assertEquals(MetricLevel.IMPORTANT, metricConfig.getMetricLevel());
-    List<PredefinedMetric> predefinedMetrics = metricConfig.getPredefinedMetrics();
-    Assert.assertEquals(predefinedMetrics.size(), 1);
+    assertTrue(metricConfig.getEnableMetric());
+    assertTrue(metricConfig.getEnablePerformanceStat());
+    assertEquals(3, metricConfig.getMetricReporterList().size());
+    assertEquals(MonitorType.DROPWIZARD, metricConfig.getMonitorType());
+    assertEquals(MetricLevel.ALL, metricConfig.getMetricLevel());
+    assertEquals(5, metricConfig.getPredefinedMetrics().size());
+    assertEquals(10, (int) metricConfig.getAsyncCollectPeriodInSecond());
+    assertEquals(9090, (int) metricConfig.getPrometheusExporterPort());
+
+    MetricConfig.IoTDBReporterConfig reporterConfig = metricConfig.getIoTDBReporterConfig();
+    assertEquals("0.0.0.0", reporterConfig.getHost());
+    assertEquals(6669, (int) reporterConfig.getPort());
+    assertEquals("user", reporterConfig.getUsername());
+    assertEquals("password", reporterConfig.getPassword());
+    assertEquals(1, (int) reporterConfig.getMaxConnectionNumber());
+    assertEquals("metric", reporterConfig.getDatabase());
+    assertEquals(5, (int) reporterConfig.getPushPeriodInSecond());
   }
 }
diff --git a/metrics/interface/src/test/resources/iotdb-metric.yml b/metrics/interface/src/test/resources/iotdb-metric.yml
index 53e9bef194..e84ec80bdb 100644
--- a/metrics/interface/src/test/resources/iotdb-metric.yml
+++ b/metrics/interface/src/test/resources/iotdb-metric.yml
@@ -18,32 +18,43 @@
 #
 
 # whether enable the module
-enableMetric: false
+enableMetric: true
+
+# Is stat performance of operation latency
+enablePerformanceStat: true
 
 # Multiple reporter, options: [JMX, PROMETHEUS, IOTDB], IOTDB is off by default
 metricReporterList:
   - JMX
   - PROMETHEUS
+  - IOTDB
 
 # Type of monitor frame, options: [MICROMETER, DROPWIZARD]
-monitorType: MICROMETER
+monitorType: DROPWIZARD
 
 # Level of metric level, options: [CORE, IMPORTANT, NORMAL, ALL]
-metricLevel: IMPORTANT
+metricLevel: ALL
 
-# Predefined metric, options: [JVM, LOGBACK], LOGBACK are not supported in dropwizard
+# Predefined metric, options: [JVM, LOGBACK, FILE, PROCESS, SYSTEM]
 predefinedMetrics:
   - JVM
+  - LOGBACK
+  - FILE
+  - PROCESS
+  - SYSTEM
+
+# The period of the collection of some metrics in asynchronous way, such as tsfile size.
+asyncCollectPeriodInSecond: 10
 
 # The http server's port for prometheus exporter to get metric data.
-prometheusExporterPort: 9091
+prometheusExporterPort: 9090
 
 # The config of iotdb reporter
 ioTDBReporterConfig:
-  host: 127.0.0.1
-  port: 6667
-  username: root
-  password: root
-  maxConnectionNumber: 3
-  database: _metric
-  pushPeriodInSecond: 15
\ No newline at end of file
+  host: 0.0.0.0
+  port: 6669
+  username: user
+  password: password
+  maxConnectionNumber: 1
+  database: metric
+  pushPeriodInSecond: 5
\ No newline at end of file
diff --git a/metrics/micrometer-metrics/pom.xml b/metrics/micrometer-metrics/pom.xml
index 673855bbd4..c230bbe46b 100644
--- a/metrics/micrometer-metrics/pom.xml
+++ b/metrics/micrometer-metrics/pom.xml
@@ -36,17 +36,17 @@
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-registry-prometheus</artifactId>
-            <version>1.6.2</version>
+            <version>${micrometer.metrics.version}</version>
         </dependency>
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-registry-jmx</artifactId>
-            <version>1.6.2</version>
+            <version>${micrometer.metrics.version}</version>
         </dependency>
         <dependency>
             <groupId>io.dropwizard.metrics</groupId>
             <artifactId>metrics-core</artifactId>
-            <version>${metrics.version}</version>
+            <version>${dropwizard.metrics.version}</version>
         </dependency>
         <dependency>
             <groupId>io.projectreactor.netty</groupId>
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MetricName.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MetricName.java
deleted file mode 100644
index 0c4d69a8ac..0000000000
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MetricName.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.micrometer;
-
-import org.apache.iotdb.metrics.utils.MetricLevel;
-
-import io.micrometer.core.instrument.Meter;
-import io.micrometer.core.instrument.Tags;
-
-public class MetricName {
-  private Meter.Id id;
-  private MetricLevel metricLevel;
-
-  public MetricName(String name, Meter.Type type, String... tags) {
-    this.id = new Meter.Id(name, Tags.of(tags), null, null, type);
-  }
-
-  public MetricName(String name, Meter.Type type, MetricLevel metricLevel, String... tags) {
-    this(name, type, tags);
-    this.metricLevel = metricLevel;
-  }
-
-  public Meter.Id getId() {
-    return id;
-  }
-
-  public MetricLevel getMetricLevel() {
-    return metricLevel;
-  }
-
-  @Override
-  public String toString() {
-    return id.toString();
-  }
-
-  @Override
-  public boolean equals(Object obj) {
-    // do not compare metricLevel
-    if (!(obj instanceof MetricName)) {
-      return false;
-    }
-    return id.equals(((MetricName) obj).getId());
-  }
-
-  @Override
-  public int hashCode() {
-    return id.hashCode();
-  }
-}
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManager.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManager.java
index 860fa88b55..cef5630f52 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManager.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManager.java
@@ -19,10 +19,7 @@
 
 package org.apache.iotdb.metrics.micrometer;
 
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.config.MetricConfig;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
-import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.micrometer.type.MicrometerAutoGauge;
 import org.apache.iotdb.metrics.micrometer.type.MicrometerCounter;
 import org.apache.iotdb.metrics.micrometer.type.MicrometerGauge;
@@ -32,417 +29,100 @@ import org.apache.iotdb.metrics.micrometer.type.MicrometerTimer;
 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.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricInfo;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.Metrics;
-import io.micrometer.core.instrument.Tag;
 import io.micrometer.core.instrument.Tags;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.ToLongFunction;
 
 /** Metric manager based on micrometer. More details in https://micrometer.io/. */
 @SuppressWarnings("common-java:DuplicatedBlocks")
-public class MicrometerMetricManager implements MetricManager {
-  private static final Logger logger = LoggerFactory.getLogger(MicrometerMetricManager.class);
+public class MicrometerMetricManager extends AbstractMetricManager {
 
-  Map<MetricName, IMetric> currentMeters;
-  boolean isEnable;
   io.micrometer.core.instrument.MeterRegistry meterRegistry;
 
-  MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
-
-  /** init the field with micrometer library. */
   public MicrometerMetricManager() {
     meterRegistry = Metrics.globalRegistry;
-    currentMeters = new ConcurrentHashMap<>();
-    isEnable = metricConfig.getEnableMetric();
-  }
-
-  /**
-   * init of manager
-   *
-   * @see org.apache.iotdb.metrics.MetricService
-   */
-  @Override
-  public boolean init() {
-    return true;
-  }
-
-  @Override
-  public Counter getOrCreateCounter(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingCounter;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.COUNTER, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName, key -> new MicrometerCounter(meterRegistry.counter(metric, tags)));
-    if (m instanceof Counter) {
-      return (Counter) m;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public <T> Gauge getOrCreateAutoGauge(
-      String metric, MetricLevel metricLevel, T obj, ToLongFunction<T> mapper, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingGauge;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key -> new MicrometerAutoGauge<T>(meterRegistry, metric, obj, mapper, tags));
-    if (m instanceof Gauge) {
-      return (Gauge) m;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Gauge getOrCreateGauge(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingGauge;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName, key -> new MicrometerGauge(meterRegistry, metric, tags));
-    if (m instanceof Gauge) {
-      return (Gauge) m;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Histogram getOrCreateHistogram(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingHistogram;
-    }
-    MetricName metricName =
-        new MetricName(metric, Meter.Type.DISTRIBUTION_SUMMARY, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key -> {
-              io.micrometer.core.instrument.DistributionSummary distributionSummary =
-                  io.micrometer.core.instrument.DistributionSummary.builder(metric)
-                      .tags(tags)
-                      .register(meterRegistry);
-              return new MicrometerHistogram(distributionSummary);
-            });
-    if (m instanceof Histogram) {
-      return (Histogram) m;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  /**
-   * We only create a gauge(AtomicLong) to record the raw value, because we assume that the backend
-   * metrics system has the ability to calculate getOrCreatRate.
-   *
-   * @param metric the name
-   * @param metricLevel
-   * @param tags tags to describe some attribute
-   * @return Rate instance
-   */
-  @Override
-  public Rate getOrCreateRate(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingRate;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, metricLevel, tags);
-
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key ->
-                new MicrometerRate(meterRegistry.gauge(metric, Tags.of(tags), new AtomicLong(0))));
-    if (m instanceof Rate) {
-      return (Rate) m;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public Timer getOrCreateTimer(String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return DoNothingMetricManager.doNothingTimer;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.TIMER, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key -> {
-              io.micrometer.core.instrument.Timer timer =
-                  io.micrometer.core.instrument.Timer.builder(metric)
-                      .tags(tags)
-                      .register(meterRegistry);
-              logger.info("create getOrCreateTimer {}", metric);
-              return new MicrometerTimer(timer);
-            });
-    if (m instanceof Timer) {
-      return (Timer) m;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void count(long delta, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.COUNTER, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName, key -> new MicrometerCounter(meterRegistry.counter(metric, tags)));
-    if (m instanceof Counter) {
-      ((Counter) m).inc(delta);
-    }
-  }
-
-  @Override
-  public void histogram(long value, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName metricName =
-        new MetricName(metric, Meter.Type.DISTRIBUTION_SUMMARY, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key -> {
-              io.micrometer.core.instrument.DistributionSummary distributionSummary =
-                  io.micrometer.core.instrument.DistributionSummary.builder(metric)
-                      .tags(tags)
-                      .publishPercentileHistogram()
-                      .publishPercentiles(0)
-                      .register(meterRegistry);
-              return new MicrometerHistogram(distributionSummary);
-            });
-    if (m instanceof Histogram) {
-      ((Histogram) m).update(value);
-      return;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void gauge(long value, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, metricLevel, tags);
-    IMetric m =
-        (currentMeters.computeIfAbsent(
-            metricName, key -> new MicrometerGauge(meterRegistry, metric, tags)));
-    if (m instanceof Gauge) {
-      ((Gauge) m).set(value);
-      return;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public void rate(long value, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key ->
-                new MicrometerRate(meterRegistry.gauge(metric, Tags.of(tags), new AtomicLong(0))));
-
-    if (m instanceof Rate) {
-      ((Rate) m).mark(value);
-      return;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public synchronized void timer(
-      long delta, TimeUnit timeUnit, String metric, MetricLevel metricLevel, String... tags) {
-    if (!isEnable(metricLevel)) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.TIMER, metricLevel, tags);
-    IMetric m =
-        currentMeters.computeIfAbsent(
-            metricName,
-            key -> {
-              io.micrometer.core.instrument.Timer timer =
-                  io.micrometer.core.instrument.Timer.builder(metric)
-                      .tags(tags)
-                      .register(meterRegistry);
-              return new MicrometerTimer(timer);
-            });
-    if (m instanceof Timer) {
-      ((Timer) m).update(delta, timeUnit);
-      return;
-    }
-    throw new IllegalArgumentException(
-        metricName + " is already used for a different type of metric");
-  }
-
-  @Override
-  public List<String[]> getAllMetricKeys() {
-    List<String[]> keys = new ArrayList<>(currentMeters.size());
-    List<Meter> meterList = meterRegistry.getMeters();
-    for (Meter meter : meterList) {
-      List<String> tags = new ArrayList<>(meter.getId().getTags().size() * 2 + 1);
-      tags.add(meter.getId().getName());
-      for (Tag tag : meter.getId().getTags()) {
-        tags.add(tag.getKey());
-        tags.add(tag.getValue());
-      }
-      keys.add(tags.toArray(new String[0]));
-    }
-    return keys;
   }
 
   @Override
-  public Map<String[], Counter> getAllCounters() {
-    Map<String[], IMetric> metricMap = getMetricByType(Meter.Type.COUNTER);
-    Map<String[], Counter> counterMap = new HashMap<>();
-    metricMap.forEach((k, v) -> counterMap.put(k, (Counter) v));
-    return counterMap;
+  public Counter createCounter(MetricInfo metricInfo) {
+    return new MicrometerCounter(
+        meterRegistry.counter(metricInfo.getName(), metricInfo.getTagsInArray()));
   }
 
   @Override
-  public Map<String[], Gauge> getAllGauges() {
-    Map<String[], IMetric> metricMap = getMetricByType(Meter.Type.GAUGE);
-    Map<String[], Gauge> gaugeMap = new HashMap<>();
-    metricMap.forEach((k, v) -> gaugeMap.put(k, (Gauge) v));
-    return gaugeMap;
+  public <T> Gauge createAutoGauge(MetricInfo metricInfo, T obj, ToLongFunction<T> mapper) {
+    return new MicrometerAutoGauge<T>(
+        meterRegistry, metricInfo.getName(), obj, mapper, metricInfo.getTagsInArray());
   }
 
   @Override
-  public Map<String[], Rate> getAllRates() {
-    Map<String[], IMetric> metricMap = getMetricByType(Meter.Type.OTHER);
-    Map<String[], Rate> rateMap = new HashMap<>();
-    metricMap.forEach((k, v) -> rateMap.put(k, (Rate) v));
-    return rateMap;
+  public Gauge createGauge(MetricInfo metricInfo) {
+    return new MicrometerGauge(meterRegistry, metricInfo.getName(), metricInfo.getTagsInArray());
   }
 
   @Override
-  public Map<String[], Histogram> getAllHistograms() {
-    Map<String[], IMetric> metricMap = getMetricByType(Meter.Type.DISTRIBUTION_SUMMARY);
-    Map<String[], Histogram> histogramMap = new HashMap<>();
-    metricMap.forEach((k, v) -> histogramMap.put(k, (Histogram) v));
-    return histogramMap;
+  public Histogram createHistogram(MetricInfo metricInfo) {
+    io.micrometer.core.instrument.DistributionSummary distributionSummary =
+        io.micrometer.core.instrument.DistributionSummary.builder(metricInfo.getName())
+            .tags(metricInfo.getTagsInArray())
+            .publishPercentiles(0, 0.25, 0.5, 0.75, 1)
+            .register(meterRegistry);
+    return new MicrometerHistogram(distributionSummary);
   }
 
   @Override
-  public Map<String[], Timer> getAllTimers() {
-    Map<String[], IMetric> metricMap = getMetricByType(Meter.Type.TIMER);
-    Map<String[], Timer> timerMap = new HashMap<>();
-    metricMap.forEach((k, v) -> timerMap.put(k, (Timer) v));
-    return timerMap;
-  }
-
-  private Map<String[], IMetric> getMetricByType(Meter.Type type) {
-    Map<String[], IMetric> metricMap = new HashMap<>();
-    for (Map.Entry<MetricName, IMetric> entry : currentMeters.entrySet()) {
-      if (entry.getKey().getId().getType() == type) {
-        List<String> tags = new ArrayList<>(entry.getKey().getId().getTags().size() * 2);
-        tags.add(entry.getKey().getId().getName());
-        for (Tag tag : entry.getKey().getId().getTags()) {
-          tags.add(tag.getKey());
-          tags.add(tag.getValue());
-        }
-        metricMap.put(tags.toArray(new String[0]), entry.getValue());
-      }
-    }
-    return metricMap;
-  }
-
-  @Override
-  public void removeCounter(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.COUNTER, tags);
-    currentMeters.remove(metricName);
-  }
-
-  @Override
-  public void removeGauge(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, tags);
-    currentMeters.remove(metricName);
+  public Rate createRate(MetricInfo metricInfo) {
+    return new MicrometerRate(
+        meterRegistry.gauge(
+            metricInfo.getName(), Tags.of(metricInfo.getTagsInArray()), new AtomicLong(0)));
   }
 
   @Override
-  public void removeRate(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.GAUGE, tags);
-    currentMeters.remove(metricName);
-  }
-
-  @Override
-  public void removeHistogram(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.DISTRIBUTION_SUMMARY, tags);
-    currentMeters.remove(metricName);
+  public Timer createTimer(MetricInfo metricInfo) {
+    io.micrometer.core.instrument.Timer timer =
+        io.micrometer.core.instrument.Timer.builder(metricInfo.getName())
+            .tags(metricInfo.getTagsInArray())
+            .publishPercentiles(0, 0.25, 0.5, 0.75, 1)
+            .register(meterRegistry);
+    return new MicrometerTimer(timer);
   }
 
   @Override
-  public void removeTimer(String metric, String... tags) {
-    if (!isEnable()) {
-      return;
-    }
-    MetricName metricName = new MetricName(metric, Meter.Type.TIMER, tags);
-    currentMeters.remove(metricName);
+  protected void remove(MetricType type, MetricInfo metricInfo) {
+    Meter.Type meterType = transformType(type);
+    Meter.Id id =
+        new Meter.Id(
+            metricInfo.getName(), Tags.of(metricInfo.getTagsInArray()), null, null, meterType);
+    meterRegistry.remove(id);
   }
 
-  /** stop everything and clear */
   @Override
-  public boolean stop() {
-    isEnable = metricConfig.getEnableMetric();
+  public boolean stopFramework() {
     meterRegistry.clear();
-    currentMeters = new ConcurrentHashMap<>();
     return true;
   }
 
-  @Override
-  public boolean isEnable() {
-    return isEnable;
-  }
-
-  @Override
-  public boolean isEnable(MetricLevel metricLevel) {
-    return isEnable() && MetricLevel.higherOrEqual(metricLevel, metricConfig.getMetricLevel());
+  private Meter.Type transformType(MetricType type) {
+    switch (type) {
+      case COUNTER:
+        return Meter.Type.COUNTER;
+      case GAUGE:
+      case RATE:
+        return Meter.Type.GAUGE;
+      case HISTOGRAM:
+        return Meter.Type.DISTRIBUTION_SUMMARY;
+      case TIMER:
+        return Meter.Type.TIMER;
+      default:
+        return Meter.Type.OTHER;
+    }
   }
 }
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerIoTDBReporter.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
index 0108c185ad..6b83425be4 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerIoTDBReporter.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.metrics.micrometer.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.reporter.Reporter;
 import org.apache.iotdb.metrics.utils.ReporterType;
 
@@ -36,7 +36,7 @@ import java.util.stream.Collectors;
 public class MicrometerIoTDBReporter implements Reporter {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(MicrometerIoTDBReporter.class);
-  private MetricManager metricManager;
+  private AbstractMetricManager metricManager;
 
   @Override
   public boolean start() {
@@ -86,7 +86,7 @@ public class MicrometerIoTDBReporter implements Reporter {
   }
 
   @Override
-  public void setMetricManager(MetricManager metricManager) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     this.metricManager = metricManager;
   }
 }
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerJmxReporter.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerJmxReporter.java
index f89e3a07e3..b306712667 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerJmxReporter.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerJmxReporter.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.metrics.micrometer.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.reporter.Reporter;
 import org.apache.iotdb.metrics.utils.ReporterType;
 
@@ -35,7 +35,7 @@ import java.util.stream.Collectors;
 
 public class MicrometerJmxReporter implements Reporter {
   private static final Logger LOGGER = LoggerFactory.getLogger(MicrometerJmxReporter.class);
-  private MetricManager metricManager;
+  private AbstractMetricManager metricManager;
 
   @Override
   public boolean start() {
@@ -81,7 +81,7 @@ public class MicrometerJmxReporter implements Reporter {
   }
 
   @Override
-  public void setMetricManager(MetricManager metricManager) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     this.metricManager = metricManager;
   }
 }
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerPrometheusReporter.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerPrometheusReporter.java
index c4735236a4..e163b53820 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerPrometheusReporter.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/reporter/MicrometerPrometheusReporter.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.metrics.micrometer.reporter;
 
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.config.MetricConfig;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.reporter.Reporter;
@@ -45,7 +45,7 @@ public class MicrometerPrometheusReporter implements Reporter {
   private static final MetricConfig metricConfig =
       MetricConfigDescriptor.getInstance().getMetricConfig();
 
-  private MetricManager metricManager;
+  private AbstractMetricManager metricManager;
   private DisposableServer httpServer;
 
   @Override
@@ -66,7 +66,7 @@ public class MicrometerPrometheusReporter implements Reporter {
         HttpServer.create()
             .idleTimeout(Duration.ofMillis(30_000L))
             .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
-            .port(Integer.parseInt(metricConfig.getPrometheusExporterPort()))
+            .port(metricConfig.getPrometheusExporterPort())
             .route(
                 routes ->
                     routes.get(
@@ -107,7 +107,7 @@ public class MicrometerPrometheusReporter implements Reporter {
   }
 
   @Override
-  public void setMetricManager(MetricManager metricManager) {
+  public void setMetricManager(AbstractMetricManager metricManager) {
     this.metricManager = metricManager;
   }
 }
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerRate.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerRate.java
index 0789f1c7ae..50b8e538e2 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerRate.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerRate.java
@@ -39,7 +39,7 @@ public class MicrometerRate implements Rate {
 
   public MicrometerRate(AtomicLong atomicLong) {
     this.atomicLong = atomicLong;
-    meter = new Meter();
+    this.meter = new Meter();
   }
 
   @Override
diff --git a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerTimer.java b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerTimer.java
index 07c68e4bb6..a58713d9c4 100644
--- a/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerTimer.java
+++ b/metrics/micrometer-metrics/src/main/java/org/apache/iotdb/metrics/micrometer/type/MicrometerTimer.java
@@ -39,7 +39,7 @@ public class MicrometerTimer implements Timer {
   @Override
   public void update(long duration, TimeUnit unit) {
     timer.record(duration, unit);
-    micrometerRate.mark(duration);
+    micrometerRate.mark();
   }
 
   @Override
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.AbstractMetricManager
similarity index 100%
rename from metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.MetricManager
rename to metrics/micrometer-metrics/src/main/resources/META-INF/services/org.apache.iotdb.metrics.AbstractMetricManager
diff --git a/metrics/micrometer-metrics/src/test/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManagerTest.java b/metrics/micrometer-metrics/src/test/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManagerTest.java
deleted file mode 100644
index 89a58bf38f..0000000000
--- a/metrics/micrometer-metrics/src/test/java/org/apache/iotdb/metrics/micrometer/MicrometerMetricManagerTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.micrometer;
-
-import org.apache.iotdb.metrics.DoNothingMetricService;
-import org.apache.iotdb.metrics.MetricManager;
-import org.apache.iotdb.metrics.MetricService;
-import org.apache.iotdb.metrics.config.MetricConfig;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
-import org.apache.iotdb.metrics.type.Gauge;
-import org.apache.iotdb.metrics.type.Timer;
-import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.MonitorType;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThrows;
-
-public class MicrometerMetricManagerTest {
-  static MetricConfig metricConfig = MetricConfigDescriptor.getInstance().getMetricConfig();
-  static MetricService metricService = new DoNothingMetricService();
-  static MetricManager metricManager;
-
-  @BeforeClass
-  public static void init() {
-    metricConfig.setEnableMetric(true);
-    metricConfig.setMonitorType(MonitorType.MICROMETER);
-    metricService.startService();
-    metricService.startAllReporter();
-    metricManager = metricService.getMetricManager();
-  }
-
-  private void getOrCreateDifferentMetricsWithSameName() {
-    Timer timer = metricManager.getOrCreateTimer("metric", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotNull(timer);
-    metricManager.getOrCreateCounter("metric", MetricLevel.IMPORTANT, "tag1", "tag2");
-  }
-
-  @Test
-  public void getOrCreateDifferentMetricsWithSameNameTest() {
-    assertThrows(IllegalArgumentException.class, this::getOrCreateDifferentMetricsWithSameName);
-  }
-
-  private void getOrCreateMetricsWithSameNameAndDifferentTags() {
-    metricManager.gauge(1L, "gaugeTest", MetricLevel.CORE, "a", "b");
-    metricManager.gauge(2L, "gaugeTest", MetricLevel.CORE, "a", "b", "c", "d");
-  }
-
-  @Test
-  public void testGetOrCreateMetricsWithSameNameAndDifferentTags() {
-    assertThrows(
-        IllegalArgumentException.class, this::getOrCreateMetricsWithSameNameAndDifferentTags);
-  }
-
-  @Test
-  public void testAutoGauge() {
-    List<Integer> list = new ArrayList<>();
-    Gauge autoGauge =
-        metricManager.getOrCreateAutoGauge(
-            "autoGaugeMetric", MetricLevel.IMPORTANT, list, List::size, "tagk", "tagv");
-    assertEquals(0L, autoGauge.value());
-    list.add(1);
-    assertEquals(1L, autoGauge.value());
-    list.clear();
-    assertEquals(0L, autoGauge.value());
-    list.add(1);
-    assertEquals(1L, autoGauge.value());
-    list = null;
-    System.gc();
-    assertEquals(0L, autoGauge.value());
-  }
-
-  @Test
-  public void removeGauge() {
-    Gauge gauge1 =
-        metricManager.getOrCreateGauge("gauge_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    metricManager.removeGauge("gauge_remove", "tag1", "tag2");
-    Gauge gauge2 =
-        metricManager.getOrCreateGauge("gauge_remove", MetricLevel.IMPORTANT, "tag1", "tag2");
-    assertNotEquals(gauge1, gauge2);
-  }
-}
diff --git a/node-commons/src/main/java/org/apache/iotdb/commons/service/ServiceType.java b/node-commons/src/main/java/org/apache/iotdb/commons/service/ServiceType.java
index ae930eea60..ec38df7015 100644
--- a/node-commons/src/main/java/org/apache/iotdb/commons/service/ServiceType.java
+++ b/node-commons/src/main/java/org/apache/iotdb/commons/service/ServiceType.java
@@ -22,7 +22,7 @@ package org.apache.iotdb.commons.service;
 public enum ServiceType {
   STORAGE_ENGINE_SERVICE("Storage Engine ServerService", ""),
   JMX_SERVICE("JMX ServerService", "JMX ServerService"),
-  METRICS_SERVICE("Metrics ServerService", "MetricsService"),
+  METRIC_SERVICE("Metrics ServerService", "MetricService"),
   RPC_SERVICE("RPC ServerService", "RPCService"),
   INFLUX_SERVICE("InfluxDB Protocol Service", "InfluxDB Protocol"),
   MQTT_SERVICE("MQTTService", ""),
diff --git a/pom.xml b/pom.xml
index 2b45bcb2dd..198403d10c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -153,7 +153,8 @@
         <guava.version>24.1.1</guava.version>
         <jline.version>3.21.0</jline.version>
         <jetty.version>9.4.48.v20220622</jetty.version>
-        <metrics.version>4.2.7</metrics.version>
+        <dropwizard.metrics.version>4.2.7</dropwizard.metrics.version>
+        <micrometer.metrics.version>1.6.2</micrometer.metrics.version>
         <javax.xml.bind.version>2.4.0-b180830.0359</javax.xml.bind.version>
         <felix.version>5.1.7</felix.version>
         <snappy.version>1.1.8.4</snappy.version>
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index 29ea7ce6a2..aecb8a54f8 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -36,7 +36,7 @@ import org.apache.iotdb.db.engine.compaction.constant.InnerUnsequenceCompactionS
 import org.apache.iotdb.db.exception.BadNodeUrlFormatException;
 import org.apache.iotdb.db.exception.query.QueryProcessException;
 import org.apache.iotdb.db.qp.utils.DatetimeUtils;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.wal.WALManager;
 import org.apache.iotdb.db.wal.utils.WALMode;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
@@ -1451,8 +1451,8 @@ public class IoTDBDescriptor {
       throw new QueryProcessException(
           String.format("Fail to reload config file %s because %s", url, e.getMessage()));
     }
-    ReloadLevel reloadLevel = MetricConfigDescriptor.getInstance().loadHotProperties();
-    MetricsService.getInstance().reloadProperties(reloadLevel);
+    ReloadLevel reloadLevel = MetricConfigDescriptor.getInstance().loadHotProps();
+    MetricService.getInstance().reloadProperties(reloadLevel);
   }
 
   private void initMemoryAllocate(Properties properties) {
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCache.java b/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCache.java
index a32f301d78..1b74456ad3 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCache.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCache.java
@@ -23,10 +23,9 @@ import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.query.control.FileReaderManager;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
 import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
@@ -87,17 +86,14 @@ public class ChunkCache {
                 });
 
     // add metrics
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CACHE_HIT.toString(),
-              MetricLevel.IMPORTANT,
-              lruCache,
-              l -> (long) (l.stats().hitRate() * 100),
-              Tag.NAME.toString(),
-              "chunk");
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CACHE_HIT.toString(),
+            MetricLevel.IMPORTANT,
+            lruCache,
+            l -> (long) (l.stats().hitRate() * 100),
+            Tag.NAME.toString(),
+            "chunk");
   }
 
   public static ChunkCache getInstance() {
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCache.java b/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCache.java
index 7f10ce7df6..576d178429 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCache.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCache.java
@@ -24,10 +24,9 @@ import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.query.control.FileReaderManager;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
 import org.apache.iotdb.tsfile.file.metadata.TimeseriesMetadata;
@@ -108,34 +107,29 @@ public class TimeSeriesMetadataCache {
             .recordStats()
             .build();
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      // add metrics
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CACHE_HIT.toString(),
-              MetricLevel.IMPORTANT,
-              lruCache,
-              l -> (long) (l.stats().hitRate() * 100),
-              Tag.NAME.toString(),
-              "timeSeriesMeta");
-      // add metrics
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CACHE_HIT.toString(),
-              MetricLevel.IMPORTANT,
-              bloomFilterPreventCount,
-              prevent -> {
-                if (bloomFilterRequestCount.get() == 0L) {
-                  return 1L;
-                }
-                return (long)
-                    ((double) prevent.get() / (double) bloomFilterRequestCount.get() * 100L);
-              },
-              Tag.NAME.toString(),
-              "bloomFilter");
-    }
+    // add metrics
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CACHE_HIT.toString(),
+            MetricLevel.IMPORTANT,
+            lruCache,
+            l -> (long) (l.stats().hitRate() * 100),
+            Tag.NAME.toString(),
+            "timeSeriesMeta");
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CACHE_HIT.toString(),
+            MetricLevel.IMPORTANT,
+            bloomFilterPreventCount,
+            prevent -> {
+              if (bloomFilterRequestCount.get() == 0L) {
+                return 1L;
+              }
+              return (long)
+                  ((double) prevent.get() / (double) bloomFilterRequestCount.get() * 100L);
+            },
+            Tag.NAME.toString(),
+            "bloomFilter");
   }
 
   public static TimeSeriesMetadataCache getInstance() {
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/inner/utils/SingleSeriesCompactionExecutor.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/inner/utils/SingleSeriesCompactionExecutor.java
index bcc3f0ef3a..40f2632d0e 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/inner/utils/SingleSeriesCompactionExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/inner/utils/SingleSeriesCompactionExecutor.java
@@ -25,7 +25,6 @@ import org.apache.iotdb.db.engine.compaction.constant.CompactionType;
 import org.apache.iotdb.db.engine.compaction.constant.ProcessChunkType;
 import org.apache.iotdb.db.engine.storagegroup.TsFileResource;
 import org.apache.iotdb.db.service.metrics.recorder.CompactionMetricsRecorder;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.tsfile.file.header.ChunkHeader;
 import org.apache.iotdb.tsfile.file.metadata.ChunkMetadata;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
@@ -73,8 +72,6 @@ public class SingleSeriesCompactionExecutor {
       IoTDBDescriptor.getInstance().getConfig().getChunkSizeLowerBoundInCompaction();
   private final long chunkPointNumLowerBound =
       IoTDBDescriptor.getInstance().getConfig().getChunkPointNumLowerBoundInCompaction();
-  private final boolean enableMetrics =
-      MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric();
 
   public SingleSeriesCompactionExecutor(
       PartialPath series,
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/compaction/writer/AbstractCompactionWriter.java b/server/src/main/java/org/apache/iotdb/db/engine/compaction/writer/AbstractCompactionWriter.java
index 6da38ebc16..542c44c4f0 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/compaction/writer/AbstractCompactionWriter.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/compaction/writer/AbstractCompactionWriter.java
@@ -23,7 +23,6 @@ import org.apache.iotdb.db.engine.compaction.CompactionTaskManager;
 import org.apache.iotdb.db.engine.compaction.constant.CompactionType;
 import org.apache.iotdb.db.engine.compaction.constant.ProcessChunkType;
 import org.apache.iotdb.db.service.metrics.recorder.CompactionMetricsRecorder;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.read.common.block.column.Column;
 import org.apache.iotdb.tsfile.read.common.block.column.TimeColumn;
@@ -51,8 +50,6 @@ public abstract class AbstractCompactionWriter implements AutoCloseable {
   protected String deviceId;
   private final long targetChunkSize =
       IoTDBDescriptor.getInstance().getConfig().getTargetChunkSize();
-  private final boolean enableMetrics =
-      MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric();
 
   // Each sub task has point count in current measurment, which is used to check size.
   // The index of the array corresponds to subTaskId.
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManager.java b/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManager.java
index d0455e0a7a..3eef0d9fcb 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManager.java
@@ -29,10 +29,9 @@ import org.apache.iotdb.db.engine.flush.pool.FlushSubTaskPoolManager;
 import org.apache.iotdb.db.engine.flush.pool.FlushTaskPoolManager;
 import org.apache.iotdb.db.engine.storagegroup.TsFileProcessor;
 import org.apache.iotdb.db.rescon.AbstractPoolManager;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 
 import org.slf4j.Logger;
@@ -56,31 +55,26 @@ public class FlushManager implements FlushManagerMBean, IService {
     flushPool.start();
     try {
       JMXService.registerMBean(this, ServiceType.FLUSH_SERVICE.getJmxName());
-      if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-        MetricsService.getInstance()
-            .getMetricManager()
-            .getOrCreateAutoGauge(
-                Metric.QUEUE.toString(),
-                MetricLevel.IMPORTANT,
-                flushPool,
-                AbstractPoolManager::getWaitingTasksNumber,
-                Tag.NAME.toString(),
-                "flush",
-                Tag.STATUS.toString(),
-                "waiting");
-        MetricsService.getInstance()
-            .getMetricManager()
-            .getOrCreateAutoGauge(
-                Metric.QUEUE.toString(),
-                MetricLevel.IMPORTANT,
-                flushPool,
-                AbstractPoolManager::getWorkingTasksNumber,
-                Tag.NAME.toString(),
-                "flush",
-                Tag.STATUS.toString(),
-                "running");
-      }
-
+      MetricService.getInstance()
+          .getOrCreateAutoGauge(
+              Metric.QUEUE.toString(),
+              MetricLevel.IMPORTANT,
+              flushPool,
+              AbstractPoolManager::getWaitingTasksNumber,
+              Tag.NAME.toString(),
+              "flush",
+              Tag.STATUS.toString(),
+              "waiting");
+      MetricService.getInstance()
+          .getOrCreateAutoGauge(
+              Metric.QUEUE.toString(),
+              MetricLevel.IMPORTANT,
+              flushPool,
+              AbstractPoolManager::getWorkingTasksNumber,
+              Tag.NAME.toString(),
+              "flush",
+              Tag.STATUS.toString(),
+              "running");
     } catch (Exception e) {
       throw new StartupException(this.getID().getName(), e.getMessage());
     }
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 5b145de275..a3ca350fea 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
@@ -27,10 +27,9 @@ import org.apache.iotdb.db.engine.memtable.IWritableMemChunkGroup;
 import org.apache.iotdb.db.exception.runtime.FlushRunTimeException;
 import org.apache.iotdb.db.metadata.idtable.entry.IDeviceID;
 import org.apache.iotdb.db.rescon.SystemInfo;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.write.chunk.IChunkWriter;
 import org.apache.iotdb.tsfile.write.writer.RestorableTsFileIOWriter;
@@ -162,17 +161,14 @@ public class MemTableFlushTask {
       SystemInfo.getInstance().setEncodingFasterThanIo(ioTime >= memSerializeTime);
     }
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .timer(
-              System.currentTimeMillis() - start,
-              TimeUnit.MILLISECONDS,
-              Metric.COST_TASK.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              "flush");
-    }
+    MetricService.getInstance()
+        .timer(
+            System.currentTimeMillis() - start,
+            TimeUnit.MILLISECONDS,
+            Metric.COST_TASK.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            "flush");
 
     LOGGER.info(
         "Storage group {} memtable {} flushing a memtable has finished! Time consumption: {}ms",
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java b/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
index 2b6d39d32b..e008ff8056 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/memtable/AbstractMemTable.java
@@ -33,13 +33,12 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertRowNode;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertTabletNode;
 import org.apache.iotdb.db.qp.physical.crud.InsertRowPlan;
 import org.apache.iotdb.db.qp.physical.crud.InsertTabletPlan;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.utils.MemUtils;
 import org.apache.iotdb.db.wal.buffer.IWALByteBufferView;
 import org.apache.iotdb.db.wal.utils.WALWriteUtils;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
 import org.apache.iotdb.tsfile.utils.Pair;
@@ -197,16 +196,13 @@ public abstract class AbstractMemTable implements IMemTable {
 
     totalPointsNum += pointsInserted;
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .count(
-              pointsInserted,
-              Metric.QUANTITY.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              METRIC_POINT_IN);
-    }
+    MetricService.getInstance()
+        .count(
+            pointsInserted,
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            METRIC_POINT_IN);
   }
 
   @Override
@@ -250,16 +246,13 @@ public abstract class AbstractMemTable implements IMemTable {
 
     totalPointsNum += pointsInserted;
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .count(
-              pointsInserted,
-              Metric.QUANTITY.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              METRIC_POINT_IN);
-    }
+    MetricService.getInstance()
+        .count(
+            pointsInserted,
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            METRIC_POINT_IN);
   }
 
   @Override
@@ -294,16 +287,13 @@ public abstract class AbstractMemTable implements IMemTable {
         insertRowPlan.getMeasurements().length - insertRowPlan.getFailedMeasurementNumber();
     totalPointsNum += pointsInserted;
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .count(
-              pointsInserted,
-              Metric.QUANTITY.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              METRIC_POINT_IN);
-    }
+    MetricService.getInstance()
+        .count(
+            pointsInserted,
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            METRIC_POINT_IN);
   }
 
   @Override
@@ -337,16 +327,13 @@ public abstract class AbstractMemTable implements IMemTable {
     int pointsInserted = insertRowNode.getMeasurements().length;
     totalPointsNum += pointsInserted;
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .count(
-              pointsInserted,
-              Metric.QUANTITY.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              METRIC_POINT_IN);
-    }
+    MetricService.getInstance()
+        .count(
+            pointsInserted,
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            METRIC_POINT_IN);
   }
 
   @Override
@@ -360,16 +347,13 @@ public abstract class AbstractMemTable implements IMemTable {
           (insertTabletPlan.getDataTypes().length - insertTabletPlan.getFailedMeasurementNumber())
               * (end - start);
       totalPointsNum += pointsInserted;
-      if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-        MetricsService.getInstance()
-            .getMetricManager()
-            .count(
-                pointsInserted,
-                Metric.QUANTITY.toString(),
-                MetricLevel.IMPORTANT,
-                Tag.NAME.toString(),
-                METRIC_POINT_IN);
-      }
+      MetricService.getInstance()
+          .count(
+              pointsInserted,
+              Metric.QUANTITY.toString(),
+              MetricLevel.IMPORTANT,
+              Tag.NAME.toString(),
+              METRIC_POINT_IN);
     } catch (RuntimeException e) {
       throw new WriteProcessException(e);
     }
@@ -386,16 +370,13 @@ public abstract class AbstractMemTable implements IMemTable {
           (insertTabletPlan.getDataTypes().length - insertTabletPlan.getFailedMeasurementNumber())
               * (end - start);
       totalPointsNum += pointsInserted;
-      if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-        MetricsService.getInstance()
-            .getMetricManager()
-            .count(
-                pointsInserted,
-                Metric.QUANTITY.toString(),
-                MetricLevel.IMPORTANT,
-                Tag.NAME.toString(),
-                METRIC_POINT_IN);
-      }
+      MetricService.getInstance()
+          .count(
+              pointsInserted,
+              Metric.QUANTITY.toString(),
+              MetricLevel.IMPORTANT,
+              Tag.NAME.toString(),
+              METRIC_POINT_IN);
     } catch (RuntimeException e) {
       throw new WriteProcessException(e);
     }
@@ -412,16 +393,13 @@ public abstract class AbstractMemTable implements IMemTable {
       memSize += MemUtils.getTabletSize(insertTabletNode, start, end, disableMemControl);
       int pointsInserted = insertTabletNode.getDataTypes().length * (end - start);
       totalPointsNum += pointsInserted;
-      if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-        MetricsService.getInstance()
-            .getMetricManager()
-            .count(
-                pointsInserted,
-                Metric.QUANTITY.toString(),
-                MetricLevel.IMPORTANT,
-                Tag.NAME.toString(),
-                METRIC_POINT_IN);
-      }
+      MetricService.getInstance()
+          .count(
+              pointsInserted,
+              Metric.QUANTITY.toString(),
+              MetricLevel.IMPORTANT,
+              Tag.NAME.toString(),
+              METRIC_POINT_IN);
     } catch (RuntimeException e) {
       throw new WriteProcessException(e);
     }
@@ -438,16 +416,13 @@ public abstract class AbstractMemTable implements IMemTable {
       memSize += MemUtils.getAlignedTabletSize(insertTabletNode, start, end, disableMemControl);
       int pointsInserted = insertTabletNode.getDataTypes().length * (end - start);
       totalPointsNum += pointsInserted;
-      if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-        MetricsService.getInstance()
-            .getMetricManager()
-            .count(
-                pointsInserted,
-                Metric.QUANTITY.toString(),
-                MetricLevel.IMPORTANT,
-                Tag.NAME.toString(),
-                METRIC_POINT_IN);
-      }
+      MetricService.getInstance()
+          .count(
+              pointsInserted,
+              Metric.QUANTITY.toString(),
+              MetricLevel.IMPORTANT,
+              Tag.NAME.toString(),
+              METRIC_POINT_IN);
     } catch (RuntimeException e) {
       throw new WriteProcessException(e);
     }
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/DataRegion.java b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/DataRegion.java
index 5ff47806d2..4e8ece7bb4 100755
--- a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/DataRegion.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/DataRegion.java
@@ -81,7 +81,7 @@ import org.apache.iotdb.db.query.control.QueryFileManager;
 import org.apache.iotdb.db.rescon.TsFileResourceManager;
 import org.apache.iotdb.db.service.IoTDB;
 import org.apache.iotdb.db.service.SettleService;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.sync.sender.manager.TsFileSyncManager;
@@ -96,7 +96,6 @@ import org.apache.iotdb.db.wal.recover.file.UnsealedTsFileRecoverPerformer;
 import org.apache.iotdb.db.wal.utils.WALMode;
 import org.apache.iotdb.db.wal.utils.listener.WALFlushListener;
 import org.apache.iotdb.db.wal.utils.listener.WALRecoverListener;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.rpc.RpcUtils;
 import org.apache.iotdb.rpc.TSStatusCode;
@@ -345,17 +344,14 @@ public class DataRegion {
       recover();
     }
 
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              storageGroupInfo,
-              StorageGroupInfo::getMemCost,
-              Tag.NAME.toString(),
-              "storageGroup_" + getLogicalStorageGroupName());
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.MEM.toString(),
+            MetricLevel.IMPORTANT,
+            storageGroupInfo,
+            StorageGroupInfo::getMemCost,
+            Tag.NAME.toString(),
+            "storageGroup_" + getLogicalStorageGroupName());
   }
 
   public String getLogicalStorageGroupName() {
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfo.java b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfo.java
index 71298ca5e4..4eb8442697 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfo.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfo.java
@@ -18,10 +18,9 @@
  */
 package org.apache.iotdb.db.engine.storagegroup;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 
 /** The TsFileProcessorInfo records the memory cost of this TsFileProcessor. */
@@ -42,9 +41,8 @@ public class TsFileProcessorInfo {
   public void addTSPMemCost(long cost) {
     memCost += cost;
     storageGroupInfo.addStorageGroupMemCost(cost);
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
+    if (null != storageGroupInfo.getDataRegion()) {
+      MetricService.getInstance()
           .getOrCreateGauge(
               Metric.MEM.toString(),
               MetricLevel.IMPORTANT,
@@ -58,31 +56,25 @@ public class TsFileProcessorInfo {
   public void releaseTSPMemCost(long cost) {
     storageGroupInfo.releaseStorageGroupMemCost(cost);
     memCost -= cost;
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              "chunkMetaData_" + storageGroupInfo.getDataRegion().getLogicalStorageGroupName())
-          .decr(cost);
-    }
+    MetricService.getInstance()
+        .getOrCreateGauge(
+            Metric.MEM.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            "chunkMetaData_" + storageGroupInfo.getDataRegion().getLogicalStorageGroupName())
+        .decr(cost);
   }
 
   /** called when closing TSP */
   public void clear() {
     storageGroupInfo.releaseStorageGroupMemCost(memCost);
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              "chunkMetaData_" + storageGroupInfo.getDataRegion().getLogicalStorageGroupName())
-          .decr(memCost);
-    }
+    MetricService.getInstance()
+        .getOrCreateGauge(
+            Metric.MEM.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            "chunkMetaData_" + storageGroupInfo.getDataRegion().getLogicalStorageGroupName())
+        .decr(memCost);
     memCost = 0L;
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java b/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
index 4afca8a361..5306817e8c 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/cache/DataNodeSchemaCache.java
@@ -25,10 +25,9 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.metadata.path.MeasurementPath;
 import org.apache.iotdb.db.mpp.common.schematree.ClusterSchemaTree;
 import org.apache.iotdb.db.mpp.common.schematree.ISchemaTree;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.read.TimeValuePair;
 import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
@@ -57,18 +56,14 @@ public class DataNodeSchemaCache {
                 (PartialPath key, SchemaCacheEntry value) ->
                     PartialPath.estimateSize(key) + SchemaCacheEntry.estimateSize(value))
             .build();
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      // add metrics
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.CACHE_HIT.toString(),
-              MetricLevel.IMPORTANT,
-              cache,
-              l -> (long) (l.stats().hitRate() * 100),
-              Tag.NAME.toString(),
-              "schemaCache");
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.CACHE_HIT.toString(),
+            MetricLevel.IMPORTANT,
+            cache,
+            l -> (long) (l.stats().hitRate() * 100),
+            Tag.NAME.toString(),
+            "schemaCache");
   }
 
   public static DataNodeSchemaCache getInstance() {
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/rescon/TimeseriesStatistics.java b/server/src/main/java/org/apache/iotdb/db/metadata/rescon/TimeseriesStatistics.java
index 097d1accce..f8a1f21a20 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/rescon/TimeseriesStatistics.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/rescon/TimeseriesStatistics.java
@@ -18,10 +18,9 @@
  */
 package org.apache.iotdb.db.metadata.rescon;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 
 import java.util.concurrent.atomic.AtomicLong;
@@ -45,17 +44,14 @@ public class TimeseriesStatistics {
   }
 
   public void init() {
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.QUANTITY.toString(),
-              MetricLevel.IMPORTANT,
-              totalSeriesNumber,
-              AtomicLong::get,
-              Tag.NAME.toString(),
-              "timeSeries");
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            totalSeriesNumber,
+            AtomicLong::get,
+            Tag.NAME.toString(),
+            "timeSeries");
   }
 
   public long getTotalSeriesNumber() {
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeService.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeService.java
index 3ccbcbb512..5dcd2866db 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeService.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeService.java
@@ -34,7 +34,7 @@ import org.apache.iotdb.db.client.DataNodeClientPoolFactory;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.mpp.execution.memory.LocalMemoryManager;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -110,8 +110,7 @@ public class MPPDataExchangeService extends ThriftService implements MPPDataExch
       throw new IllegalAccessException(e.getMessage());
     }
     thriftServiceThread.setName(ThreadName.MPP_DATA_EXCHANGE_RPC_SERVER.getName());
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateAutoGauge(
             Metric.THRIFT_ACTIVE_THREADS.toString(),
             MetricLevel.CORE,
diff --git a/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeServiceThriftHandler.java b/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeServiceThriftHandler.java
index cfe80c687f..60d50729d9 100644
--- a/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeServiceThriftHandler.java
+++ b/server/src/main/java/org/apache/iotdb/db/mpp/execution/exchange/MPPDataExchangeServiceThriftHandler.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.db.mpp.execution.exchange;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -36,8 +36,7 @@ public class MPPDataExchangeServiceThriftHandler implements TServerEventHandler
 
   @Override
   public ServerContext createContext(TProtocol tProtocol, TProtocol tProtocol1) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(),
             MetricLevel.CORE,
@@ -50,8 +49,7 @@ public class MPPDataExchangeServiceThriftHandler implements TServerEventHandler
   @Override
   public void deleteContext(
       ServerContext serverContext, TProtocol tProtocol, TProtocol tProtocol1) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(),
             MetricLevel.CORE,
diff --git a/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManager.java b/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManager.java
index 1a1301f130..f2fbf7c92b 100644
--- a/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManager.java
@@ -23,10 +23,9 @@ import org.apache.iotdb.commons.concurrent.IoTDBThreadPoolFactory;
 import org.apache.iotdb.commons.concurrent.ThreadName;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.rescon.AbstractPoolManager;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 
 import org.slf4j.Logger;
@@ -51,30 +50,26 @@ public class RawQueryReadTaskPoolManager extends AbstractPoolManager {
     pool =
         IoTDBThreadPoolFactory.newFixedThreadPool(
             threadCnt, ThreadName.SUB_RAW_QUERY_SERVICE.getName());
-    if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.QUEUE.toString(),
-              MetricLevel.IMPORTANT,
-              pool,
-              p -> ((ThreadPoolExecutor) p).getActiveCount(),
-              Tag.NAME.toString(),
-              ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
-              Tag.STATUS.toString(),
-              "running");
-      MetricsService.getInstance()
-          .getMetricManager()
-          .getOrCreateAutoGauge(
-              Metric.QUEUE.toString(),
-              MetricLevel.IMPORTANT,
-              pool,
-              p -> ((ThreadPoolExecutor) p).getQueue().size(),
-              Tag.NAME.toString(),
-              ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
-              Tag.STATUS.toString(),
-              "waiting");
-    }
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUEUE.toString(),
+            MetricLevel.IMPORTANT,
+            pool,
+            p -> ((ThreadPoolExecutor) p).getActiveCount(),
+            Tag.NAME.toString(),
+            ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
+            Tag.STATUS.toString(),
+            "running");
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUEUE.toString(),
+            MetricLevel.IMPORTANT,
+            pool,
+            p -> ((ThreadPoolExecutor) p).getQueue().size(),
+            Tag.NAME.toString(),
+            ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
+            Tag.STATUS.toString(),
+            "waiting");
   }
 
   public static RawQueryReadTaskPoolManager getInstance() {
diff --git a/server/src/main/java/org/apache/iotdb/db/service/DataNode.java b/server/src/main/java/org/apache/iotdb/db/service/DataNode.java
index c5f27b0813..6838d6f9fa 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/DataNode.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/DataNode.java
@@ -59,7 +59,7 @@ import org.apache.iotdb.db.mpp.execution.schedule.DriverScheduler;
 import org.apache.iotdb.db.protocol.mpprest.MPPRestService;
 import org.apache.iotdb.db.service.basic.ServiceProvider;
 import org.apache.iotdb.db.service.basic.StandaloneServiceProvider;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.thrift.impl.ClientRPCServiceImpl;
 import org.apache.iotdb.db.sync.SyncService;
 import org.apache.iotdb.db.wal.WALManager;
@@ -257,7 +257,7 @@ public class DataNode implements DataNodeMBean {
     initServiceProvider();
 
     // init metric service
-    registerManager.register(MetricsService.getInstance());
+    registerManager.register(MetricService.getInstance());
 
     logger.info("recover the schema...");
     initSchemaEngine();
@@ -303,7 +303,7 @@ public class DataNode implements DataNodeMBean {
     registerManager.register(ContinuousQueryService.getInstance());
 
     // start reporter
-    MetricsService.getInstance().startAllReporter();
+    MetricService.getInstance().startAllReporter();
 
     // start region migrate service
     registerManager.register(RegionMigrateService.getInstance());
@@ -389,7 +389,7 @@ public class DataNode implements DataNodeMBean {
 
     // QSW
     try {
-      MetricsService.getInstance().stop();
+      MetricService.getInstance().stop();
       SchemaRegionConsensusImpl.getInstance().stop();
       DataRegionConsensusImpl.getInstance().stop();
     } catch (Exception e) {
diff --git a/server/src/main/java/org/apache/iotdb/db/service/DataNodeInternalRPCService.java b/server/src/main/java/org/apache/iotdb/db/service/DataNodeInternalRPCService.java
index 7ba65031a0..0724796e30 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/DataNodeInternalRPCService.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/DataNodeInternalRPCService.java
@@ -27,7 +27,7 @@ import org.apache.iotdb.commons.service.ThriftService;
 import org.apache.iotdb.commons.service.ThriftServiceThread;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.service.thrift.handler.InternalServiceThriftHandler;
@@ -76,8 +76,7 @@ public class DataNodeInternalRPCService extends ThriftService
       throw new IllegalAccessException(e.getMessage());
     }
     thriftServiceThread.setName(ThreadName.INTERNAL_SERVICE_RPC_SERVER.getName());
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateAutoGauge(
             Metric.THRIFT_ACTIVE_THREADS.toString(),
             MetricLevel.CORE,
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 f262c33a8c..c80222089a 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
@@ -47,7 +47,7 @@ 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.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.sync.SyncService;
 import org.apache.iotdb.db.wal.WALManager;
 
@@ -141,7 +141,7 @@ public class IoTDB implements IoTDBMBean {
     setUncaughtExceptionHandler();
     initServiceProvider();
 
-    registerManager.register(MetricsService.getInstance());
+    registerManager.register(MetricService.getInstance());
     logger.info("recover the schema...");
     initConfigManager();
     registerManager.register(new JMXService());
@@ -197,7 +197,7 @@ public class IoTDB implements IoTDBMBean {
     registerManager.register(ContinuousQueryService.getInstance());
 
     // start reporter
-    MetricsService.getInstance().startAllReporter();
+    MetricService.getInstance().startAllReporter();
 
     logger.info("Congratulation, IoTDB is set up successfully. Now, enjoy yourself!");
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/NewIoTDB.java b/server/src/main/java/org/apache/iotdb/db/service/NewIoTDB.java
index a317ee9802..bddb750199 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/NewIoTDB.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/NewIoTDB.java
@@ -46,7 +46,7 @@ import org.apache.iotdb.db.mpp.execution.schedule.DriverScheduler;
 import org.apache.iotdb.db.protocol.mpprest.MPPRestService;
 import org.apache.iotdb.db.rescon.PrimitiveArrayManager;
 import org.apache.iotdb.db.rescon.SystemInfo;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.thrift.impl.ClientRPCServiceImpl;
 import org.apache.iotdb.db.sync.SyncService;
 import org.apache.iotdb.db.wal.WALManager;
@@ -120,7 +120,7 @@ public class NewIoTDB implements NewIoTDBMBean {
         .getConfig()
         .setRpcImplClassName(ClientRPCServiceImpl.class.getName());
 
-    registerManager.register(MetricsService.getInstance());
+    registerManager.register(MetricService.getInstance());
     logger.info("recover the schema...");
     initConfigManager();
     registerManager.register(new JMXService());
@@ -175,7 +175,7 @@ public class NewIoTDB implements NewIoTDBMBean {
     registerManager.register(ContinuousQueryService.getInstance());
 
     // start reporter
-    MetricsService.getInstance().startAllReporter();
+    MetricService.getInstance().startAllReporter();
 
     logger.info("Congratulation, IoTDB is set up successfully. Now, enjoy yourself!");
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/RPCService.java b/server/src/main/java/org/apache/iotdb/db/service/RPCService.java
index 841dc6c4c0..9011945bd3 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/RPCService.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/RPCService.java
@@ -26,7 +26,7 @@ import org.apache.iotdb.commons.service.ThriftService;
 import org.apache.iotdb.commons.service.ThriftServiceThread;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.service.thrift.ProcessorWithMetrics;
@@ -83,8 +83,7 @@ public class RPCService extends ThriftService implements RPCServiceMBean {
       throw new IllegalAccessException(e.getMessage());
     }
     thriftServiceThread.setName(ThreadName.RPC_SERVICE.getName());
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateAutoGauge(
             Metric.THRIFT_ACTIVE_THREADS.toString(),
             MetricLevel.CORE,
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricsService.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
similarity index 90%
rename from server/src/main/java/org/apache/iotdb/db/service/metrics/MetricsService.java
rename to server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
index 0f0886f62c..75dd84a77d 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricsService.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
@@ -27,23 +27,23 @@ import org.apache.iotdb.commons.service.ServiceType;
 import org.apache.iotdb.db.service.metrics.predefined.FileMetrics;
 import org.apache.iotdb.db.service.metrics.predefined.ProcessMetrics;
 import org.apache.iotdb.db.service.metrics.predefined.SystemMetrics;
-import org.apache.iotdb.metrics.MetricService;
+import org.apache.iotdb.metrics.AbstractMetricService;
 import org.apache.iotdb.metrics.config.ReloadLevel;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.predefined.jvm.JvmMetrics;
 import org.apache.iotdb.metrics.predefined.logback.LogbackMetrics;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class MetricsService extends MetricService implements MetricsServiceMBean, IService {
-  private static final Logger logger = LoggerFactory.getLogger(MetricsService.class);
+public class MetricService extends AbstractMetricService implements MetricServiceMBean, IService {
+  private static final Logger logger = LoggerFactory.getLogger(MetricService.class);
   private final String mbeanName =
       String.format(
           "%s:%s=%s", IoTDBConstant.IOTDB_PACKAGE, IoTDBConstant.JMX_TYPE, getID().getJmxName());
 
-  private MetricsService() {}
+  private MetricService() {}
 
   @Override
   public void start() throws StartupException {
@@ -77,7 +77,7 @@ public class MetricsService extends MetricService implements MetricsServiceMBean
   }
 
   @Override
-  public void enablePredefinedMetric(PredefinedMetric metric) {
+  public void enablePredefinedMetrics(PredefinedMetric metric) {
     IMetricSet metricSet;
     switch (metric) {
       case JVM:
@@ -143,16 +143,16 @@ public class MetricsService extends MetricService implements MetricsServiceMBean
 
   @Override
   public ServiceType getID() {
-    return ServiceType.METRICS_SERVICE;
+    return ServiceType.METRIC_SERVICE;
   }
 
-  public static MetricsService getInstance() {
+  public static MetricService getInstance() {
     return MetricsServiceHolder.INSTANCE;
   }
 
   private static class MetricsServiceHolder {
 
-    private static final MetricsService INSTANCE = new MetricsService();
+    private static final MetricService INSTANCE = new MetricService();
 
     private MetricsServiceHolder() {}
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricsServiceMBean.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricServiceMBean.java
similarity index 96%
rename from server/src/main/java/org/apache/iotdb/db/service/metrics/MetricsServiceMBean.java
rename to server/src/main/java/org/apache/iotdb/db/service/metrics/MetricServiceMBean.java
index 458f1e0d07..b65b5690d3 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricsServiceMBean.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricServiceMBean.java
@@ -20,7 +20,7 @@ package org.apache.iotdb.db.service.metrics;
 
 import org.apache.iotdb.commons.exception.StartupException;
 
-public interface MetricsServiceMBean {
+public interface MetricServiceMBean {
 
   void startService() throws StartupException;
 
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/FileMetrics.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/FileMetrics.java
index 3889dd7ac2..c2573ac5a8 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/FileMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/FileMetrics.java
@@ -26,11 +26,11 @@ import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.wal.WALManager;
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import java.io.File;
 import java.util.concurrent.Executors;
@@ -50,7 +50,7 @@ public class FileMetrics implements IMetricSet {
   private long unsequenceFileTotalCount = 0L;
 
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     metricManager.getOrCreateAutoGauge(
         Metric.FILE_SIZE.toString(),
         MetricLevel.IMPORTANT,
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/ProcessMetrics.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/ProcessMetrics.java
index 949a31b356..2ab82ee686 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/ProcessMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/ProcessMetrics.java
@@ -21,10 +21,10 @@ package org.apache.iotdb.db.service.metrics.predefined;
 
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import com.sun.management.OperatingSystemMXBean;
 
@@ -41,7 +41,7 @@ public class ProcessMetrics implements IMetricSet {
   }
 
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     collectProcessCPUInfo(metricManager);
     collectProcessMemInfo(metricManager);
     collectProcessStatusInfo(metricManager);
@@ -53,7 +53,7 @@ public class ProcessMetrics implements IMetricSet {
     return PredefinedMetric.PROCESS;
   }
 
-  private void collectProcessCPUInfo(MetricManager metricManager) {
+  private void collectProcessCPUInfo(AbstractMetricManager metricManager) {
     metricManager.getOrCreateAutoGauge(
         Metric.PROCESS_CPU_LOAD.toString(),
         MetricLevel.CORE,
@@ -71,7 +71,7 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
-  private void collectProcessMemInfo(MetricManager metricManager) {
+  private void collectProcessMemInfo(AbstractMetricManager metricManager) {
     Runtime runtime = Runtime.getRuntime();
     metricManager.getOrCreateAutoGauge(
         Metric.PROCESS_MAX_MEM.toString(),
@@ -110,7 +110,7 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
-  private void collectThreadInfo(MetricManager metricManager) {
+  private void collectThreadInfo(AbstractMetricManager metricManager) {
     metricManager.getOrCreateAutoGauge(
         Metric.PROCESS_THREADS_COUNT.toString(),
         MetricLevel.CORE,
@@ -120,7 +120,7 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
-  private void collectProcessStatusInfo(MetricManager metricManager) {
+  private void collectProcessStatusInfo(AbstractMetricManager metricManager) {
     metricManager.getOrCreateAutoGauge(
         Metric.PROCESS_STATUS.toString(),
         MetricLevel.CORE,
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/SystemMetrics.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/SystemMetrics.java
index 4a97ce47cc..b4f52a2515 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/SystemMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/predefined/SystemMetrics.java
@@ -21,11 +21,11 @@ package org.apache.iotdb.db.service.metrics.predefined;
 import org.apache.iotdb.commons.concurrent.threadpool.ScheduledExecutorUtil;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.MetricManager;
+import org.apache.iotdb.metrics.AbstractMetricManager;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.predefined.IMetricSet;
+import org.apache.iotdb.metrics.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
-import org.apache.iotdb.metrics.utils.PredefinedMetric;
 
 import com.sun.management.OperatingSystemMXBean;
 
@@ -46,7 +46,7 @@ public class SystemMetrics implements IMetricSet {
   }
 
   @Override
-  public void bindTo(MetricManager metricManager) {
+  public void bindTo(AbstractMetricManager metricManager) {
     collectSystemCpuInfo(metricManager);
     collectSystemDiskInfo(metricManager);
     collectSystemMEMInfo(metricManager);
@@ -57,7 +57,7 @@ public class SystemMetrics implements IMetricSet {
     return PredefinedMetric.SYSTEM;
   }
 
-  private void collectSystemCpuInfo(MetricManager metricManager) {
+  private void collectSystemCpuInfo(AbstractMetricManager metricManager) {
     metricManager.getOrCreateAutoGauge(
         Metric.SYS_CPU_LOAD.toString(),
         MetricLevel.CORE,
@@ -72,7 +72,7 @@ public class SystemMetrics implements IMetricSet {
         .set(osMXBean.getAvailableProcessors());
   }
 
-  private void collectSystemMEMInfo(MetricManager metricManager) {
+  private void collectSystemMEMInfo(AbstractMetricManager metricManager) {
     metricManager
         .getOrCreateGauge(
             Metric.SYS_TOTAL_PHYSICAL_MEMORY_SIZE.toString(),
@@ -110,7 +110,7 @@ public class SystemMetrics implements IMetricSet {
         "system");
   }
 
-  private void collectSystemDiskInfo(MetricManager metricManager) {
+  private void collectSystemDiskInfo(AbstractMetricManager metricManager) {
     metricManager.getOrCreateAutoGauge(
         Metric.SYS_DISK_TOTAL_SPACE.toString(),
         MetricLevel.CORE,
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CacheMetricsRecorder.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CacheMetricsRecorder.java
index 1c1a0ccda6..432f44b3b2 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CacheMetricsRecorder.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CacheMetricsRecorder.java
@@ -18,17 +18,13 @@
  */
 package org.apache.iotdb.db.service.metrics.recorder;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 
 public class CacheMetricsRecorder {
 
-  private static final boolean ENABLE_METRIC =
-      MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric();
-
   /**
    * record the result of cache
    *
@@ -36,22 +32,9 @@ public class CacheMetricsRecorder {
    * @param name the name of object that cached
    */
   public static void record(boolean result, String name) {
-    if (ENABLE_METRIC) {
-      if (result) {
-        // cache hit
-        MetricsService.getInstance()
-            .getMetricManager()
-            .count(
-                1,
-                Metric.CACHE.toString(),
-                MetricLevel.IMPORTANT,
-                Tag.NAME.toString(),
-                name,
-                Tag.TYPE.toString(),
-                "hit");
-      }
-      MetricsService.getInstance()
-          .getMetricManager()
+    if (result) {
+      // cache hit
+      MetricService.getInstance()
           .count(
               1,
               Metric.CACHE.toString(),
@@ -59,7 +42,16 @@ public class CacheMetricsRecorder {
               Tag.NAME.toString(),
               name,
               Tag.TYPE.toString(),
-              "all");
+              "hit");
     }
+    MetricService.getInstance()
+        .count(
+            1,
+            Metric.CACHE.toString(),
+            MetricLevel.IMPORTANT,
+            Tag.NAME.toString(),
+            name,
+            Tag.TYPE.toString(),
+            "all");
   }
 }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CompactionMetricsRecorder.java b/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CompactionMetricsRecorder.java
index b9482f2ff5..30d5178efd 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CompactionMetricsRecorder.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/metrics/recorder/CompactionMetricsRecorder.java
@@ -24,29 +24,21 @@ import org.apache.iotdb.db.engine.compaction.constant.ProcessChunkType;
 import org.apache.iotdb.db.engine.compaction.cross.CrossSpaceCompactionTask;
 import org.apache.iotdb.db.engine.compaction.inner.InnerSpaceCompactionTask;
 import org.apache.iotdb.db.engine.compaction.task.AbstractCompactionTask;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 
 import java.util.concurrent.TimeUnit;
 
 public class CompactionMetricsRecorder {
 
-  private static final boolean ENABLE_METRIC =
-      MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric();
-
   public static void recordWriteInfo(
       CompactionType compactionType,
       ProcessChunkType processChunkType,
       boolean aligned,
       long byteNum) {
-    if (!ENABLE_METRIC) {
-      return;
-    }
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .count(
             byteNum / 1024L,
             Metric.DATA_WRITTEN.toString(),
@@ -59,8 +51,7 @@ public class CompactionMetricsRecorder {
             aligned ? "ALIGNED" : "NOT_ALIGNED",
             Tag.TYPE.toString(),
             processChunkType.toString());
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .count(
             byteNum / 1024L,
             Metric.DATA_WRITTEN.toString(),
@@ -72,11 +63,7 @@ public class CompactionMetricsRecorder {
   }
 
   public static void recordReadInfo(long byteNum) {
-    if (!ENABLE_METRIC) {
-      return;
-    }
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .count(
             byteNum,
             Metric.DATA_READ.toString(),
@@ -87,9 +74,6 @@ public class CompactionMetricsRecorder {
 
   public static void recordTaskInfo(
       AbstractCompactionTask task, CompactionTaskStatus status, int size) {
-    if (!ENABLE_METRIC) {
-      return;
-    }
     String taskType = "unknown";
     boolean isInnerTask = false;
     if (task instanceof InnerSpaceCompactionTask) {
@@ -102,8 +86,7 @@ public class CompactionMetricsRecorder {
     switch (status) {
       case ADD_TO_QUEUE:
       case POLL_FROM_QUEUE:
-        MetricsService.getInstance()
-            .getMetricManager()
+        MetricService.getInstance()
             .getOrCreateGauge(
                 Metric.QUEUE.toString(),
                 MetricLevel.IMPORTANT,
@@ -114,8 +97,7 @@ public class CompactionMetricsRecorder {
             .set(size);
         break;
       case READY_TO_EXECUTE:
-        MetricsService.getInstance()
-            .getMetricManager()
+        MetricService.getInstance()
             .getOrCreateGauge(
                 Metric.QUEUE.toString(),
                 MetricLevel.IMPORTANT,
@@ -126,8 +108,7 @@ public class CompactionMetricsRecorder {
             .set(size);
         break;
       case FINISHED:
-        MetricsService.getInstance()
-            .getMetricManager()
+        MetricService.getInstance()
             .getOrCreateGauge(
                 Metric.QUEUE.toString(),
                 MetricLevel.IMPORTANT,
@@ -136,8 +117,7 @@ public class CompactionMetricsRecorder {
                 Tag.STATUS.toString(),
                 "running")
             .set(size);
-        MetricsService.getInstance()
-            .getMetricManager()
+        MetricService.getInstance()
             .timer(
                 task.getTimeCost(),
                 TimeUnit.MILLISECONDS,
@@ -146,8 +126,7 @@ public class CompactionMetricsRecorder {
                 Tag.NAME.toString(),
                 isInnerTask ? "inner_compaction" : "cross_compaction");
         if (isInnerTask) {
-          MetricsService.getInstance()
-              .getMetricManager()
+          MetricService.getInstance()
               .count(
                   1,
                   Metric.COMPACTION_TASK_COUNT.toString(),
@@ -157,8 +136,7 @@ public class CompactionMetricsRecorder {
                   Tag.TYPE.toString(),
                   ((InnerSpaceCompactionTask) task).isSequence() ? "sequence" : "unsequence");
         } else {
-          MetricsService.getInstance()
-              .getMetricManager()
+          MetricService.getInstance()
               .count(
                   1,
                   Metric.COMPACTION_TASK_COUNT.toString(),
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/ProcessorWithMetrics.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/ProcessorWithMetrics.java
index dda3cb1a4b..3b3e671068 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/ProcessorWithMetrics.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/ProcessorWithMetrics.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.db.service.thrift;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -64,8 +64,7 @@ public class ProcessorWithMetrics extends Processor {
       fn.process(msg.seqid, in, out, iface);
     }
     long cost = System.currentTimeMillis() - startTime;
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .timer(
             cost,
             TimeUnit.MILLISECONDS,
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/InternalServiceThriftHandler.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/InternalServiceThriftHandler.java
index 09e9d7492f..65ac4d0f0b 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/InternalServiceThriftHandler.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/InternalServiceThriftHandler.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.db.service.thrift.handler;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -36,8 +36,7 @@ public class InternalServiceThriftHandler implements TServerEventHandler {
 
   @Override
   public ServerContext createContext(TProtocol tProtocol, TProtocol tProtocol1) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(), MetricLevel.CORE, Tag.NAME.toString(), "Internal")
         .incr(1L);
@@ -47,8 +46,7 @@ public class InternalServiceThriftHandler implements TServerEventHandler {
   @Override
   public void deleteContext(
       ServerContext serverContext, TProtocol tProtocol, TProtocol tProtocol1) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(), MetricLevel.CORE, Tag.NAME.toString(), "Internal")
         .decr(1L);
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandler.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandler.java
index 4ad2e5b728..8938fe16d8 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandler.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandler.java
@@ -16,7 +16,7 @@
  */
 package org.apache.iotdb.db.service.thrift.handler;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.service.thrift.impl.IClientRPCServiceWithHandler;
@@ -37,8 +37,7 @@ public class RPCServiceThriftHandler implements TServerEventHandler {
 
   @Override
   public ServerContext createContext(TProtocol arg0, TProtocol arg1) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(), MetricLevel.CORE, Tag.NAME.toString(), "RPC")
         .incr(1L);
@@ -50,8 +49,7 @@ public class RPCServiceThriftHandler implements TServerEventHandler {
     // release query resources.
     eventHandler.handleClientExit();
 
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(), MetricLevel.CORE, Tag.NAME.toString(), "RPC")
         .decr(1L);
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java
index 47198217c9..3377225280 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/ClientRPCServiceImpl.java
@@ -57,7 +57,7 @@ import org.apache.iotdb.db.mpp.plan.statement.metadata.template.SetSchemaTemplat
 import org.apache.iotdb.db.query.control.SessionManager;
 import org.apache.iotdb.db.query.control.SessionTimeoutManager;
 import org.apache.iotdb.db.service.basic.BasicOpenSessionResp;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Operation;
 import org.apache.iotdb.db.utils.QueryDataSetUtils;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
@@ -1531,16 +1531,14 @@ public class ClientRPCServiceImpl implements IClientRPCServiceWithHandler {
   /** Add stat of operation into metrics */
   private void addOperationLatency(Operation operation, long startTime) {
     if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnablePerformanceStat()) {
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .histogram(
               System.currentTimeMillis() - startTime,
               "operation_histogram",
               MetricLevel.IMPORTANT,
               "name",
               operation.getName());
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .count(1, "operation_count", MetricLevel.IMPORTANT, "name", operation.getName());
     }
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeInternalRPCServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeInternalRPCServiceImpl.java
index 074a505f59..548b594864 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeInternalRPCServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/DataNodeInternalRPCServiceImpl.java
@@ -68,7 +68,7 @@ import org.apache.iotdb.db.mpp.plan.planner.plan.node.PlanNodeType;
 import org.apache.iotdb.db.mpp.plan.planner.plan.node.write.InsertNode;
 import org.apache.iotdb.db.service.DataNode;
 import org.apache.iotdb.db.service.RegionMigrateService;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
@@ -394,8 +394,7 @@ public class DataNodeInternalRPCServiceImpl implements IDataNodeRPCService.Iface
     if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()
         && req.isNeedSamplingLoad()) {
       long cpuLoad =
-          MetricsService.getInstance()
-              .getMetricManager()
+          MetricService.getInstance()
               .getOrCreateGauge(
                   Metric.SYS_CPU_LOAD.toString(), MetricLevel.CORE, Tag.NAME.toString(), "system")
               .value();
@@ -456,15 +455,13 @@ public class DataNodeInternalRPCServiceImpl implements IDataNodeRPCService.Iface
 
       for (String id : heapIds) {
         Gauge gauge =
-            MetricsService.getInstance()
-                .getMetricManager()
+            MetricService.getInstance()
                 .getOrCreateGauge(gaugeName, MetricLevel.IMPORTANT, "id", id, "area", "heap");
         result += gauge.value();
       }
       for (String id : noHeapIds) {
         Gauge gauge =
-            MetricsService.getInstance()
-                .getMetricManager()
+            MetricService.getInstance()
                 .getOrCreateGauge(gaugeName, MetricLevel.IMPORTANT, "id", id, "area", "noheap");
         result += gauge.value();
       }
diff --git a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java
index 77f101207e..b32a23c28e 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/thrift/impl/TSServiceImpl.java
@@ -72,7 +72,7 @@ import org.apache.iotdb.db.service.IoTDB;
 import org.apache.iotdb.db.service.StaticResps;
 import org.apache.iotdb.db.service.basic.BasicOpenSessionResp;
 import org.apache.iotdb.db.service.basic.ServiceProvider;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Operation;
 import org.apache.iotdb.db.tools.watermark.GroupedLSBWatermarkEncoder;
 import org.apache.iotdb.db.tools.watermark.WatermarkEncoder;
@@ -2122,16 +2122,14 @@ public class TSServiceImpl implements IClientRPCServiceWithHandler {
   /** Add stat of operation into metrics */
   private void addOperationLatency(Operation operation, long startTime) {
     if (MetricConfigDescriptor.getInstance().getMetricConfig().getEnablePerformanceStat()) {
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .histogram(
               System.currentTimeMillis() - startTime,
               "operation_histogram",
               MetricLevel.IMPORTANT,
               "name",
               operation.getName());
-      MetricsService.getInstance()
-          .getMetricManager()
+      MetricService.getInstance()
           .count(1, "operation_count", MetricLevel.IMPORTANT, "name", operation.getName());
     }
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerManager.java b/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerManager.java
index 05c8ce1dc7..c0663f8d13 100644
--- a/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerManager.java
@@ -28,7 +28,7 @@ import org.apache.iotdb.commons.service.ThriftServiceThread;
 import org.apache.iotdb.commons.utils.TestOnly;
 import org.apache.iotdb.db.conf.IoTDBConfig;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -89,8 +89,7 @@ public class TransportServerManager extends ThriftService
             new TransportServerThriftHandler(serviceImpl),
             config.isRpcThriftCompressionEnable());
     thriftServiceThread.setName(ThreadName.SYNC_SERVER.getName());
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateAutoGauge(
             Metric.THRIFT_ACTIVE_THREADS.toString(),
             MetricLevel.CORE,
diff --git a/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerThriftHandler.java b/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerThriftHandler.java
index 36d325156b..1045a71c6b 100644
--- a/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerThriftHandler.java
+++ b/server/src/main/java/org/apache/iotdb/db/sync/transport/server/TransportServerThriftHandler.java
@@ -19,7 +19,7 @@
  */
 package org.apache.iotdb.db.sync.transport.server;
 
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.metrics.utils.MetricLevel;
@@ -42,8 +42,7 @@ public class TransportServerThriftHandler implements TServerEventHandler {
 
   @Override
   public ServerContext createContext(TProtocol input, TProtocol output) {
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(),
             MetricLevel.CORE,
@@ -57,8 +56,7 @@ public class TransportServerThriftHandler implements TServerEventHandler {
   public void deleteContext(ServerContext serverContext, TProtocol input, TProtocol output) {
     // release query resources.
     serviceImpl.handleClientExit();
-    MetricsService.getInstance()
-        .getMetricManager()
+    MetricService.getInstance()
         .getOrCreateGauge(
             Metric.THRIFT_CONNECTIONS.toString(),
             MetricLevel.CORE,
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
new file mode 100644
index 0000000000..f1bca32b99
--- /dev/null
+++ b/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
@@ -0,0 +1,276 @@
+/*
+ * 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.metric;
+
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.DoNothingMetricService;
+import org.apache.iotdb.metrics.config.MetricConfig;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.impl.DoNothingMetricManager;
+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.Rate;
+import org.apache.iotdb.metrics.type.Timer;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+import org.apache.iotdb.metrics.utils.MonitorType;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+public class MetricServiceTest {
+
+  private static final MetricConfig metricConfig =
+      MetricConfigDescriptor.getInstance().getMetricConfig();
+  private static AbstractMetricService metricService = new DoNothingMetricService();
+
+  @Test
+  public void testMetricService() {
+    for (MonitorType type : MonitorType.values()) {
+      // init metric service
+      metricConfig.setEnableMetric(true);
+      metricConfig.setMonitorType(type);
+      metricConfig.setMetricLevel(MetricLevel.IMPORTANT);
+      metricService = new DoNothingMetricService();
+      metricService.startService();
+      metricService.startAllReporter();
+
+      // test metric service
+      assertTrue(metricService.isEnable());
+      assertTrue(metricService.getMetricManager().isEnableMetric());
+      assertTrue(metricService.getMetricManager().isEnableMetricInGivenLevel(MetricLevel.CORE));
+      assertTrue(
+          metricService.getMetricManager().isEnableMetricInGivenLevel(MetricLevel.IMPORTANT));
+      assertFalse(metricService.getMetricManager().isEnableMetricInGivenLevel(MetricLevel.NORMAL));
+      assertFalse(metricService.getMetricManager().isEnableMetricInGivenLevel(MetricLevel.ALL));
+
+      testNormalSituation();
+
+      testOtherSituation();
+
+      // stop metric module
+      metricService.stopService();
+    }
+  }
+
+  private void testNormalSituation() {
+    // test counter
+    Counter counter1 =
+        metricService.getOrCreateCounter("counter1", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(counter1);
+    metricService.count(10, "counter1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(10, counter1.count());
+    metricService.count(20, "counter1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(30, counter1.count());
+    Counter counter2 =
+        metricService.getOrCreateCounter("counter1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(counter1, counter2);
+    counter2 = metricService.getOrCreateCounter("counter2", MetricLevel.IMPORTANT);
+    assertNotEquals(counter1, counter2);
+    counter2 = metricService.getOrCreateCounter("counter3", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotEquals(counter1, counter2);
+    counter2 =
+        metricService.getOrCreateCounter(
+            "counter4", MetricLevel.IMPORTANT, "tag", "value", "tag2", "value");
+    assertNotEquals(counter1, counter2);
+    counter2 = metricService.getOrCreateCounter("counter5", MetricLevel.NORMAL, "tag", "value");
+    assertEquals(DoNothingMetricManager.doNothingCounter, counter2);
+    assertEquals(4, metricService.getAllCounters().size());
+    metricService.count(10, "counter6", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, metricService.getAllCounters().size());
+    metricService.remove(MetricType.COUNTER, "counter6");
+    assertEquals(5, metricService.getAllCounters().size());
+    metricService.remove(MetricType.COUNTER, "counter6", "tag", "value");
+    assertEquals(4, metricService.getAllCounters().size());
+    assertEquals(4, metricService.getAllMetricKeys().size());
+
+    // test gauge
+    Gauge gauge1 = metricService.getOrCreateGauge("gauge1", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(gauge1);
+    metricService.gauge(10, "gauge1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(10, gauge1.value());
+    Gauge gauge2 = metricService.getOrCreateGauge("gauge1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(gauge1, gauge2);
+    gauge2 = metricService.getOrCreateGauge("gauge2", MetricLevel.IMPORTANT);
+    assertNotEquals(gauge1, gauge2);
+    gauge2 = metricService.getOrCreateGauge("gauge3", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotEquals(gauge1, gauge2);
+    gauge2 =
+        metricService.getOrCreateGauge(
+            "gauge4", MetricLevel.IMPORTANT, "tag", "value", "tag2", "value");
+    assertNotEquals(gauge1, gauge2);
+    gauge2 = metricService.getOrCreateGauge("gauge5", MetricLevel.NORMAL, "tag", "value");
+    assertEquals(DoNothingMetricManager.doNothingGauge, gauge2);
+    assertEquals(4, metricService.getAllGauges().size());
+    metricService.gauge(10, "gauge6", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, metricService.getAllGauges().size());
+    metricService.remove(MetricType.GAUGE, "gauge6");
+    assertEquals(5, metricService.getAllGauges().size());
+    metricService.remove(MetricType.GAUGE, "gauge6", "tag", "value");
+    assertEquals(4, metricService.getAllGauges().size());
+    assertEquals(8, metricService.getAllMetricKeys().size());
+
+    // test auto gauge
+    List<Integer> list = new ArrayList<>();
+    Gauge autoGauge =
+        metricService.getOrCreateAutoGauge(
+            "autoGauge", MetricLevel.IMPORTANT, list, List::size, "tag", "value");
+    assertEquals(0L, autoGauge.value());
+    list.add(1);
+    assertEquals(1L, autoGauge.value());
+    list.clear();
+    assertEquals(0L, autoGauge.value());
+    list.add(1);
+    assertEquals(1L, autoGauge.value());
+    list = null;
+    System.gc();
+    assertEquals(0L, autoGauge.value());
+    assertEquals(5, metricService.getAllGauges().size());
+    metricService.remove(MetricType.GAUGE, "autoGauge", "tag", "value");
+    assertEquals(4, metricService.getAllGauges().size());
+    assertEquals(8, metricService.getAllMetricKeys().size());
+
+    // test rate
+    Rate rate1 = metricService.getOrCreateRate("rate1", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(rate1);
+    metricService.rate(10, "rate1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(10, rate1.getCount());
+    metricService.rate(20, "rate1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(30, rate1.getCount());
+    Rate rate2 = metricService.getOrCreateRate("rate1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(rate1, rate2);
+    rate2 = metricService.getOrCreateRate("rate2", MetricLevel.IMPORTANT);
+    assertNotEquals(rate1, rate2);
+    rate2 = metricService.getOrCreateRate("rate3", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotEquals(rate1, rate2);
+    rate2 =
+        metricService.getOrCreateRate(
+            "rate4", MetricLevel.IMPORTANT, "tag", "value", "tag2", "value");
+    assertNotEquals(rate1, rate2);
+    rate2 = metricService.getOrCreateRate("rate5", MetricLevel.NORMAL, "tag", "value");
+    assertEquals(4, metricService.getAllRates().size());
+    assertEquals(DoNothingMetricManager.doNothingRate, rate2);
+    metricService.rate(10, "rate6", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, metricService.getAllRates().size());
+    metricService.remove(MetricType.RATE, "rate6");
+    assertEquals(5, metricService.getAllRates().size());
+    metricService.remove(MetricType.RATE, "rate6", "tag", "value");
+    assertEquals(4, metricService.getAllRates().size());
+    assertEquals(12, metricService.getAllMetricKeys().size());
+
+    // test histogram
+    Histogram histogram1 =
+        metricService.getOrCreateHistogram("histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(histogram1);
+    metricService.histogram(10, "histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.histogram(20, "histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.histogram(30, "histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.histogram(40, "histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.histogram(50, "histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, histogram1.count());
+    assertEquals(5, histogram1.takeSnapshot().size());
+    assertEquals(10, histogram1.takeSnapshot().getMin());
+    assertEquals(50, histogram1.takeSnapshot().getMax());
+    Histogram histogram2 =
+        metricService.getOrCreateHistogram("histogram1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(histogram1, histogram2);
+    histogram2 = metricService.getOrCreateHistogram("histogram2", MetricLevel.IMPORTANT);
+    assertNotEquals(histogram1, histogram2);
+    histogram2 =
+        metricService.getOrCreateHistogram("histogram3", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotEquals(histogram1, histogram2);
+    histogram2 =
+        metricService.getOrCreateHistogram(
+            "histogram4", MetricLevel.IMPORTANT, "tag", "value", "tag2", "value");
+    assertNotEquals(histogram1, histogram2);
+    histogram2 =
+        metricService.getOrCreateHistogram("histogram5", MetricLevel.NORMAL, "tag", "value");
+    assertEquals(DoNothingMetricManager.doNothingHistogram, histogram2);
+    assertEquals(4, metricService.getAllHistograms().size());
+    metricService.histogram(10, "histogram6", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, metricService.getAllHistograms().size());
+    metricService.remove(MetricType.HISTOGRAM, "histogram6");
+    assertEquals(5, metricService.getAllHistograms().size());
+    metricService.remove(MetricType.HISTOGRAM, "histogram6", "tag", "value");
+    assertEquals(4, metricService.getAllHistograms().size());
+    assertEquals(16, metricService.getAllMetricKeys().size());
+
+    // test timer
+    Timer timer1 = metricService.getOrCreateTimer("timer1", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(timer1);
+    metricService.timer(2, TimeUnit.MINUTES, "timer1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.timer(4, TimeUnit.MINUTES, "timer1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.timer(6, TimeUnit.MINUTES, "timer1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.timer(8, TimeUnit.MINUTES, "timer1", MetricLevel.IMPORTANT, "tag", "value");
+    metricService.timer(10, TimeUnit.MINUTES, "timer1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, timer1.getImmutableRate().getCount());
+    assertEquals(5, timer1.takeSnapshot().size());
+    Timer timer2 = metricService.getOrCreateTimer("timer1", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(timer1, timer2);
+    timer2 = metricService.getOrCreateTimer("timer2", MetricLevel.IMPORTANT);
+    assertNotEquals(timer1, timer2);
+    timer2 = metricService.getOrCreateTimer("timer3", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotEquals(timer1, timer2);
+    timer2 =
+        metricService.getOrCreateTimer(
+            "timer4", MetricLevel.IMPORTANT, "tag", "value", "tag2", "value");
+    assertNotEquals(timer1, timer2);
+    timer2 = metricService.getOrCreateTimer("timer5", MetricLevel.NORMAL, "tag", "value");
+    assertNotEquals(timer1, timer2);
+    assertEquals(4, metricService.getAllTimers().size());
+    metricService.timer(10, TimeUnit.MILLISECONDS, "timer6", MetricLevel.IMPORTANT, "tag", "value");
+    assertEquals(5, metricService.getAllTimers().size());
+    metricService.remove(MetricType.TIMER, "timer6");
+    assertEquals(5, metricService.getAllTimers().size());
+    metricService.remove(MetricType.TIMER, "timer6", "tag", "value");
+    assertEquals(4, metricService.getAllTimers().size());
+    assertEquals(20, metricService.getAllMetricKeys().size());
+  }
+
+  private void testOtherSituation() {
+    assertThrows(IllegalArgumentException.class, this::getOrCreateDifferentMetricsWithSameName);
+
+    Timer timer =
+        metricService.getOrCreateTimer("same_name", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(timer);
+    assertNotEquals(DoNothingMetricManager.doNothingTimer, timer);
+    Counter counter = metricService.getOrCreateCounter("same_name", MetricLevel.IMPORTANT);
+    assertNotNull(counter);
+    assertEquals(DoNothingMetricManager.doNothingCounter, counter);
+  }
+
+  private void getOrCreateDifferentMetricsWithSameName() {
+    Timer timer =
+        metricService.getOrCreateTimer("same_name", MetricLevel.IMPORTANT, "tag", "value");
+    assertNotNull(timer);
+    metricService.getOrCreateCounter("same_name", MetricLevel.IMPORTANT, "tag", "value");
+  }
+}
diff --git a/server/src/test/resources/logback-test.xml b/server/src/test/resources/logback-test.xml
index 00b88bfe95..4b03f9ba91 100644
--- a/server/src/test/resources/logback-test.xml
+++ b/server/src/test/resources/logback-test.xml
@@ -45,7 +45,7 @@
     <logger name="org.apache.iotdb.db.metadata" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.ThriftServiceThread" level="INFO"/>
     <logger name="org.eclipse.jetty.util.thread.QueuedThreadPool" level="INFO"/>
-    <logger name="org.apache.iotdb.db.service.metrics.MetricsService" level="INFO"/>
+    <logger name="org.apache.iotdb.db.service.metrics.MetricService" level="INFO"/>
     <logger name="org.apache.iotdb.db.engine.flush.FlushManager" level="INFO"/>
     <logger name="org.apache.iotdb.db.integration.IoTDBCompactionIT" level="INFO"/>
     <logger name="org.apache.iotdb.commons.service.RegisterManager" level="INFO"/>
diff --git a/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java b/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
index 3f30db9fdb..fcd9886ed0 100644
--- a/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
+++ b/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
@@ -43,7 +43,7 @@ import org.apache.iotdb.db.query.context.QueryContext;
 import org.apache.iotdb.db.query.control.FileReaderManager;
 import org.apache.iotdb.db.query.control.QueryResourceManager;
 import org.apache.iotdb.db.service.IoTDB;
-import org.apache.iotdb.db.service.metrics.MetricsService;
+import org.apache.iotdb.db.service.metrics.MetricService;
 import org.apache.iotdb.db.wal.WALManager;
 import org.apache.iotdb.jdbc.Config;
 import org.junit.Assert;
@@ -123,7 +123,7 @@ public class EnvironmentUtils {
     }
     // close metadata
     IoTDB.configManager.clear();
-    MetricsService.getInstance().stop();
+    MetricService.getInstance().stop();
     // delete all directory
     cleanAllDir();