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

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


The following commit(s) were added to refs/heads/rel/0.13 by this push:
     new 917f10eaee [To rel/0.13][IOTDB-3988][IOTDB-3733] Fix reload problem of 
metric module, and refactor metric module. (#7382)
917f10eaee is described below

commit 917f10eaee6901e7ca10193ba309477931322427
Author: ZhangHongYin <[email protected]>
AuthorDate: Wed Sep 28 15:48:04 2022 +0800

    [To rel/0.13][IOTDB-3988][IOTDB-3733] Fix reload problem of metric module, 
and refactor metric module. (#7382)
---
 .../log/manage/PartitionedSnapshotLogManager.java  |   1 +
 .../reporter/DropwizardPrometheusReporter.java     |   6 +-
 .../iotdb/metrics/AbstractMetricService.java       |  67 ++++--
 .../iotdb/metrics/DoNothingMetricService.java      |   2 +-
 .../apache/iotdb/metrics/config/MetricConfig.java  |   2 +-
 .../{predefined => metricsets}/IMetricSet.java     |  19 +-
 .../predefined/PredefinedMetric.java               |   2 +-
 .../predefined/jvm/JvmClassLoaderMetrics.java      |  20 +-
 .../predefined/jvm/JvmCompileMetrics.java          |  20 +-
 .../predefined/jvm/JvmGcMetrics.java               | 117 +++++++---
 .../predefined/jvm/JvmMemoryMetrics.java           |  55 +++--
 .../metricsets/predefined/jvm/JvmMetrics.java      |  52 +++++
 .../predefined/jvm/JvmThreadMetrics.java           |  37 ++-
 .../{ => metricsets}/predefined/jvm/JvmUtils.java  |   2 +-
 .../predefined/logback/LogbackMetrics.java         | 104 +++++++++
 .../predefined/logback/MetricsTurboFilter.java     |  98 ++++++++
 .../iotdb/metrics/predefined/jvm/JvmMetrics.java   |  49 ----
 .../metrics/predefined/logback/LogbackMetrics.java | 181 ---------------
 .../reporter/MicrometerPrometheusReporter.java     |   8 +-
 .../apache/iotdb/db/engine/cache/ChunkCache.java   |  19 +-
 .../iotdb/db/engine/cache/ChunkCacheMetrics.java   |  67 ++++++
 .../db/engine/cache/TimeSeriesMetadataCache.java   |  39 +---
 .../cache/TimeSeriesMetadataCacheMetrics.java      |  76 +++++++
 .../apache/iotdb/db/engine/flush/FlushManager.java |  34 +--
 .../iotdb/db/engine/flush/FlushManagerMBean.java   |   2 +
 .../iotdb/db/engine/flush/FlushManagerMetrics.java |  90 ++++++++
 .../engine/storagegroup/TsFileProcessorInfo.java   |  41 +---
 .../storagegroup/TsFileProcessorInfoMetrics.java   |  75 ++++++
 .../storagegroup/VirtualStorageGroupProcessor.java |  19 +-
 .../VirtualStorageGroupProcessorMetrics.java       |  56 +++++
 .../org/apache/iotdb/db/metadata/MManager.java     | 105 +++------
 .../apache/iotdb/db/metadata/MManagerMetrics.java  | 134 +++++++++++
 .../db/query/pool/RawQueryReadTaskPoolManager.java |  35 +--
 .../pool/RawQueryReadTaskPoolManagerMetrics.java   |  92 ++++++++
 .../java/org/apache/iotdb/db/service/IoTDB.java    |   5 +-
 .../iotdb/db/service/metrics/MetricService.java    |  29 ++-
 .../db/service/metrics/predefined/FileMetrics.java | 252 +++++++++++++++------
 .../service/metrics/predefined/ProcessMetrics.java |  80 +++++--
 .../service/metrics/predefined/SystemMetrics.java  | 137 ++++++++---
 .../thrift/handler/RPCServiceThriftHandler.java    |  18 +-
 .../handler/RPCServiceThriftHandlerMetrics.java    |  68 ++++++
 .../apache/iotdb/db/metric/MetricServiceTest.java  |   1 -
 42 files changed, 1600 insertions(+), 716 deletions(-)

diff --git 
a/cluster/src/main/java/org/apache/iotdb/cluster/log/manage/PartitionedSnapshotLogManager.java
 
b/cluster/src/main/java/org/apache/iotdb/cluster/log/manage/PartitionedSnapshotLogManager.java
index 95172dce53..f20bce34cb 100644
--- 
a/cluster/src/main/java/org/apache/iotdb/cluster/log/manage/PartitionedSnapshotLogManager.java
+++ 
b/cluster/src/main/java/org/apache/iotdb/cluster/log/manage/PartitionedSnapshotLogManager.java
@@ -84,6 +84,7 @@ public abstract class PartitionedSnapshotLogManager<T extends 
Snapshot> extends
     this.dataGroupMember = dataGroupMember;
 
     if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
+      // No need to move into IMetricSet because old cluster is removed in 
0.14.0+
       MetricService.getInstance()
           .getOrCreateAutoGauge(
               Metric.CLUSTER_UNCOMMITTED_LOG.toString(),
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 4706dc0fa0..bbb98faa79 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
@@ -27,6 +27,8 @@ import org.apache.iotdb.metrics.utils.ReporterType;
 
 import com.codahale.metrics.MetricRegistry;
 import io.netty.channel.ChannelOption;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import reactor.core.publisher.Mono;
@@ -36,7 +38,6 @@ import reactor.netty.http.server.HttpServer;
 import java.io.IOException;
 import java.io.StringWriter;
 import java.io.Writer;
-import java.time.Duration;
 
 public class DropwizardPrometheusReporter implements Reporter {
   private static final Logger LOGGER = 
LoggerFactory.getLogger(DropwizardPrometheusReporter.class);
@@ -47,14 +48,13 @@ public class DropwizardPrometheusReporter implements 
Reporter {
   @Override
   public boolean start() {
     if (httpServer != null) {
-      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)
+            .channelGroup(new 
DefaultChannelGroup(GlobalEventExecutor.INSTANCE))
             .port(port)
             .route(
                 routes ->
diff --git 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
index f00d7f1c4a..bd610bc3fc 100644
--- 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/AbstractMetricService.java
@@ -23,8 +23,8 @@ 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.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.reporter.CompositeReporter;
 import org.apache.iotdb.metrics.reporter.Reporter;
 import org.apache.iotdb.metrics.type.Counter;
@@ -44,7 +44,6 @@ 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. */
@@ -53,8 +52,6 @@ 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 */
@@ -68,31 +65,53 @@ public abstract class AbstractMetricService {
 
   /** start metric service */
   public void startService() {
+    startCoreModule();
+    for (IMetricSet metricSet : metricSets) {
+      metricSet.bindTo(this);
+    }
+  }
+
+  /** restart metric service */
+  public void restartService() {
+    logger.info("Restart Core Module");
+    stopCoreModule();
+    startCoreModule();
+    for (IMetricSet metricSet : metricSets) {
+      logger.info("Restart metricSet: {}", metricSet.getClass().getName());
+      metricSet.unbindFrom(this);
+      metricSet.bindTo(this);
+    }
+  }
+
+  /** stop metric service */
+  public void stopService() {
+    for (IMetricSet metricSet : metricSets) {
+      metricSet.unbindFrom(this);
+    }
+    stopCoreModule();
+  }
+
+  /** start metric core module */
+  private void startCoreModule() {
     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();
-    }
+    startAllReporter();
+    logger.info("Start predefined metrics: {}", 
metricConfig.getPredefinedMetrics());
     for (PredefinedMetric predefinedMetric : 
metricConfig.getPredefinedMetrics()) {
       enablePredefinedMetrics(predefinedMetric);
     }
-    logger.info("Start predefined metrics: {}", 
metricConfig.getPredefinedMetrics());
   }
 
-  /** stop metric service */
-  public void stopService() {
-    compositeReporter.stopAll();
+  /** stop metric core module */
+  private void stopCoreModule() {
+    stopAllReporter();
     metricManager.stop();
     metricManager = new DoNothingMetricManager();
     compositeReporter = new CompositeReporter();
-    for (IMetricSet metricSet : metricSets) {
-      metricSet.stopAsyncCollectedMetrics();
-    }
-    metricSets = new ArrayList<>();
   }
 
   /** Load metric manager according to configuration */
@@ -156,6 +175,14 @@ public abstract class AbstractMetricService {
     compositeReporter.startAll();
   }
 
+  /** Stop all reporters */
+  public void stopAllReporter() {
+    if (!isEnable()) {
+      return;
+    }
+    compositeReporter.stopAll();
+  }
+
   /** Start reporter according to type */
   public void start(ReporterType type) {
     if (!isEnable()) {
@@ -259,4 +286,12 @@ public abstract class AbstractMetricService {
   public boolean isEnable() {
     return isEnableMetric;
   }
+
+  /** bind metrics and store metric set */
+  public void addMetricSet(IMetricSet metricSet) {
+    if (!metricSets.contains(metricSet)) {
+      metricSet.bindTo(this);
+      metricSets.add(metricSet);
+    }
+  }
 }
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 8f07e299fb..b6e4baf066 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,7 +20,7 @@
 package org.apache.iotdb.metrics;
 
 import org.apache.iotdb.metrics.config.ReloadLevel;
-import org.apache.iotdb.metrics.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
 
 public class DoNothingMetricService extends AbstractMetricService {
 
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 162fda6f4d..1b5a625b8f 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,7 +19,7 @@
 
 package org.apache.iotdb.metrics.config;
 
-import org.apache.iotdb.metrics.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
 import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.metrics.utils.MonitorType;
 import org.apache.iotdb.metrics.utils.ReporterType;
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/metricsets/IMetricSet.java
similarity index 66%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/IMetricSet.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/IMetricSet.java
index b566d2dd53..9b66fcec4f 100644
--- 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/IMetricSet.java
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/IMetricSet.java
@@ -17,20 +17,15 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined;
+package org.apache.iotdb.metrics.metricsets;
 
-import org.apache.iotdb.metrics.AbstractMetricManager;
+import org.apache.iotdb.metrics.AbstractMetricService;
 
+/** Notice that IMetricSet should be stateless */
 public interface IMetricSet {
-  /** bind related metric to metric manager */
-  void bindTo(AbstractMetricManager metricManager);
+  /** bind metrics to metricManager and init environment */
+  void bindTo(AbstractMetricService metricService);
 
-  /** get type of metric set */
-  PredefinedMetric getType();
-
-  /** start async collectd metric */
-  default void startAsyncCollectedMetrics() {}
-
-  /** stop async collectd metric */
-  default void stopAsyncCollectedMetrics() {}
+  /** remove metrics from metricManager and clear environment */
+  void unbindFrom(AbstractMetricService metricService);
 }
diff --git 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/PredefinedMetric.java
 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/PredefinedMetric.java
similarity index 94%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/PredefinedMetric.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/PredefinedMetric.java
index c6580f69e8..c520afc1f0 100644
--- 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/PredefinedMetric.java
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/PredefinedMetric.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined;
+package org.apache.iotdb.metrics.metricsets.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/metricsets/predefined/jvm/JvmClassLoaderMetrics.java
similarity index 72%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmClassLoaderMetrics.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmClassLoaderMetrics.java
index 8579717f85..daa7cf5206 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/metricsets/predefined/jvm/JvmClassLoaderMetrics.java
@@ -17,12 +17,12 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined.jvm;
+package org.apache.iotdb.metrics.metricsets.predefined.jvm;
 
-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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import java.lang.management.ClassLoadingMXBean;
 import java.lang.management.ManagementFactory;
@@ -30,15 +30,14 @@ 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(AbstractMetricManager metricManager) {
+  public void bindTo(AbstractMetricService metricService) {
     ClassLoadingMXBean classLoadingBean = 
ManagementFactory.getClassLoadingMXBean();
-
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.classes.loaded.classes",
         MetricLevel.IMPORTANT,
         classLoadingBean,
         ClassLoadingMXBean::getLoadedClassCount);
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.classes.unloaded.classes",
         MetricLevel.IMPORTANT,
         classLoadingBean,
@@ -46,7 +45,8 @@ public class JvmClassLoaderMetrics implements IMetricSet {
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.JVM;
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(MetricType.GAUGE, "jvm.classes.loaded.classes");
+    metricService.remove(MetricType.GAUGE, "jvm.classes.unloaded.classes");
   }
 }
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/metricsets/predefined/jvm/JvmCompileMetrics.java
similarity index 69%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmCompileMetrics.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmCompileMetrics.java
index 86adf2dbad..fcf8801983 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/metricsets/predefined/jvm/JvmCompileMetrics.java
@@ -17,12 +17,12 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined.jvm;
+package org.apache.iotdb.metrics.metricsets.predefined.jvm;
 
-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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import java.lang.management.CompilationMXBean;
 import java.lang.management.ManagementFactory;
@@ -30,10 +30,10 @@ 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(AbstractMetricManager metricManager) {
+  public void bindTo(AbstractMetricService metricService) {
     CompilationMXBean compilationBean = 
ManagementFactory.getCompilationMXBean();
     if (compilationBean != null && 
compilationBean.isCompilationTimeMonitoringSupported()) {
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.compilation.time.ms",
           MetricLevel.IMPORTANT,
           compilationBean,
@@ -44,7 +44,11 @@ public class JvmCompileMetrics implements IMetricSet {
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.JVM;
+  public void unbindFrom(AbstractMetricService metricService) {
+    CompilationMXBean compilationBean = 
ManagementFactory.getCompilationMXBean();
+    if (compilationBean != null && 
compilationBean.isCompilationTimeMonitoringSupported()) {
+      metricService.remove(
+          MetricType.GAUGE, "jvm.compilation.time.ms", "compiler", 
compilationBean.getName());
+    }
   }
 }
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/metricsets/predefined/jvm/JvmGcMetrics.java
similarity index 79%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmGcMetrics.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmGcMetrics.java
index 27cd6a670b..703f3b1e32 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/metricsets/predefined/jvm/JvmGcMetrics.java
@@ -17,14 +17,14 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined.jvm;
+package org.apache.iotdb.metrics.metricsets.predefined.jvm;
 
-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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.type.Counter;
 import org.apache.iotdb.metrics.type.Timer;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import com.sun.management.GarbageCollectionNotificationInfo;
 import com.sun.management.GcInfo;
@@ -71,23 +71,8 @@ public class JvmGcMetrics implements IMetricSet, 
AutoCloseable {
   }
 
   @Override
-  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");
-      return;
-    }
-
-    try {
-      Class.forName(
-          "com.sun.management.GarbageCollectionNotificationInfo",
-          false,
-          MemoryPoolMXBean.class.getClassLoader());
-    } catch (Throwable e) {
-      // We are operating in a JVM without access to this level of detail
-      logger.warn(
-          "GC notifications will not be available because "
-              + "com.sun.management.GarbageCollectionNotificationInfo is not 
present");
+  public void bindTo(AbstractMetricService metricService) {
+    if (!preCheck()) {
       return;
     }
 
@@ -100,20 +85,20 @@ public class JvmGcMetrics implements IMetricSet, 
AutoCloseable {
             .orElse(0.0);
 
     AtomicLong maxDataSize = new AtomicLong((long) maxLongLivedPoolBytes);
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.gc.max.data.size.bytes", MetricLevel.IMPORTANT, maxDataSize, 
AtomicLong::get);
 
     AtomicLong liveDataSize = new AtomicLong();
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.gc.live.data.size.bytes", MetricLevel.IMPORTANT, liveDataSize, 
AtomicLong::get);
 
     Counter allocatedBytes =
-        metricManager.getOrCreateCounter("jvm.gc.memory.allocated.bytes", 
MetricLevel.IMPORTANT);
+        metricService.getOrCreateCounter("jvm.gc.memory.allocated.bytes", 
MetricLevel.IMPORTANT);
 
     Counter promotedBytes =
         (oldGenPoolName == null)
             ? null
-            : metricManager.getOrCreateCounter(
+            : metricService.getOrCreateCounter(
                 "jvm.gc.memory.promoted.bytes", MetricLevel.IMPORTANT);
 
     // start watching for GC notifications
@@ -140,7 +125,7 @@ public class JvmGcMetrics implements IMetricSet, 
AutoCloseable {
               timerName = "jvm.gc.pause";
             }
             Timer timer =
-                metricManager.getOrCreateTimer(
+                metricService.getOrCreateTimer(
                     timerName, MetricLevel.IMPORTANT, "action", gcAction, 
"cause", gcCause);
             timer.update(duration, TimeUnit.MILLISECONDS);
 
@@ -213,6 +198,81 @@ public class JvmGcMetrics implements IMetricSet, 
AutoCloseable {
     }
   }
 
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    if (!preCheck()) {
+      return;
+    }
+
+    metricService.remove(MetricType.GAUGE, "jvm.gc.max.data.size.bytes");
+    metricService.remove(MetricType.GAUGE, "jvm.gc.live.data.size.bytes");
+    metricService.remove(MetricType.COUNTER, "jvm.gc.memory.allocated.bytes");
+
+    if (oldGenPoolName != null) {
+      metricService.remove(MetricType.COUNTER, "jvm.gc.memory.promoted.bytes");
+    }
+
+    // start watching for GC notifications
+    for (GarbageCollectorMXBean mbean : 
ManagementFactory.getGarbageCollectorMXBeans()) {
+      if (!(mbean instanceof NotificationEmitter)) {
+        continue;
+      }
+      NotificationListener notificationListener =
+          (notification, ref) -> {
+            CompositeData cd = (CompositeData) notification.getUserData();
+            GarbageCollectionNotificationInfo notificationInfo =
+                GarbageCollectionNotificationInfo.from(cd);
+
+            String gcCause = notificationInfo.getGcCause();
+            String gcAction = notificationInfo.getGcAction();
+            String timerName;
+            if (isConcurrentPhase(gcCause, notificationInfo.getGcName())) {
+              timerName = "jvm.gc.concurrent.phase.time";
+            } else {
+              timerName = "jvm.gc.pause";
+            }
+            metricService.remove(MetricType.TIMER, timerName, "action", 
gcAction, "cause", gcCause);
+          };
+      NotificationEmitter notificationEmitter = (NotificationEmitter) mbean;
+      notificationEmitter.addNotificationListener(
+          notificationListener,
+          notification ->
+              notification
+                  .getType()
+                  
.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION),
+          null);
+      notificationListenerCleanUpRunnables.add(
+          () -> {
+            try {
+              
notificationEmitter.removeNotificationListener(notificationListener);
+            } catch (ListenerNotFoundException ignore) {
+            }
+          });
+    }
+  }
+
+  private boolean preCheck() {
+    if (ManagementFactory.getMemoryPoolMXBeans().isEmpty()) {
+      logger.warn(
+          "GC notifications will not be available because MemoryPoolMXBeans 
are not provided by the JVM");
+      return false;
+    }
+
+    try {
+      Class.forName(
+          "com.sun.management.GarbageCollectionNotificationInfo",
+          false,
+          MemoryPoolMXBean.class.getClassLoader());
+    } catch (Throwable e) {
+      // We are operating in a JVM without access to this level of detail
+      logger.warn(
+          "GC notifications will not be available because "
+              + "com.sun.management.GarbageCollectionNotificationInfo is not 
present");
+      return false;
+    }
+    return true;
+  }
+
   private void countPoolSizeDelta(
       Map<String, MemoryUsage> before,
       Map<String, MemoryUsage> after,
@@ -233,11 +293,6 @@ public class JvmGcMetrics implements IMetricSet, 
AutoCloseable {
     notificationListenerCleanUpRunnables.forEach(Runnable::run);
   }
 
-  @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.JVM;
-  }
-
   enum GcGenerationAge {
     OLD,
     YOUNG,
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/metricsets/predefined/jvm/JvmMemoryMetrics.java
similarity index 63%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMemoryMetrics.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmMemoryMetrics.java
index 1e28133961..da13ef12ac 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/metricsets/predefined/jvm/JvmMemoryMetrics.java
@@ -17,12 +17,12 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined.jvm;
+package org.apache.iotdb.metrics.metricsets.predefined.jvm;
 
-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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import java.lang.management.BufferPoolMXBean;
 import java.lang.management.ManagementFactory;
@@ -33,10 +33,10 @@ 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(AbstractMetricManager metricManager) {
+  public void bindTo(AbstractMetricService metricService) {
     for (BufferPoolMXBean bufferPoolBean :
         ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class)) {
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.buffer.count.buffers",
           MetricLevel.IMPORTANT,
           bufferPoolBean,
@@ -44,7 +44,7 @@ public class JvmMemoryMetrics implements IMetricSet {
           "id",
           bufferPoolBean.getName());
 
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.buffer.memory.used.bytes",
           MetricLevel.IMPORTANT,
           bufferPoolBean,
@@ -52,7 +52,7 @@ public class JvmMemoryMetrics implements IMetricSet {
           "id",
           bufferPoolBean.getName());
 
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.buffer.total.capacity.bytes",
           MetricLevel.IMPORTANT,
           bufferPoolBean,
@@ -65,7 +65,7 @@ public class JvmMemoryMetrics implements IMetricSet {
         ManagementFactory.getPlatformMXBeans(MemoryPoolMXBean.class)) {
       String area = MemoryType.HEAP.equals(memoryPoolBean.getType()) ? "heap" 
: "nonheap";
 
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.memory.used.bytes",
           MetricLevel.IMPORTANT,
           memoryPoolBean,
@@ -75,7 +75,7 @@ public class JvmMemoryMetrics implements IMetricSet {
           "area",
           area);
 
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.memory.committed.bytes",
           MetricLevel.IMPORTANT,
           memoryPoolBean,
@@ -85,7 +85,7 @@ public class JvmMemoryMetrics implements IMetricSet {
           "area",
           area);
 
-      metricManager.getOrCreateAutoGauge(
+      metricService.getOrCreateAutoGauge(
           "jvm.memory.max.bytes",
           MetricLevel.IMPORTANT,
           memoryPoolBean,
@@ -98,7 +98,36 @@ public class JvmMemoryMetrics implements IMetricSet {
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.JVM;
+  public void unbindFrom(AbstractMetricService metricService) {
+    for (BufferPoolMXBean bufferPoolBean :
+        ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class)) {
+      metricService.remove(
+          MetricType.GAUGE, "jvm.buffer.count.buffers", "id", 
bufferPoolBean.getName());
+
+      metricService.remove(
+          MetricType.GAUGE, "jvm.buffer.memory.used.bytes", "id", 
bufferPoolBean.getName());
+
+      metricService.remove(
+          MetricType.GAUGE, "jvm.buffer.total.capacity.bytes", "id", 
bufferPoolBean.getName());
+    }
+
+    for (MemoryPoolMXBean memoryPoolBean :
+        ManagementFactory.getPlatformMXBeans(MemoryPoolMXBean.class)) {
+      String area = MemoryType.HEAP.equals(memoryPoolBean.getType()) ? "heap" 
: "nonheap";
+
+      metricService.remove(
+          MetricType.GAUGE, "jvm.memory.used.bytes", "id", 
memoryPoolBean.getName(), "area", area);
+
+      metricService.remove(
+          MetricType.GAUGE,
+          "jvm.memory.committed.bytes",
+          "id",
+          memoryPoolBean.getName(),
+          "area",
+          area);
+
+      metricService.remove(
+          MetricType.GAUGE, "jvm.memory.max.bytes", "id", 
memoryPoolBean.getName(), "area", area);
+    }
   }
 }
diff --git 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmMetrics.java
 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmMetrics.java
new file mode 100644
index 0000000000..0d63d6a3a9
--- /dev/null
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmMetrics.java
@@ -0,0 +1,52 @@
+/*
+ * 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.metricsets.predefined.jvm;
+
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JvmMetrics implements IMetricSet {
+  private List<IMetricSet> metricSets = new ArrayList<>();
+
+  public JvmMetrics() {
+    metricSets.add(new JvmClassLoaderMetrics());
+    metricSets.add(new JvmCompileMetrics());
+    metricSets.add(new JvmGcMetrics());
+    metricSets.add(new JvmMemoryMetrics());
+    metricSets.add(new JvmThreadMetrics());
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    for (IMetricSet metricSet : metricSets) {
+      metricSet.bindTo(metricService);
+    }
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    for (IMetricSet metricSet : metricSets) {
+      metricSet.unbindFrom(metricService);
+    }
+  }
+}
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/metricsets/predefined/jvm/JvmThreadMetrics.java
similarity index 68%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmThreadMetrics.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmThreadMetrics.java
index 8a7428942f..40966c018f 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/metricsets/predefined/jvm/JvmThreadMetrics.java
@@ -17,12 +17,12 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined.jvm;
+package org.apache.iotdb.metrics.metricsets.predefined.jvm;
 
-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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import java.lang.management.ManagementFactory;
 import java.lang.management.ThreadMXBean;
@@ -31,22 +31,22 @@ 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(AbstractMetricManager metricManager) {
+  public void bindTo(AbstractMetricService metricService) {
     ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
 
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.threads.peak.threads",
         MetricLevel.IMPORTANT,
         threadBean,
         ThreadMXBean::getPeakThreadCount);
 
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.threads.daemon.threads",
         MetricLevel.IMPORTANT,
         threadBean,
         ThreadMXBean::getDaemonThreadCount);
 
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         "jvm.threads.live.threads",
         MetricLevel.IMPORTANT,
         threadBean,
@@ -55,7 +55,7 @@ public class JvmThreadMetrics implements IMetricSet {
     try {
       threadBean.getAllThreadIds();
       for (Thread.State state : Thread.State.values()) {
-        metricManager.getOrCreateAutoGauge(
+        metricService.getOrCreateAutoGauge(
             "jvm.threads.states.threads",
             MetricLevel.IMPORTANT,
             threadBean,
@@ -81,7 +81,22 @@ public class JvmThreadMetrics implements IMetricSet {
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.JVM;
+  public void unbindFrom(AbstractMetricService metricService) {
+    ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
+
+    metricService.remove(MetricType.GAUGE, "jvm.threads.peak.threads");
+    metricService.remove(MetricType.GAUGE, "jvm.threads.daemon.threads");
+    metricService.remove(MetricType.GAUGE, "jvm.threads.live.threads");
+
+    try {
+      threadBean.getAllThreadIds();
+      for (Thread.State state : Thread.State.values()) {
+        metricService.remove(
+            MetricType.GAUGE, "jvm.threads.states.threads", "state", 
getStateTagValue(state));
+      }
+    } catch (Error error) {
+      // An error will be thrown for unsupported operations
+      // e.g. SubstrateVM does not support getAllThreadIds
+    }
   }
 }
diff --git 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmUtils.java
 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmUtils.java
similarity index 96%
rename from 
metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmUtils.java
rename to 
metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmUtils.java
index 4b7f9d3062..79a7b4a54c 100644
--- 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmUtils.java
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/jvm/JvmUtils.java
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-package org.apache.iotdb.metrics.predefined.jvm;
+package org.apache.iotdb.metrics.metricsets.predefined.jvm;
 
 import java.lang.management.MemoryPoolMXBean;
 import java.lang.management.MemoryUsage;
diff --git 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/logback/LogbackMetrics.java
 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/logback/LogbackMetrics.java
new file mode 100644
index 0000000000..94464699c0
--- /dev/null
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/logback/LogbackMetrics.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.metrics.metricsets.predefined.logback;
+
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggerContextListener;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** This file is modified from 
io.micrometer.core.instrument.binder.logging.LogbackMetrics */
+public class LogbackMetrics implements IMetricSet {
+  private static final org.slf4j.Logger logger = 
LoggerFactory.getLogger(LogbackMetrics.class);
+  static ThreadLocal<Boolean> ignoreMetrics = new ThreadLocal<>();
+  private final LoggerContext loggerContext = (LoggerContext) 
LoggerFactory.getILoggerFactory();
+  private final Map<AbstractMetricService, MetricsTurboFilter> 
metricsTurboFilters =
+      new HashMap<>();
+
+  public LogbackMetrics() {
+    loggerContext.addListener(
+        new LoggerContextListener() {
+          @Override
+          public boolean isResetResistant() {
+            return true;
+          }
+
+          @Override
+          public void onReset(LoggerContext context) {
+            // re-add turbo filter because reset clears the turbo filter list
+            synchronized (metricsTurboFilters) {
+              for (MetricsTurboFilter addMetricsTurboFilter : 
metricsTurboFilters.values()) {
+                loggerContext.addTurboFilter(addMetricsTurboFilter);
+              }
+            }
+          }
+
+          @Override
+          public void onStart(LoggerContext context) {
+            // no-op
+          }
+
+          @Override
+          public void onStop(LoggerContext context) {
+            // no-op
+          }
+
+          @Override
+          public void onLevelChange(Logger logger, Level level) {
+            // no-op
+          }
+        });
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    MetricsTurboFilter filter = new MetricsTurboFilter(metricService);
+    synchronized (metricsTurboFilters) {
+      metricsTurboFilters.put(metricService, filter);
+      loggerContext.addTurboFilter(filter);
+    }
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    try {
+      synchronized (metricsTurboFilters) {
+        for (MetricsTurboFilter addMetricsTurboFilter : 
metricsTurboFilters.values()) {
+          loggerContext.getTurboFilterList().remove(addMetricsTurboFilter);
+        }
+        metricService.remove(MetricType.COUNTER, "logback.events", "level", 
"error");
+        metricService.remove(MetricType.COUNTER, "logback.events", "level", 
"warn");
+        metricService.remove(MetricType.COUNTER, "logback.events", "level", 
"info");
+        metricService.remove(MetricType.COUNTER, "logback.events", "level", 
"debug");
+        metricService.remove(MetricType.COUNTER, "logback.events", "level", 
"trace");
+      }
+    } catch (Exception e) {
+      logger.error("Failed to remove LogBackMetrics.");
+    }
+  }
+}
diff --git 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/logback/MetricsTurboFilter.java
 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/logback/MetricsTurboFilter.java
new file mode 100644
index 0000000000..173ea3b5e7
--- /dev/null
+++ 
b/metrics/interface/src/main/java/org/apache/iotdb/metrics/metricsets/predefined/logback/MetricsTurboFilter.java
@@ -0,0 +1,98 @@
+/*
+ * 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.metricsets.predefined.logback;
+
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.type.Counter;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.turbo.TurboFilter;
+import ch.qos.logback.core.spi.FilterReply;
+import org.slf4j.Marker;
+
+public class MetricsTurboFilter extends TurboFilter {
+  private Counter errorCounter;
+  private Counter warnCounter;
+  private Counter infoCounter;
+  private Counter debugCounter;
+  private Counter traceCounter;
+
+  MetricsTurboFilter(AbstractMetricService metricService) {
+    errorCounter =
+        metricService.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "error");
+
+    warnCounter =
+        metricService.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "warn");
+
+    infoCounter =
+        metricService.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "info");
+
+    debugCounter =
+        metricService.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "debug");
+
+    traceCounter =
+        metricService.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "trace");
+  }
+
+  @Override
+  public FilterReply decide(
+      Marker marker, Logger logger, Level level, String format, Object[] 
params, Throwable t) {
+    // When filter is asked for decision for an isDebugEnabled call or similar 
test, there is no
+    // message (ie format)
+    // and no intention to log anything with this call. We will not increment 
counters and can
+    // return immediately and
+    // avoid the relatively expensive ThreadLocal access below. See also 
logbacks
+    // Logger.callTurboFilters().
+    if (format == null) {
+      return FilterReply.NEUTRAL;
+    }
+
+    Boolean ignored = LogbackMetrics.ignoreMetrics.get();
+    if (ignored != null && ignored) {
+      return FilterReply.NEUTRAL;
+    }
+
+    // cannot use logger.isEnabledFor(level), as it would cause a 
StackOverflowError by calling this
+    // filter again!
+    if (level.isGreaterOrEqual(logger.getEffectiveLevel())) {
+      switch (level.toInt()) {
+        case Level.ERROR_INT:
+          errorCounter.inc();
+          break;
+        case Level.WARN_INT:
+          warnCounter.inc();
+          break;
+        case Level.INFO_INT:
+          infoCounter.inc();
+          break;
+        case Level.DEBUG_INT:
+          debugCounter.inc();
+          break;
+        case Level.TRACE_INT:
+          traceCounter.inc();
+          break;
+      }
+    }
+
+    return FilterReply.NEUTRAL;
+  }
+}
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
deleted file mode 100644
index 3d2a744861..0000000000
--- 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/jvm/JvmMetrics.java
+++ /dev/null
@@ -1,49 +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.predefined.jvm;
-
-import org.apache.iotdb.metrics.AbstractMetricManager;
-import org.apache.iotdb.metrics.predefined.IMetricSet;
-import org.apache.iotdb.metrics.predefined.PredefinedMetric;
-
-public class JvmMetrics implements IMetricSet {
-  @Override
-  public void bindTo(AbstractMetricManager metricManager) {
-    JvmClassLoaderMetrics jvmClassLoaderMetricSet = new 
JvmClassLoaderMetrics();
-    jvmClassLoaderMetricSet.bindTo(metricManager);
-
-    JvmCompileMetrics jvmCompileMetricSet = new JvmCompileMetrics();
-    jvmCompileMetricSet.bindTo(metricManager);
-
-    JvmGcMetrics jvmGcMetricSet = new JvmGcMetrics();
-    jvmGcMetricSet.bindTo(metricManager);
-
-    JvmMemoryMetrics jvmMemoryMetricSet = new JvmMemoryMetrics();
-    jvmMemoryMetricSet.bindTo(metricManager);
-
-    JvmThreadMetrics jvmThreadMetrics = new JvmThreadMetrics();
-    jvmThreadMetrics.bindTo(metricManager);
-  }
-
-  @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.JVM;
-  }
-}
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
deleted file mode 100644
index b2dde91411..0000000000
--- 
a/metrics/interface/src/main/java/org/apache/iotdb/metrics/predefined/logback/LogbackMetrics.java
+++ /dev/null
@@ -1,181 +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.predefined.logback;
-
-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 ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.spi.LoggerContextListener;
-import ch.qos.logback.classic.turbo.TurboFilter;
-import ch.qos.logback.core.spi.FilterReply;
-import org.slf4j.LoggerFactory;
-import org.slf4j.Marker;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** This file is modified from 
io.micrometer.core.instrument.binder.logging.LogbackMetrics */
-public class LogbackMetrics implements IMetricSet, AutoCloseable {
-  static ThreadLocal<Boolean> ignoreMetrics = new ThreadLocal<>();
-  private final LoggerContext loggerContext = (LoggerContext) 
LoggerFactory.getILoggerFactory();
-  private final Map<AbstractMetricManager, MetricsTurboFilter> 
metricsTurboFilters =
-      new HashMap<>();
-
-  public LogbackMetrics() {
-    loggerContext.addListener(
-        new LoggerContextListener() {
-          @Override
-          public boolean isResetResistant() {
-            return true;
-          }
-
-          @Override
-          public void onReset(LoggerContext context) {
-            // re-add turbo filter because reset clears the turbo filter list
-            synchronized (metricsTurboFilters) {
-              for (MetricsTurboFilter metricsTurboFilter : 
metricsTurboFilters.values()) {
-                loggerContext.addTurboFilter(metricsTurboFilter);
-              }
-            }
-          }
-
-          @Override
-          public void onStart(LoggerContext context) {
-            // no-op
-          }
-
-          @Override
-          public void onStop(LoggerContext context) {
-            // no-op
-          }
-
-          @Override
-          public void onLevelChange(Logger logger, Level level) {
-            // no-op
-          }
-        });
-  }
-
-  @Override
-  public void bindTo(AbstractMetricManager metricManager) {
-    MetricsTurboFilter filter = new MetricsTurboFilter(metricManager);
-    synchronized (metricsTurboFilters) {
-      metricsTurboFilters.put(metricManager, filter);
-      loggerContext.addTurboFilter(filter);
-    }
-  }
-
-  public static void ignoreMetrics(Runnable r) {
-    ignoreMetrics.set(true);
-    try {
-      r.run();
-    } finally {
-      ignoreMetrics.remove();
-    }
-  }
-
-  @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.LOGBACK;
-  }
-
-  @Override
-  public void close() throws Exception {
-    synchronized (metricsTurboFilters) {
-      for (MetricsTurboFilter metricsTurboFilter : 
metricsTurboFilters.values()) {
-        loggerContext.getTurboFilterList().remove(metricsTurboFilter);
-      }
-    }
-  }
-}
-
-class MetricsTurboFilter extends TurboFilter {
-  private Counter errorCounter;
-  private Counter warnCounter;
-  private Counter infoCounter;
-  private Counter debugCounter;
-  private Counter traceCounter;
-
-  MetricsTurboFilter(AbstractMetricManager metricManager) {
-    errorCounter =
-        metricManager.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "error");
-
-    warnCounter =
-        metricManager.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "warn");
-
-    infoCounter =
-        metricManager.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "info");
-
-    debugCounter =
-        metricManager.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "debug");
-
-    traceCounter =
-        metricManager.getOrCreateCounter("logback.events", 
MetricLevel.IMPORTANT, "level", "trace");
-  }
-
-  @Override
-  public FilterReply decide(
-      Marker marker, Logger logger, Level level, String format, Object[] 
params, Throwable t) {
-    // When filter is asked for decision for an isDebugEnabled call or similar 
test, there is no
-    // message (ie format)
-    // and no intention to log anything with this call. We will not increment 
counters and can
-    // return immediately and
-    // avoid the relatively expensive ThreadLocal access below. See also 
logbacks
-    // Logger.callTurboFilters().
-    if (format == null) {
-      return FilterReply.NEUTRAL;
-    }
-
-    Boolean ignored = LogbackMetrics.ignoreMetrics.get();
-    if (ignored != null && ignored) {
-      return FilterReply.NEUTRAL;
-    }
-
-    // cannot use logger.isEnabledFor(level), as it would cause a 
StackOverflowError by calling this
-    // filter again!
-    if (level.isGreaterOrEqual(logger.getEffectiveLevel())) {
-      switch (level.toInt()) {
-        case Level.ERROR_INT:
-          errorCounter.inc();
-          break;
-        case Level.WARN_INT:
-          warnCounter.inc();
-          break;
-        case Level.INFO_INT:
-          infoCounter.inc();
-          break;
-        case Level.DEBUG_INT:
-          debugCounter.inc();
-          break;
-        case Level.TRACE_INT:
-          traceCounter.inc();
-          break;
-      }
-    }
-
-    return FilterReply.NEUTRAL;
-  }
-}
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 e163b53820..d27ad8d68e 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
@@ -30,13 +30,14 @@ import io.micrometer.core.instrument.Metrics;
 import io.micrometer.prometheus.PrometheusConfig;
 import io.micrometer.prometheus.PrometheusMeterRegistry;
 import io.netty.channel.ChannelOption;
+import io.netty.channel.group.DefaultChannelGroup;
+import io.netty.util.concurrent.GlobalEventExecutor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import reactor.core.publisher.Mono;
 import reactor.netty.DisposableServer;
 import reactor.netty.http.server.HttpServer;
 
-import java.time.Duration;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -50,6 +51,9 @@ public class MicrometerPrometheusReporter implements Reporter 
{
 
   @Override
   public boolean start() {
+    if (httpServer != null) {
+      return false;
+    }
     Set<MeterRegistry> meterRegistrySet =
         Metrics.globalRegistry.getRegistries().stream()
             .filter(reporter -> reporter instanceof PrometheusMeterRegistry)
@@ -64,8 +68,8 @@ public class MicrometerPrometheusReporter implements Reporter 
{
     }
     httpServer =
         HttpServer.create()
-            .idleTimeout(Duration.ofMillis(30_000L))
             .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000)
+            .channelGroup(new 
DefaultChannelGroup(GlobalEventExecutor.INSTANCE))
             .port(metricConfig.getPrometheusExporterPort())
             .route(
                 routes ->
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 7b19e2d711..f01efef820 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,11 +23,7 @@ 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.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.TestOnly;
-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;
 import org.apache.iotdb.tsfile.read.common.Chunk;
@@ -87,16 +83,11 @@ public class ChunkCache {
                 });
 
     // add metrics
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricService.getInstance()
-          .getOrCreateAutoGauge(
-              Metric.CACHE_HIT.toString(),
-              MetricLevel.IMPORTANT,
-              lruCache,
-              l -> (long) (l.stats().hitRate() * 100),
-              Tag.NAME.toString(),
-              "chunk");
-    }
+    MetricService.getInstance().addMetricSet(new ChunkCacheMetrics(this));
+  }
+
+  public double getHitRate() {
+    return lruCache.stats().hitRate() * 100;
   }
 
   public static ChunkCache getInstance() {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java 
b/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
new file mode 100644
index 0000000000..64f40bb46a
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/cache/ChunkCacheMetrics.java
@@ -0,0 +1,67 @@
+/*
+ * 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.engine.cache;
+
+import org.apache.iotdb.db.service.metrics.enums.Metric;
+import org.apache.iotdb.db.service.metrics.enums.Tag;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Objects;
+
+public class ChunkCacheMetrics implements IMetricSet {
+  private ChunkCache chunkCache;
+
+  public ChunkCacheMetrics(ChunkCache chunkCache) {
+    this.chunkCache = chunkCache;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
+        Metric.CACHE_HIT.toString(),
+        MetricLevel.IMPORTANT,
+        chunkCache,
+        o -> (long) o.getHitRate(),
+        Tag.NAME.toString(),
+        "chunk");
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.CACHE_HIT.toString(), Tag.NAME.toString(), 
"chunk");
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    ChunkCacheMetrics that = (ChunkCacheMetrics) o;
+    return Objects.equals(chunkCache, that.chunkCache);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(chunkCache);
+  }
+}
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 8f2051303c..5700708367 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,11 +24,7 @@ import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.query.control.FileReaderManager;
 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.TestOnly;
-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;
 import org.apache.iotdb.tsfile.read.TsFileSequenceReader;
@@ -108,32 +104,7 @@ public class TimeSeriesMetadataCache {
             .recordStats()
             .build();
 
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      // add metrics
-      MetricService.getInstance()
-          .getOrCreateAutoGauge(
-              Metric.CACHE_HIT.toString(),
-              MetricLevel.IMPORTANT,
-              lruCache,
-              l -> (long) (l.stats().hitRate() * 100),
-              Tag.NAME.toString(),
-              "timeSeriesMeta");
-      // add metrics
-      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");
-    }
+    MetricService.getInstance().addMetricSet(new 
TimeSeriesMetadataCacheMetrics(this));
   }
 
   public static TimeSeriesMetadataCache getInstance() {
@@ -247,6 +218,14 @@ public class TimeSeriesMetadataCache {
     return entryAverageSize.get();
   }
 
+  public long calculateBloomFilterHitRatio() {
+    if (bloomFilterRequestCount.get() == 0L) {
+      return 1L;
+    }
+    return (long)
+        ((double) bloomFilterPreventCount.get() / (double) 
bloomFilterRequestCount.get() * 100L);
+  }
+
   /** clear LRUCache. */
   public void clear() {
     lruCache.invalidateAll();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java
new file mode 100644
index 0000000000..e931e58216
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/cache/TimeSeriesMetadataCacheMetrics.java
@@ -0,0 +1,76 @@
+/*
+ * 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.engine.cache;
+
+import org.apache.iotdb.db.service.metrics.enums.Metric;
+import org.apache.iotdb.db.service.metrics.enums.Tag;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Objects;
+
+public class TimeSeriesMetadataCacheMetrics implements IMetricSet {
+  private TimeSeriesMetadataCache timeSeriesMetadataCache;
+
+  public TimeSeriesMetadataCacheMetrics(TimeSeriesMetadataCache 
timeSeriesMetadataCache) {
+    this.timeSeriesMetadataCache = timeSeriesMetadataCache;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
+        Metric.CACHE_HIT.toString(),
+        MetricLevel.IMPORTANT,
+        timeSeriesMetadataCache,
+        l -> (long) 
timeSeriesMetadataCache.calculateTimeSeriesMetadataHitRatio(),
+        Tag.NAME.toString(),
+        "timeSeriesMeta");
+    metricService.getOrCreateAutoGauge(
+        Metric.CACHE_HIT.toString(),
+        MetricLevel.IMPORTANT,
+        timeSeriesMetadataCache,
+        TimeSeriesMetadataCache::calculateBloomFilterHitRatio,
+        Tag.NAME.toString(),
+        "bloomFilter");
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.CACHE_HIT.toString(), Tag.NAME.toString(), 
"timeSeriesMeta");
+    metricService.remove(
+        MetricType.GAUGE, Metric.CACHE_HIT.toString(), Tag.NAME.toString(), 
"bloomFilter");
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    TimeSeriesMetadataCacheMetrics that = (TimeSeriesMetadataCacheMetrics) o;
+    return Objects.equals(timeSeriesMetadataCache, 
that.timeSeriesMetadataCache);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(timeSeriesMetadataCache);
+  }
+}
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 9e8a4cabaa..1b63a8e670 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
@@ -25,15 +25,10 @@ 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.exception.StartupException;
-import org.apache.iotdb.db.rescon.AbstractPoolManager;
 import org.apache.iotdb.db.service.IService;
 import org.apache.iotdb.db.service.JMXService;
 import org.apache.iotdb.db.service.ServiceType;
 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;
 import org.slf4j.LoggerFactory;
@@ -56,29 +51,7 @@ public class FlushManager implements FlushManagerMBean, 
IService {
     flushPool.start();
     try {
       JMXService.registerMBean(this, ServiceType.FLUSH_SERVICE.getJmxName());
-      if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-        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");
-      }
-
+      MetricService.getInstance().addMetricSet(new FlushManagerMetrics(this));
     } catch (Exception e) {
       throw new StartupException(this.getID().getName(), e.getMessage());
     }
@@ -96,6 +69,11 @@ public class FlushManager implements FlushManagerMBean, 
IService {
     return ServiceType.FLUSH_SERVICE;
   }
 
+  @Override
+  public int getNumberOfWaitingTasks() {
+    return flushPool.getWaitingTasksNumber();
+  }
+
   @Override
   public int getNumberOfWorkingTasks() {
     return flushPool.getWorkingTasksNumber();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMBean.java 
b/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMBean.java
index 7f474902d6..a78b190910 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMBean.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMBean.java
@@ -21,6 +21,8 @@ package org.apache.iotdb.db.engine.flush;
 
 public interface FlushManagerMBean {
 
+  int getNumberOfWaitingTasks();
+
   int getNumberOfWorkingTasks();
 
   int getNumberOfPendingTasks();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMetrics.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMetrics.java
new file mode 100644
index 0000000000..43a95dc3c5
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/flush/FlushManagerMetrics.java
@@ -0,0 +1,90 @@
+/*
+ * 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.engine.flush;
+
+import org.apache.iotdb.db.service.metrics.enums.Metric;
+import org.apache.iotdb.db.service.metrics.enums.Tag;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Objects;
+
+public class FlushManagerMetrics implements IMetricSet {
+  private FlushManager flushManager;
+
+  public FlushManagerMetrics(FlushManager flushManager) {
+    this.flushManager = flushManager;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
+        Metric.QUEUE.toString(),
+        MetricLevel.IMPORTANT,
+        flushManager,
+        FlushManager::getNumberOfWaitingTasks,
+        Tag.NAME.toString(),
+        "flush",
+        Tag.STATUS.toString(),
+        "waiting");
+    metricService.getOrCreateAutoGauge(
+        Metric.QUEUE.toString(),
+        MetricLevel.IMPORTANT,
+        flushManager,
+        FlushManager::getNumberOfWorkingTasks,
+        Tag.NAME.toString(),
+        "flush",
+        Tag.STATUS.toString(),
+        "running");
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.QUEUE.toString(),
+        Tag.NAME.toString(),
+        "flush",
+        Tag.STATUS.toString(),
+        "waiting");
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.QUEUE.toString(),
+        Tag.NAME.toString(),
+        "flush",
+        Tag.STATUS.toString(),
+        "running");
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    FlushManagerMetrics that = (FlushManagerMetrics) o;
+    return Objects.equals(flushManager, that.flushManager);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(flushManager);
+  }
+}
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 54ae620663..32e0543fbd 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
@@ -19,10 +19,6 @@
 package org.apache.iotdb.db.engine.storagegroup;
 
 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. */
 public class TsFileProcessorInfo {
@@ -36,53 +32,30 @@ public class TsFileProcessorInfo {
   public TsFileProcessorInfo(StorageGroupInfo storageGroupInfo) {
     this.storageGroupInfo = storageGroupInfo;
     this.memCost = 0L;
+    if (null != storageGroupInfo.getVirtualStorageGroupProcessor()) {
+      MetricService.getInstance()
+          .addMetricSet(
+              new TsFileProcessorInfoMetrics(
+                  
storageGroupInfo.getVirtualStorageGroupProcessor().getLogicalStorageGroupName(),
+                  memCost));
+    }
   }
 
   /** called in each insert */
   public void addTSPMemCost(long cost) {
     memCost += cost;
     storageGroupInfo.addStorageGroupMemCost(cost);
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricService.getInstance()
-          .getOrCreateGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              "chunkMetaData_"
-                  + 
storageGroupInfo.getVirtualStorageGroupProcessor().getLogicalStorageGroupName())
-          .incr(cost);
-    }
   }
 
   /** called when meet exception */
   public void releaseTSPMemCost(long cost) {
     storageGroupInfo.releaseStorageGroupMemCost(cost);
     memCost -= cost;
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricService.getInstance()
-          .getOrCreateGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              "chunkMetaData_"
-                  + 
storageGroupInfo.getVirtualStorageGroupProcessor().getLogicalStorageGroupName())
-          .decr(cost);
-    }
   }
 
   /** called when closing TSP */
   public void clear() {
     storageGroupInfo.releaseStorageGroupMemCost(memCost);
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricService.getInstance()
-          .getOrCreateGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              Tag.NAME.toString(),
-              "chunkMetaData_"
-                  + 
storageGroupInfo.getVirtualStorageGroupProcessor().getLogicalStorageGroupName())
-          .decr(memCost);
-    }
     memCost = 0L;
   }
 }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfoMetrics.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfoMetrics.java
new file mode 100644
index 0000000000..553e59d65f
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/TsFileProcessorInfoMetrics.java
@@ -0,0 +1,75 @@
+/*
+ * 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.engine.storagegroup;
+
+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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Objects;
+
+public class TsFileProcessorInfoMetrics implements IMetricSet {
+  private String storageGroupName;
+  private long memCost;
+
+  public TsFileProcessorInfoMetrics(String storageGroupName, long memCost) {
+    this.storageGroupName = storageGroupName;
+    this.memCost = memCost;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.MEM.toString(),
+            MetricLevel.IMPORTANT,
+            memCost,
+            o -> o,
+            Tag.NAME.toString(),
+            "chunkMetaData_" + storageGroupName);
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
+            Metric.MEM.toString(),
+            Tag.NAME.toString(),
+            "chunkMetaData_" + storageGroupName);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    TsFileProcessorInfoMetrics that = (TsFileProcessorInfoMetrics) o;
+    return memCost == that.memCost && Objects.equals(storageGroupName, 
that.storageGroupName);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(storageGroupName, memCost);
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessor.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessor.java
index 467763e23a..997a61467e 100755
--- 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessor.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessor.java
@@ -69,16 +69,12 @@ 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.MetricService;
-import org.apache.iotdb.db.service.metrics.enums.Metric;
-import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.tools.settle.TsFileAndModSettleTool;
 import org.apache.iotdb.db.utils.CopyOnReadLinkedList;
 import org.apache.iotdb.db.utils.MmapUtil;
 import org.apache.iotdb.db.utils.TestOnly;
 import org.apache.iotdb.db.utils.UpgradeUtils;
 import org.apache.iotdb.db.writelog.recover.TsFileRecoverPerformer;
-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;
 import org.apache.iotdb.service.rpc.thrift.TSStatus;
@@ -403,16 +399,7 @@ public class VirtualStorageGroupProcessor {
     // recover tsfiles
     recover();
 
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      MetricService.getInstance()
-          .getOrCreateAutoGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              storageGroupInfo,
-              StorageGroupInfo::getMemCost,
-              Tag.NAME.toString(),
-              "storageGroup_" + getLogicalStorageGroupName());
-    }
+    MetricService.getInstance().addMetricSet(new 
VirtualStorageGroupProcessorMetrics(this));
 
     // start trim task at last
     walTrimScheduleTask =
@@ -429,6 +416,10 @@ public class VirtualStorageGroupProcessor {
         TimeUnit.MILLISECONDS);
   }
 
+  public long getStorageGroupMemCost() {
+    return storageGroupInfo.getMemCost();
+  }
+
   public String getLogicalStorageGroupName() {
     return logicalStorageGroupName;
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessorMetrics.java
 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessorMetrics.java
new file mode 100644
index 0000000000..ac2146ca44
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/engine/storagegroup/VirtualStorageGroupProcessorMetrics.java
@@ -0,0 +1,56 @@
+/*
+ * 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.engine.storagegroup;
+
+import org.apache.iotdb.db.service.metrics.enums.Metric;
+import org.apache.iotdb.db.service.metrics.enums.Tag;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+public class VirtualStorageGroupProcessorMetrics implements IMetricSet {
+  private VirtualStorageGroupProcessor virtualStorageGroupProcessor;
+
+  public VirtualStorageGroupProcessorMetrics(
+      VirtualStorageGroupProcessor virtualStorageGroupProcessor) {
+    this.virtualStorageGroupProcessor = virtualStorageGroupProcessor;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
+        Metric.MEM.toString(),
+        MetricLevel.IMPORTANT,
+        virtualStorageGroupProcessor,
+        VirtualStorageGroupProcessor::getStorageGroupMemCost,
+        Tag.NAME.toString(),
+        "storageGroup_" + 
virtualStorageGroupProcessor.getLogicalStorageGroupName());
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.MEM.toString(),
+        Tag.NAME.toString(),
+        "storageGroup_" + 
virtualStorageGroupProcessor.getLogicalStorageGroupName());
+  }
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
index 87d54cae0f..d88dd82879 100644
--- a/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManager.java
@@ -86,14 +86,10 @@ import 
org.apache.iotdb.db.query.dataset.ShowTimeSeriesResult;
 import org.apache.iotdb.db.rescon.MemTableManager;
 import org.apache.iotdb.db.service.IoTDB;
 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.SchemaUtils;
 import org.apache.iotdb.db.utils.TestOnly;
 import org.apache.iotdb.db.utils.TypeInferenceUtils;
 import org.apache.iotdb.external.api.ISeriesNumerMonitor;
-import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
-import org.apache.iotdb.metrics.utils.MetricLevel;
 import org.apache.iotdb.tsfile.common.conf.TSFileDescriptor;
 import org.apache.iotdb.tsfile.file.metadata.enums.CompressionType;
 import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
@@ -323,78 +319,37 @@ public class MManager {
           "Cannot recover all MTree from file, we try to recover as possible 
as we can", e);
     }
     initialized = true;
+    MetricService.getInstance().addMetricSet(new MManagerMetrics(this));
+  }
+
+  public long getNormalSeriesNumber() {
+    return totalNormalSeriesNumber.get();
+  }
+
+  public long getTemplateSeriesNumber() {
+    return totalTemplateSeriesNumber.get();
+  }
+
+  public long getDeviceNumber() {
+    try {
+      return mtree.getDevicesNum(new PartialPath("root.**"));
+    } catch (MetadataException e) {
+      logger.error("get deviceNum error", e);
+    }
+    return 0;
+  }
+
+  public long getStorageGroupNumber() {
+    try {
+      return mtree.getStorageGroupNum(new PartialPath("root.**"));
+    } catch (MetadataException e) {
+      logger.error("get storageGroupNum error", e);
+    }
+    return 0;
+  }
 
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      startStatisticCounts();
-      MetricService.getInstance()
-          .getOrCreateAutoGauge(
-              Metric.MEM.toString(),
-              MetricLevel.IMPORTANT,
-              mtree,
-              RamUsageEstimator::sizeOf,
-              Tag.NAME.toString(),
-              "mtree");
-    }
-  }
-
-  private void startStatisticCounts() {
-    MetricService.getInstance()
-        .getOrCreateAutoGauge(
-            Metric.QUANTITY.toString(),
-            MetricLevel.IMPORTANT,
-            totalNormalSeriesNumber,
-            AtomicLong::get,
-            Tag.NAME.toString(),
-            "timeSeries",
-            Tag.TYPE.toString(),
-            "normal");
-
-    MetricService.getInstance()
-        .getOrCreateAutoGauge(
-            Metric.QUANTITY.toString(),
-            MetricLevel.IMPORTANT,
-            totalTemplateSeriesNumber,
-            AtomicLong::get,
-            Tag.NAME.toString(),
-            "timeSeries",
-            Tag.TYPE.toString(),
-            "template");
-
-    MetricService.getInstance()
-        .getOrCreateAutoGauge(
-            Metric.QUANTITY.toString(),
-            MetricLevel.IMPORTANT,
-            mtree,
-            tree -> {
-              try {
-                return tree.getDevicesNum(new PartialPath("root.**"));
-              } catch (MetadataException e) {
-                logger.error("get deviceNum error", e);
-              }
-              return 0;
-            },
-            Tag.NAME.toString(),
-            "device",
-            Tag.TYPE.toString(),
-            "total");
-
-    MetricService.getInstance()
-        .getOrCreateAutoGauge(
-            Metric.QUANTITY.toString(),
-            MetricLevel.IMPORTANT,
-            mtree,
-            tree -> {
-              try {
-                return tree.getStorageGroupNum(new PartialPath("root.**"));
-              } catch (MetadataException e) {
-                logger.error("get storageGroupNum error", e);
-              }
-              return 0;
-            },
-            Tag.NAME.toString(),
-            "storageGroup",
-            Tag.TYPE.toString(),
-            "total");
+  public long getMtreeSize() {
+    return RamUsageEstimator.sizeOf(mtree);
   }
 
   private void forceMlog() {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/metadata/MManagerMetrics.java 
b/server/src/main/java/org/apache/iotdb/db/metadata/MManagerMetrics.java
new file mode 100644
index 0000000000..999796df95
--- /dev/null
+++ b/server/src/main/java/org/apache/iotdb/db/metadata/MManagerMetrics.java
@@ -0,0 +1,134 @@
+/*
+ * 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.metadata;
+
+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.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+public class MManagerMetrics implements IMetricSet {
+  private MManager mManager;
+
+  public MManagerMetrics(MManager mManager) {
+    this.mManager = mManager;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            mManager,
+            MManager::getNormalSeriesNumber,
+            Tag.NAME.toString(),
+            "timeSeries",
+            Tag.TYPE.toString(),
+            "normal");
+
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            mManager,
+            MManager::getTemplateSeriesNumber,
+            Tag.NAME.toString(),
+            "timeSeries",
+            Tag.TYPE.toString(),
+            "template");
+
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            mManager,
+            MManager::getDeviceNumber,
+            Tag.NAME.toString(),
+            "device",
+            Tag.TYPE.toString(),
+            "total");
+
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.QUANTITY.toString(),
+            MetricLevel.IMPORTANT,
+            mManager,
+            MManager::getStorageGroupNumber,
+            Tag.NAME.toString(),
+            "storageGroup",
+            Tag.TYPE.toString(),
+            "total");
+
+    MetricService.getInstance()
+        .getOrCreateAutoGauge(
+            Metric.MEM.toString(),
+            MetricLevel.IMPORTANT,
+            mManager,
+            MManager::getMtreeSize,
+            Tag.NAME.toString(),
+            "mtree");
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
+            Metric.QUANTITY.toString(),
+            Tag.NAME.toString(),
+            "timeSeries",
+            Tag.TYPE.toString(),
+            "normal");
+
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
+            Metric.QUANTITY.toString(),
+            Tag.NAME.toString(),
+            "timeSeries",
+            Tag.TYPE.toString(),
+            "template");
+
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
+            Metric.QUANTITY.toString(),
+            Tag.NAME.toString(),
+            "device",
+            Tag.TYPE.toString(),
+            "total");
+
+    MetricService.getInstance()
+        .remove(
+            MetricType.GAUGE,
+            Metric.QUANTITY.toString(),
+            Tag.NAME.toString(),
+            "storageGroup",
+            Tag.TYPE.toString(),
+            "total");
+
+    MetricService.getInstance()
+        .remove(MetricType.GAUGE, Metric.MEM.toString(), Tag.NAME.toString(), 
"mtree");
+  }
+}
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 99c40ab4f5..7ce306fac2 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
@@ -24,10 +24,6 @@ import org.apache.iotdb.db.concurrent.ThreadName;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
 import org.apache.iotdb.db.rescon.AbstractPoolManager;
 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;
 import org.slf4j.LoggerFactory;
@@ -51,28 +47,15 @@ public class RawQueryReadTaskPoolManager extends 
AbstractPoolManager {
     pool =
         IoTDBThreadPoolFactory.newFixedThreadPool(
             threadCnt, ThreadName.SUB_RAW_QUERY_SERVICE.getName());
-    if 
(MetricConfigDescriptor.getInstance().getMetricConfig().getEnableMetric()) {
-      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");
-    }
+    MetricService.getInstance().addMetricSet(new 
RawQueryReadTaskPoolManagerMetrics(this));
+  }
+
+  public long getActiveCount() {
+    return ((ThreadPoolExecutor) pool).getActiveCount();
+  }
+
+  public long getWaitingCount() {
+    return ((ThreadPoolExecutor) pool).getQueue().size();
   }
 
   public static RawQueryReadTaskPoolManager getInstance() {
diff --git 
a/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManagerMetrics.java
 
b/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManagerMetrics.java
new file mode 100644
index 0000000000..858fd592d9
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/query/pool/RawQueryReadTaskPoolManagerMetrics.java
@@ -0,0 +1,92 @@
+/*
+ * 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.query.pool;
+
+import org.apache.iotdb.db.concurrent.ThreadName;
+import org.apache.iotdb.db.service.metrics.enums.Metric;
+import org.apache.iotdb.db.service.metrics.enums.Tag;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Objects;
+
+public class RawQueryReadTaskPoolManagerMetrics implements IMetricSet {
+  private RawQueryReadTaskPoolManager rawQueryReadTaskPoolManager;
+
+  public RawQueryReadTaskPoolManagerMetrics(
+      RawQueryReadTaskPoolManager rawQueryReadTaskPoolManager) {
+    this.rawQueryReadTaskPoolManager = rawQueryReadTaskPoolManager;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
+        Metric.QUEUE.toString(),
+        MetricLevel.IMPORTANT,
+        rawQueryReadTaskPoolManager,
+        RawQueryReadTaskPoolManager::getActiveCount,
+        Tag.NAME.toString(),
+        ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
+        Tag.STATUS.toString(),
+        "running");
+    metricService.getOrCreateAutoGauge(
+        Metric.QUEUE.toString(),
+        MetricLevel.IMPORTANT,
+        rawQueryReadTaskPoolManager,
+        RawQueryReadTaskPoolManager::getWaitingCount,
+        Tag.NAME.toString(),
+        ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
+        Tag.STATUS.toString(),
+        "waiting");
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.QUEUE.toString(),
+        Tag.NAME.toString(),
+        ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
+        Tag.STATUS.toString(),
+        "running");
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.QUEUE.toString(),
+        Tag.NAME.toString(),
+        ThreadName.SUB_RAW_QUERY_SERVICE.getName(),
+        Tag.STATUS.toString(),
+        "waiting");
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    RawQueryReadTaskPoolManagerMetrics that = 
(RawQueryReadTaskPoolManagerMetrics) o;
+    return Objects.equals(rawQueryReadTaskPoolManager, 
that.rawQueryReadTaskPoolManager);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(rawQueryReadTaskPoolManager);
+  }
+}
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 0c9c9c7dd2..1333674805 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
@@ -137,7 +137,6 @@ public class IoTDB implements IoTDBMBean {
 
     Runtime.getRuntime().addShutdownHook(new IoTDBShutdownHook());
     setUncaughtExceptionHandler();
-    registerManager.register(MetricService.getInstance());
     logger.info("recover the schema...");
     initMManager();
     initServiceProvider();
@@ -181,9 +180,7 @@ public class IoTDB implements IoTDBMBean {
     registerManager.register(SettleService.getINSTANCE());
     registerManager.register(TriggerRegistrationService.getInstance());
     registerManager.register(ContinuousQueryService.getInstance());
-
-    // start reporter
-    MetricService.getInstance().startAllReporter();
+    registerManager.register(MetricService.getInstance());
 
     logger.info("Congratulation, IoTDB is set up successfully. Now, enjoy 
yourself!");
   }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java 
b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
index 3ee0fd34c6..923e23e304 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/service/metrics/MetricService.java
@@ -29,10 +29,10 @@ import 
org.apache.iotdb.db.service.metrics.predefined.ProcessMetrics;
 import org.apache.iotdb.db.service.metrics.predefined.SystemMetrics;
 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.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.metricsets.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.metricsets.predefined.jvm.JvmMetrics;
+import org.apache.iotdb.metrics.metricsets.predefined.logback.LogbackMetrics;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,6 +60,12 @@ public class MetricService extends AbstractMetricService 
implements MetricServic
     }
   }
 
+  public void restart() {
+    logger.info("Restart metric service.");
+    restartService();
+    logger.info("Finish restart metric service.");
+  }
+
   @Override
   public void stop() {
     if (isEnable()) {
@@ -70,12 +76,6 @@ public class MetricService extends AbstractMetricService 
implements MetricServic
     }
   }
 
-  @Override
-  public void restartService() throws StartupException {
-    stopService();
-    startService();
-  }
-
   @Override
   public void enablePredefinedMetrics(PredefinedMetric metric) {
     IMetricSet metricSet;
@@ -99,7 +99,7 @@ public class MetricService extends AbstractMetricService 
implements MetricServic
         logger.error("Unknown predefined metrics: {}", metric);
         return;
     }
-    metricSet.bindTo(metricManager);
+    metricSet.bindTo(this);
   }
 
   @Override
@@ -117,14 +117,13 @@ public class MetricService extends AbstractMetricService 
implements MetricServic
             isEnableMetric = false;
             break;
           case RESTART_METRIC:
-            stop();
             isEnableMetric = true;
-            start();
+            restart();
             break;
           case RESTART_REPORTER:
-            compositeReporter.stopAll();
+            stopAllReporter();
             loadReporter();
-            compositeReporter.startAll();
+            startAllReporter();
             logger.info("Finish restart metric reporters.");
             break;
           case NOTHING:
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 17921819be..f7da8eeb7b 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
@@ -21,108 +21,226 @@ package org.apache.iotdb.db.service.metrics.predefined;
 
 import org.apache.iotdb.db.conf.IoTDBConstant;
 import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.apache.iotdb.db.conf.directories.DirectoryManager;
 import org.apache.iotdb.db.service.metrics.enums.Metric;
 import org.apache.iotdb.db.service.metrics.enums.Tag;
 import org.apache.iotdb.db.utils.FileUtils;
-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.AbstractMetricService;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.File;
+import java.io.UncheckedIOException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Stream;
 
 public class FileMetrics implements IMetricSet {
-  @Override
-  public void bindTo(AbstractMetricManager metricManager) {
-    String walDir = DirectoryManager.getInstance().getWALFolder();
-    metricManager.getOrCreateAutoGauge(
+  private static final Logger logger = 
LoggerFactory.getLogger(FileMetrics.class);
+  private Future<?> currentServiceFuture;
+  private final ScheduledExecutorService service = 
Executors.newSingleThreadScheduledExecutor();
+  private long walFileTotalSize = 0L;
+  private long walFileTotalCount = 0L;
+  private long sequenceFileTotalSize = 0L;
+  private long sequenceFileTotalCount = 0L;
+  private long unsequenceFileTotalSize = 0L;
+  private long unsequenceFileTotalCount = 0L;
+
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
         Metric.FILE_SIZE.toString(),
         MetricLevel.IMPORTANT,
-        walDir,
-        FileUtils::getDirSize,
+        this,
+        FileMetrics::getWalFileTotalSize,
         Tag.NAME.toString(),
         "wal");
-
-    String[] dataDirs = 
IoTDBDescriptor.getInstance().getConfig().getDataDirs();
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.FILE_SIZE.toString(),
         MetricLevel.IMPORTANT,
-        dataDirs,
-        value ->
-            Stream.of(value)
-                .mapToLong(
-                    dir -> {
-                      dir += File.separator + 
IoTDBConstant.SEQUENCE_FLODER_NAME;
-                      return FileUtils.getDirSize(dir);
-                    })
-                .sum(),
+        this,
+        FileMetrics::getSequenceFileTotalSize,
         Tag.NAME.toString(),
         "seq");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.FILE_SIZE.toString(),
         MetricLevel.IMPORTANT,
-        dataDirs,
-        value ->
-            Stream.of(value)
-                .mapToLong(
-                    dir -> {
-                      dir += File.separator + 
IoTDBConstant.UNSEQUENCE_FLODER_NAME;
-                      return FileUtils.getDirSize(dir);
-                    })
-                .sum(),
+        this,
+        FileMetrics::getUnsequenceFileTotalSize,
         Tag.NAME.toString(),
         "unseq");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.FILE_COUNT.toString(),
         MetricLevel.IMPORTANT,
-        walDir,
-        value -> {
-          File walFolder = new File(value);
-          if (walFolder.exists() && walFolder.isDirectory()) {
-            return org.apache.commons.io.FileUtils.listFiles(new File(value), 
null, true).size();
-          }
-          return 0L;
-        },
+        this,
+        FileMetrics::getWalFileTotalCount,
         Tag.NAME.toString(),
         "wal");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.FILE_COUNT.toString(),
         MetricLevel.IMPORTANT,
-        dataDirs,
-        value ->
-            Stream.of(value)
-                .mapToLong(
-                    dir -> {
-                      dir += File.separator + 
IoTDBConstant.SEQUENCE_FLODER_NAME;
-                      return org.apache.commons.io.FileUtils.listFiles(
-                              new File(dir), new String[] {"tsfile"}, true)
-                          .size();
-                    })
-                .sum(),
+        this,
+        FileMetrics::getSequenceFileTotalCount,
         Tag.NAME.toString(),
         "seq");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.FILE_COUNT.toString(),
         MetricLevel.IMPORTANT,
-        dataDirs,
-        value ->
-            Stream.of(value)
-                .mapToLong(
-                    dir -> {
-                      dir += File.separator + 
IoTDBConstant.UNSEQUENCE_FLODER_NAME;
-                      return org.apache.commons.io.FileUtils.listFiles(
-                              new File(dir), new String[] {"tsfile"}, true)
-                          .size();
-                    })
-                .sum(),
+        this,
+        FileMetrics::getUnsequenceFileTotalCount,
         Tag.NAME.toString(),
         "unseq");
+
+    // finally start to update the value of some metrics in async way
+    if (metricService.isEnable() && null != currentServiceFuture) {
+      currentServiceFuture =
+          service.scheduleAtFixedRate(
+              this::collect,
+              1,
+              MetricConfigDescriptor.getInstance()
+                  .getMetricConfig()
+                  .getAsyncCollectPeriodInSecond(),
+              TimeUnit.SECONDS);
+    }
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.FILE;
+  public void unbindFrom(AbstractMetricService metricService) {
+    // first stop to update the value of some metrics in async way
+    if (currentServiceFuture != null) {
+      currentServiceFuture.cancel(false);
+      currentServiceFuture = null;
+    }
+
+    metricService.remove(MetricType.GAUGE, Metric.FILE_SIZE.toString(), 
Tag.NAME.toString(), "wal");
+    metricService.remove(MetricType.GAUGE, Metric.FILE_SIZE.toString(), 
Tag.NAME.toString(), "seq");
+    metricService.remove(
+        MetricType.GAUGE, Metric.FILE_SIZE.toString(), Tag.NAME.toString(), 
"unseq");
+    metricService.remove(
+        MetricType.GAUGE, Metric.FILE_COUNT.toString(), Tag.NAME.toString(), 
"wal");
+    metricService.remove(
+        MetricType.GAUGE, Metric.FILE_COUNT.toString(), Tag.NAME.toString(), 
"seq");
+    metricService.remove(
+        MetricType.GAUGE, Metric.FILE_COUNT.toString(), Tag.NAME.toString(), 
"unseq");
+  }
+
+  private void collect() {
+    String[] dataDirs = 
IoTDBDescriptor.getInstance().getConfig().getDataDirs();
+    String walDirs = IoTDBDescriptor.getInstance().getConfig().getWalDir();
+    walFileTotalSize = FileUtils.getDirSize(walDirs);
+    sequenceFileTotalSize =
+        Stream.of(dataDirs)
+            .mapToLong(
+                dir -> {
+                  dir += File.separator + IoTDBConstant.SEQUENCE_FLODER_NAME;
+                  return FileUtils.getDirSize(dir);
+                })
+            .sum();
+    unsequenceFileTotalSize =
+        Stream.of(dataDirs)
+            .mapToLong(
+                dir -> {
+                  dir += File.separator + IoTDBConstant.UNSEQUENCE_FLODER_NAME;
+                  return FileUtils.getDirSize(dir);
+                })
+            .sum();
+    walFileTotalCount =
+        Stream.of(walDirs)
+            .mapToLong(
+                dir -> {
+                  File walFolder = new File(dir);
+                  if (walFolder.exists()) {
+                    File[] walNodeFolders = 
walFolder.listFiles(File::isDirectory);
+                    long result = 0L;
+                    if (null != walNodeFolders) {
+                      for (File walNodeFolder : walNodeFolders) {
+                        if (walNodeFolder.exists() && 
walNodeFolder.isDirectory()) {
+                          try {
+                            result +=
+                                
org.apache.commons.io.FileUtils.listFiles(walFolder, null, true)
+                                    .size();
+                          } catch (UncheckedIOException exception) {
+                            // do nothing
+                            logger.debug(
+                                "Failed when count wal folder {}: ",
+                                walNodeFolder.getName(),
+                                exception);
+                          }
+                        }
+                      }
+                    }
+                    return result;
+                  } else {
+                    return 0L;
+                  }
+                })
+            .sum();
+    sequenceFileTotalCount =
+        Stream.of(dataDirs)
+            .mapToLong(
+                dir -> {
+                  dir += File.separator + IoTDBConstant.SEQUENCE_FLODER_NAME;
+                  File folder = new File(dir);
+                  if (folder.exists()) {
+                    try {
+                      return org.apache.commons.io.FileUtils.listFiles(
+                              new File(dir), new String[] {"tsfile"}, true)
+                          .size();
+                    } catch (UncheckedIOException exception) {
+                      // do nothing
+                      logger.debug("Failed when count sequence tsfile: ", 
exception);
+                    }
+                  }
+                  return 0L;
+                })
+            .sum();
+    unsequenceFileTotalCount =
+        Stream.of(dataDirs)
+            .mapToLong(
+                dir -> {
+                  dir += File.separator + IoTDBConstant.UNSEQUENCE_FLODER_NAME;
+                  File folder = new File(dir);
+                  if (folder.exists()) {
+                    try {
+                      return org.apache.commons.io.FileUtils.listFiles(
+                              new File(dir), new String[] {"tsfile"}, true)
+                          .size();
+                    } catch (UncheckedIOException exception) {
+                      // do nothing
+                      logger.debug("Failed when count unsequence tsfile: ", 
exception);
+                    }
+                  }
+                  return 0L;
+                })
+            .sum();
+  }
+
+  public long getWalFileTotalSize() {
+    return walFileTotalSize;
+  }
+
+  public long getWalFileTotalCount() {
+    return walFileTotalCount;
+  }
+
+  public long getSequenceFileTotalSize() {
+    return sequenceFileTotalSize;
+  }
+
+  public long getSequenceFileTotalCount() {
+    return sequenceFileTotalCount;
+  }
+
+  public long getUnsequenceFileTotalSize() {
+    return unsequenceFileTotalSize;
+  }
+
+  public long getUnsequenceFileTotalCount() {
+    return unsequenceFileTotalCount;
   }
 }
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 2ab82ee686..1397523d53 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.AbstractMetricManager;
-import org.apache.iotdb.metrics.predefined.IMetricSet;
-import org.apache.iotdb.metrics.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import com.sun.management.OperatingSystemMXBean;
 
@@ -41,20 +41,23 @@ public class ProcessMetrics implements IMetricSet {
   }
 
   @Override
-  public void bindTo(AbstractMetricManager metricManager) {
-    collectProcessCPUInfo(metricManager);
-    collectProcessMemInfo(metricManager);
-    collectProcessStatusInfo(metricManager);
-    collectThreadInfo(metricManager);
+  public void bindTo(AbstractMetricService metricService) {
+    collectProcessCPUInfo(metricService);
+    collectProcessMemInfo(metricService);
+    collectProcessStatusInfo(metricService);
+    collectThreadInfo(metricService);
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.PROCESS;
+  public void unbindFrom(AbstractMetricService metricService) {
+    removeProcessCPUInfo(metricService);
+    removeProcessMemInfo(metricService);
+    removeProcessStatusInfo(metricService);
+    removeThreadInfo(metricService);
   }
 
-  private void collectProcessCPUInfo(AbstractMetricManager metricManager) {
-    metricManager.getOrCreateAutoGauge(
+  private void collectProcessCPUInfo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_CPU_LOAD.toString(),
         MetricLevel.CORE,
         sunOsMXBean,
@@ -62,7 +65,7 @@ public class ProcessMetrics implements IMetricSet {
         Tag.NAME.toString(),
         "process");
 
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_CPU_TIME.toString(),
         MetricLevel.CORE,
         sunOsMXBean,
@@ -71,37 +74,45 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
-  private void collectProcessMemInfo(AbstractMetricManager metricManager) {
+  private void removeProcessCPUInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_CPU_LOAD.toString(), 
Tag.NAME.toString(), "process");
+
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_CPU_TIME.toString(), 
Tag.NAME.toString(), "process");
+  }
+
+  private void collectProcessMemInfo(AbstractMetricService metricService) {
     Runtime runtime = Runtime.getRuntime();
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_MAX_MEM.toString(),
         MetricLevel.CORE,
         runtime,
         a -> runtime.maxMemory(),
         Tag.NAME.toString(),
         "process");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_TOTAL_MEM.toString(),
         MetricLevel.CORE,
         runtime,
         a -> runtime.totalMemory(),
         Tag.NAME.toString(),
         "process");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_FREE_MEM.toString(),
         MetricLevel.CORE,
         runtime,
         a -> runtime.freeMemory(),
         Tag.NAME.toString(),
         "process");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_USED_MEM.toString(),
         MetricLevel.CORE,
         this,
         a -> getProcessUsedMemory(),
         Tag.NAME.toString(),
         "process");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_MEM_RATIO.toString(),
         MetricLevel.CORE,
         this,
@@ -110,8 +121,21 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
-  private void collectThreadInfo(AbstractMetricManager metricManager) {
-    metricManager.getOrCreateAutoGauge(
+  private void removeProcessMemInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_MAX_MEM.toString(), 
Tag.NAME.toString(), "process");
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_TOTAL_MEM.toString(), 
Tag.NAME.toString(), "process");
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_FREE_MEM.toString(), 
Tag.NAME.toString(), "process");
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_USED_MEM.toString(), 
Tag.NAME.toString(), "process");
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_MEM_RATIO.toString(), 
Tag.NAME.toString(), "process");
+  }
+
+  private void collectThreadInfo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_THREADS_COUNT.toString(),
         MetricLevel.CORE,
         this,
@@ -120,8 +144,13 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
-  private void collectProcessStatusInfo(AbstractMetricManager metricManager) {
-    metricManager.getOrCreateAutoGauge(
+  private void removeThreadInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_THREADS_COUNT.toString(), 
Tag.NAME.toString(), "process");
+  }
+
+  private void collectProcessStatusInfo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
         Metric.PROCESS_STATUS.toString(),
         MetricLevel.CORE,
         this,
@@ -130,6 +159,11 @@ public class ProcessMetrics implements IMetricSet {
         "process");
   }
 
+  private void removeProcessStatusInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.PROCESS_STATUS.toString(), 
Tag.NAME.toString(), "process");
+  }
+
   private long getProcessUsedMemory() {
     return runtime.totalMemory() - runtime.freeMemory();
   }
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 2730ffd99a..8a380e182d 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
@@ -18,40 +18,68 @@
  */
 package org.apache.iotdb.db.service.metrics.predefined;
 
-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.metrics.AbstractMetricManager;
-import org.apache.iotdb.metrics.predefined.IMetricSet;
-import org.apache.iotdb.metrics.predefined.PredefinedMetric;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.config.MetricConfigDescriptor;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
 import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
 
 import com.sun.management.OperatingSystemMXBean;
 
 import java.io.File;
 import java.lang.management.ManagementFactory;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 public class SystemMetrics implements IMetricSet {
   private com.sun.management.OperatingSystemMXBean osMXBean;
+  private Future<?> currentServiceFuture;
+  private final ScheduledExecutorService service = 
Executors.newSingleThreadScheduledExecutor();
+  private long systemDiskTotalSpace = 0L;
+  private long systemDiskFreeSpace = 0L;
 
   public SystemMetrics() {
     osMXBean = (OperatingSystemMXBean) 
ManagementFactory.getOperatingSystemMXBean();
   }
 
   @Override
-  public void bindTo(AbstractMetricManager metricManager) {
-    collectSystemCpuInfo(metricManager);
-    collectSystemDiskInfo(metricManager);
-    collectSystemMEMInfo(metricManager);
+  public void bindTo(AbstractMetricService metricService) {
+    collectSystemCpuInfo(metricService);
+    collectSystemDiskInfo(metricService);
+    collectSystemMemInfo(metricService);
+
+    // finally start to update the value of some metrics in async way
+    if (metricService.isEnable() && null != currentServiceFuture) {
+      currentServiceFuture =
+          service.scheduleAtFixedRate(
+              this::collect,
+              1,
+              MetricConfigDescriptor.getInstance()
+                  .getMetricConfig()
+                  .getAsyncCollectPeriodInSecond(),
+              TimeUnit.SECONDS);
+    }
   }
 
   @Override
-  public PredefinedMetric getType() {
-    return PredefinedMetric.SYSTEM;
+  public void unbindFrom(AbstractMetricService metricService) {
+    // first stop to update the value of some metrics in async way
+    if (currentServiceFuture != null) {
+      currentServiceFuture.cancel(false);
+      currentServiceFuture = null;
+    }
+
+    removeSystemCpuInfo(metricService);
+    removeSystemDiskInfo(metricService);
+    removeSystemMemInfo(metricService);
   }
 
-  private void collectSystemCpuInfo(AbstractMetricManager metricManager) {
-    metricManager.getOrCreateAutoGauge(
+  private void collectSystemCpuInfo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_CPU_LOAD.toString(),
         MetricLevel.CORE,
         osMXBean,
@@ -59,42 +87,50 @@ public class SystemMetrics implements IMetricSet {
         Tag.NAME.toString(),
         "system");
 
-    metricManager
+    metricService
         .getOrCreateGauge(
             Metric.SYS_CPU_CORES.toString(), MetricLevel.IMPORTANT, 
Tag.NAME.toString(), "system")
         .set(osMXBean.getAvailableProcessors());
   }
 
-  private void collectSystemMEMInfo(AbstractMetricManager metricManager) {
-    metricManager
+  private void removeSystemCpuInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.SYS_CPU_LOAD.toString(), Tag.NAME.toString(), 
"system");
+
+    metricService.remove(
+        MetricType.GAUGE, Metric.SYS_CPU_CORES.toString(), 
Tag.NAME.toString(), "system");
+  }
+
+  private void collectSystemMemInfo(AbstractMetricService metricService) {
+    metricService
         .getOrCreateGauge(
             Metric.SYS_TOTAL_PHYSICAL_MEMORY_SIZE.toString(),
             MetricLevel.CORE,
             Tag.NAME.toString(),
             "system")
         .set(osMXBean.getTotalPhysicalMemorySize());
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_FREE_PHYSICAL_MEMORY_SIZE.toString(),
         MetricLevel.CORE,
         osMXBean,
         a -> osMXBean.getFreePhysicalMemorySize(),
         Tag.NAME.toString(),
         "system");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_TOTAL_SWAP_SPACE_SIZE.toString(),
         MetricLevel.CORE,
         osMXBean,
         a -> osMXBean.getTotalSwapSpaceSize(),
         Tag.NAME.toString(),
         "system");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_FREE_SWAP_SPACE_SIZE.toString(),
         MetricLevel.CORE,
         osMXBean,
         a -> osMXBean.getFreeSwapSpaceSize(),
         Tag.NAME.toString(),
         "system");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_COMMITTED_VM_SIZE.toString(),
         MetricLevel.CORE,
         osMXBean,
@@ -103,39 +139,72 @@ public class SystemMetrics implements IMetricSet {
         "system");
   }
 
-  private void collectSystemDiskInfo(AbstractMetricManager metricManager) {
-    metricManager.getOrCreateAutoGauge(
+  private void removeSystemMemInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.SYS_TOTAL_PHYSICAL_MEMORY_SIZE.toString(),
+        Tag.NAME.toString(),
+        "system");
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.SYS_FREE_PHYSICAL_MEMORY_SIZE.toString(),
+        Tag.NAME.toString(),
+        "system");
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.SYS_TOTAL_SWAP_SPACE_SIZE.toString(),
+        Tag.NAME.toString(),
+        "system");
+    metricService.remove(
+        MetricType.GAUGE,
+        Metric.SYS_FREE_SWAP_SPACE_SIZE.toString(),
+        Tag.NAME.toString(),
+        "system");
+    metricService.remove(
+        MetricType.GAUGE, Metric.SYS_COMMITTED_VM_SIZE.toString(), 
Tag.NAME.toString(), "system");
+  }
+
+  private void collectSystemDiskInfo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_DISK_TOTAL_SPACE.toString(),
         MetricLevel.CORE,
         this,
-        a -> getSysDiskTotalSpace(),
+        SystemMetrics::getSystemDiskTotalSpace,
         Tag.NAME.toString(),
         "system");
-    metricManager.getOrCreateAutoGauge(
+    metricService.getOrCreateAutoGauge(
         Metric.SYS_DISK_FREE_SPACE.toString(),
         MetricLevel.CORE,
         this,
-        a -> getSysDickFreeSpace(),
+        SystemMetrics::getSystemDiskFreeSpace,
         Tag.NAME.toString(),
         "system");
-    String[] dataDirs = 
IoTDBDescriptor.getInstance().getConfig().getDataDirs();
   }
 
-  private long getSysDiskTotalSpace() {
-    File[] files = File.listRoots();
-    long sysTotalSpace = 0L;
-    for (File file : files) {
-      sysTotalSpace += file.getTotalSpace();
-    }
-    return sysTotalSpace;
+  private void removeSystemDiskInfo(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.SYS_DISK_TOTAL_SPACE.toString(), 
Tag.NAME.toString(), "system");
+    metricService.remove(
+        MetricType.GAUGE, Metric.SYS_DISK_FREE_SPACE.toString(), 
Tag.NAME.toString(), "system");
   }
 
-  private long getSysDickFreeSpace() {
+  private void collect() {
     File[] files = File.listRoots();
+    long sysTotalSpace = 0L;
     long sysFreeSpace = 0L;
     for (File file : files) {
+      sysTotalSpace += file.getTotalSpace();
       sysFreeSpace += file.getFreeSpace();
     }
-    return sysFreeSpace;
+    systemDiskTotalSpace = sysTotalSpace;
+    systemDiskFreeSpace = sysFreeSpace;
+  }
+
+  public long getSystemDiskTotalSpace() {
+    return systemDiskTotalSpace;
+  }
+
+  public long getSystemDiskFreeSpace() {
+    return systemDiskFreeSpace;
   }
 }
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 94302536fc..6761c0d1c9 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
@@ -17,29 +17,28 @@
 package org.apache.iotdb.db.service.thrift.handler;
 
 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.TSServiceImpl;
-import org.apache.iotdb.metrics.utils.MetricLevel;
 
 import org.apache.thrift.protocol.TProtocol;
 import org.apache.thrift.server.ServerContext;
 import org.apache.thrift.server.TServerEventHandler;
 import org.apache.thrift.transport.TTransport;
 
+import java.util.concurrent.atomic.AtomicLong;
+
 public class RPCServiceThriftHandler implements TServerEventHandler {
   private TSServiceImpl serviceImpl;
+  private AtomicLong thriftConnectionNumber = new AtomicLong(0);
 
   public RPCServiceThriftHandler(TSServiceImpl serviceImpl) {
     this.serviceImpl = serviceImpl;
+    MetricService.getInstance()
+        .addMetricSet(new 
RPCServiceThriftHandlerMetrics(thriftConnectionNumber));
   }
 
   @Override
   public ServerContext createContext(TProtocol arg0, TProtocol arg1) {
-    MetricService.getInstance()
-        .getOrCreateGauge(
-            Metric.THRIFT_CONNECTIONS.toString(), MetricLevel.CORE, 
Tag.NAME.toString(), "RPC")
-        .incr(1L);
+    thriftConnectionNumber.incrementAndGet();
     return null;
   }
 
@@ -47,10 +46,7 @@ public class RPCServiceThriftHandler implements 
TServerEventHandler {
   public void deleteContext(ServerContext arg0, TProtocol arg1, TProtocol 
arg2) {
     // release query resources.
     serviceImpl.handleClientExit();
-    MetricService.getInstance()
-        .getOrCreateGauge(
-            Metric.THRIFT_CONNECTIONS.toString(), MetricLevel.CORE, 
Tag.NAME.toString(), "RPC")
-        .decr(1L);
+    thriftConnectionNumber.decrementAndGet();
   }
 
   @Override
diff --git 
a/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandlerMetrics.java
 
b/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandlerMetrics.java
new file mode 100644
index 0000000000..0287d2b522
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/service/thrift/handler/RPCServiceThriftHandlerMetrics.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.service.thrift.handler;
+
+import org.apache.iotdb.db.service.metrics.enums.Metric;
+import org.apache.iotdb.db.service.metrics.enums.Tag;
+import org.apache.iotdb.metrics.AbstractMetricService;
+import org.apache.iotdb.metrics.metricsets.IMetricSet;
+import org.apache.iotdb.metrics.utils.MetricLevel;
+import org.apache.iotdb.metrics.utils.MetricType;
+
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class RPCServiceThriftHandlerMetrics implements IMetricSet {
+  private AtomicLong thriftConnectionNumber;
+
+  public RPCServiceThriftHandlerMetrics(AtomicLong thriftConnectionNumber) {
+    this.thriftConnectionNumber = thriftConnectionNumber;
+  }
+
+  @Override
+  public void bindTo(AbstractMetricService metricService) {
+    metricService.getOrCreateAutoGauge(
+        Metric.THRIFT_CONNECTIONS.toString(),
+        MetricLevel.CORE,
+        thriftConnectionNumber,
+        AtomicLong::get,
+        Tag.NAME.toString(),
+        "RPC");
+  }
+
+  @Override
+  public void unbindFrom(AbstractMetricService metricService) {
+    metricService.remove(
+        MetricType.GAUGE, Metric.THRIFT_CONNECTIONS.toString(), 
Tag.NAME.toString(), "RPC");
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    RPCServiceThriftHandlerMetrics that = (RPCServiceThriftHandlerMetrics) o;
+    return Objects.equals(thriftConnectionNumber, that.thriftConnectionNumber);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(thriftConnectionNumber);
+  }
+}
diff --git 
a/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java 
b/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
index f1bca32b99..a7db0093f5 100644
--- a/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/metric/MetricServiceTest.java
@@ -61,7 +61,6 @@ public class MetricServiceTest {
       metricConfig.setMetricLevel(MetricLevel.IMPORTANT);
       metricService = new DoNothingMetricService();
       metricService.startService();
-      metricService.startAllReporter();
 
       // test metric service
       assertTrue(metricService.isEnable());


Reply via email to