You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2023/12/01 08:22:18 UTC

(servicecomb-java-chassis) branch master updated (d5f5714d1 -> 32397b91e)

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

liubao pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


    from d5f5714d1 fix: fix loaded variable not assigned (#4065)
     new 7bc6d7f84 [SCB-2838]using micrometer to replace spectator part1: MetricsInitializer
     new a16d5bd40 [SCB-2838]using micrometer to replace spectator part2: InvocationMeter
     new 611517baf [SCB-2838]using micrometer to replace spectator part3: EndpointMeter
     new 07e85f0ac [SCB-2838]using micrometer to replace spectator part3: OsMeter
     new 1ac6afbfe [SCB-2838]using micrometer to replace spectator part3: ThreadPool
     new 82d443243 [SCB-2838]using micrometer to replace spectator part4: remove spectator and fix UT
     new 3b349b3ef [SCB-2838]using micrometer to replace spectator part5: configure meter registry
     new 26b990fd5 [SCB-2838]using micrometer to replace spectator part6: thread pool and endpoint improvement
     new a88817437 [SCB-2838]using micrometer to replace spectator part7: use step histogram
     new f9b3c9f16 [SCB-2838]fix test case in linux not mock
     new 32397b91e [SCB-2838]fix checkstyle

The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 dependencies/default/pom.xml                       |   7 -
 foundations/foundation-metrics/pom.xml             |   4 +-
 .../com/netflix/spectator/api/SpectatorUtils.java  |  39 --
 .../foundation/metrics/MetricsBootstrap.java       |  38 +-
 .../foundation/metrics/MetricsInitializer.java     |   9 +-
 .../foundation/metrics/PolledEvent.java            |  17 +-
 .../metrics/meter/AbstractPeriodMeter.java         |  42 --
 .../metrics/meter/LatencyDistributionConfig.java   |   4 +-
 .../metrics/meter/LatencyDistributionMeter.java    |  60 ---
 .../metrics/meter/LatencyScopeMeter.java           |  12 +-
 .../foundation/metrics/meter/PeriodMeter.java      |  11 +-
 .../foundation/metrics/meter/SimpleTimer.java      |  93 -----
 .../publish/{spectator => }/DefaultTagFinder.java  |   7 +-
 .../{spectator => }/MeasurementGroupConfig.java    |   2 +-
 .../publish/{spectator => }/MeasurementNode.java   |  27 +-
 .../publish/{spectator => }/MeasurementTree.java   |  49 ++-
 .../metrics/publish/{spectator => }/TagFinder.java |   4 +-
 .../metrics/registry/GlobalRegistry.java           | 114 ------
 .../foundation/metrics/TestMetricsBootstrap.java   |  20 +-
 .../meter/TestLatencyDistributionMeter.java        |  47 ---
 .../foundation/metrics/meter/TestSimpleTimer.java  |  40 --
 .../publish/spectator/TestDefaultTagFinder.java    |  12 +-
 .../spectator/TestMeasurementGroupConfig.java      |   2 +
 .../publish/spectator/TestMeasurementNode.java     |  29 +-
 .../publish/spectator/TestMeasurementTree.java     |  39 +-
 .../metrics/publish/spectator/TestTagFinder.java   |   2 +
 foundations/foundation-test-scaffolding/pom.xml    |   4 +-
 .../metric/DefaultClientEndpointMetricManager.java |   5 +-
 .../monitor/MetricsMonitorDataProvider.java        |  29 +-
 .../ThreadPoolMonitorPublishModelFactory.java      |  84 ----
 .../metrics/core/DefaultRegistryInitializer.java   |  63 ---
 .../metrics/core/InvocationMetersInitializer.java  |  14 +-
 .../metrics/core/MetricsBootListener.java          |  11 +-
 .../metrics/core/MetricsCoreConfiguration.java     |  37 +-
 .../metrics/core/OsMetersInitializer.java          |  21 +-
 .../metrics/core/SimpleMeterRegistryExt.java       |  63 +++
 .../metrics/core/StepDistributionSummaryExt.java}  |  20 +-
 .../metrics/core/ThreadPoolMetersInitializer.java  |  43 +--
 .../metrics/core/VertxMetersInitializer.java       |  41 +-
 .../metrics/core/meter/ConsumerMeters.java         |   6 +-
 .../servicecomb/metrics/core/meter/EdgeMeters.java |   6 +-
 .../metrics/core/meter/ProducerMeters.java         |   6 +-
 .../ThreadPoolMonitorPublishModelFactory.java      |  71 ++++
 .../meter/invocation/AbstractInvocationMeter.java  | 111 +++---
 .../meter/invocation/AbstractInvocationMeters.java |  30 +-
 .../meter/invocation/ConsumerInvocationMeter.java  |  66 ++--
 .../meter/invocation/ConsumerInvocationMeters.java |  12 +-
 .../core/meter/invocation/EdgeInvocationMeter.java |  54 +--
 .../meter/invocation/EdgeInvocationMeters.java     |  12 +-
 .../meter/invocation/MeterInvocationConst.java     |   6 +-
 .../meter/invocation/ProducerInvocationMeter.java  |  69 ++--
 .../meter/invocation/ProducerInvocationMeters.java |  12 +-
 .../metrics/core/meter/os/CpuMeter.java            |  41 +-
 .../metrics/core/meter/os/NetMeter.java            |  60 ++-
 .../servicecomb/metrics/core/meter/os/OsMeter.java |  32 +-
 .../core/meter/os/cpu/AbstractCpuUsage.java        |  12 -
 .../metrics/core/meter/os/cpu/OsCpuUsage.java      |   5 +-
 .../metrics/core/meter/os/cpu/ProcessCpuUsage.java |   5 +-
 .../metrics/core/meter/os/net/InterfaceUsage.java  |  74 ++--
 .../metrics/core/meter/os/net/NetStat.java         |  10 +-
 .../metrics/core/meter/pool/ThreadPoolMeter.java   | 102 +++++
 .../metrics/core/meter/vertx/EndpointMeter.java    | 141 ++++---
 .../core/meter/vertx/HttpClientEndpointMeter.java  |  25 +-
 .../core/meter/vertx/HttpClientEndpointsMeter.java |  15 +-
 .../core/meter/vertx/ServerEndpointMeter.java      |  31 +-
 .../core/meter/vertx/ServerEndpointsMeter.java     |  12 +-
 .../core/meter/vertx/VertxEndpointsMeter.java      |  61 ++-
 .../AbstractMeasurementNodeLogPublisher.java       |   4 +-
 .../core/publish/ClientEndpointsLogPublisher.java  |   4 +-
 .../metrics/core/publish/DefaultLogPublisher.java  |  77 ++--
 .../metrics/core/publish/PublishModelFactory.java  |  30 +-
 .../metrics/core/publish/PublishUtils.java         |  18 +-
 .../core/publish/ServerEndpointsLogPublisher.java  |   4 +-
 .../core/publish/model/invocation/PerfInfo.java    |  16 +-
 .../servicecomb/metrics/core/AssertUtil.java       |  12 +-
 .../core/TestDefaultRegistryInitializer.java       |  73 ----
 .../core/TestInvocationMetersInitializer.java      | 430 +++++++++++++--------
 .../metrics/core/TestOsMeterInitializer.java       |  48 ++-
 .../core/TestThreadPoolMetersInitializer.java      |  58 ++-
 .../metrics/core/TestVertxMetersInitializer.java   |  42 +-
 .../metrics/core/meter/os/TestCpuMeter.java        |  42 +-
 .../metrics/core/meter/os/TestNetMeter.java        | 214 +++++-----
 .../metrics/core/meter/os/TestOsMeter.java         |  38 +-
 .../core/publish/TestDefaultLogPublisher.java      |  65 ++--
 .../publish/TestInvocationPublishModelFactory.java | 239 ++++++------
 .../metrics/core/publish/TestPublishUtils.java     |  19 +-
 .../publish/TestThreadPoolPublishModelFactory.java |  35 +-
 .../model/invocation/TestOperationPerf.java        |   4 +-
 .../model/invocation/TestOperationPerfGroup.java   |   4 +-
 .../publish/model/invocation/TestPerfInfo.java     |  16 +-
 .../core/publish/model/invocation/Utils.java       |  45 +--
 .../metrics/prometheus/PrometheusPublisher.java    |  43 +--
 .../prometheus/TestPrometheusPublisher.java        |  23 +-
 .../basic/integration/MetricsEndpointImpl.java     |  47 +--
 .../basic/integration/TestMetricsEndpointImpl.java |  49 +--
 95 files changed, 1844 insertions(+), 2107 deletions(-)
 delete mode 100644 foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
 delete mode 100644 foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
 delete mode 100644 foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java
 delete mode 100644 foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
 rename foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/{spectator => }/DefaultTagFinder.java (90%)
 rename foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/{spectator => }/MeasurementGroupConfig.java (95%)
 rename foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/{spectator => }/MeasurementNode.java (79%)
 rename foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/{spectator => }/MeasurementTree.java (52%)
 rename foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/{spectator => }/TagFinder.java (92%)
 delete mode 100644 foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
 delete mode 100644 foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java
 delete mode 100644 foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
 delete mode 100644 metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java
 delete mode 100644 metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java
 create mode 100644 metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/SimpleMeterRegistryExt.java
 copy metrics/metrics-core/src/{test/java/org/apache/servicecomb/metrics/core/AssertUtil.java => main/java/org/apache/servicecomb/metrics/core/StepDistributionSummaryExt.java} (59%)
 create mode 100644 metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
 create mode 100644 metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/pool/ThreadPoolMeter.java
 delete mode 100644 metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java


(servicecomb-java-chassis) 02/11: [SCB-2838]using micrometer to replace spectator part2: InvocationMeter

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit a16d5bd409c6c3246ed327b9fe0bc4b94820f6f4
Author: liubao <bi...@qq.com>
AuthorDate: Sat Nov 25 11:44:14 2023 +0800

    [SCB-2838]using micrometer to replace spectator part2: InvocationMeter
---
 .../metrics/meter/LatencyDistributionMeter.java    | 60 --------------
 .../meter/TestLatencyDistributionMeter.java        | 47 -----------
 .../meter/invocation/AbstractInvocationMeter.java  | 92 +++++++++-------------
 .../meter/invocation/AbstractInvocationMeters.java | 14 +---
 .../meter/invocation/ConsumerInvocationMeter.java  | 66 ++++++++--------
 .../meter/invocation/ConsumerInvocationMeters.java |  6 +-
 .../core/meter/invocation/EdgeInvocationMeter.java | 54 ++++++-------
 .../meter/invocation/EdgeInvocationMeters.java     |  6 +-
 .../meter/invocation/ProducerInvocationMeter.java  | 69 ++++++++--------
 .../meter/invocation/ProducerInvocationMeters.java |  6 +-
 10 files changed, 147 insertions(+), 273 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java
deleted file mode 100644
index 175c06b8e..000000000
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java
+++ /dev/null
@@ -1,60 +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.servicecomb.foundation.metrics.meter;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-
-public class LatencyDistributionMeter extends AbstractPeriodMeter {
-  private final List<LatencyScopeMeter> latencyScopeMeters = new ArrayList<>();
-
-  public LatencyDistributionMeter(Id id, String config) {
-    this.id = id;
-
-    LatencyDistributionConfig latencyDistributionConfig = new LatencyDistributionConfig(config);
-    for (LatencyScopeConfig scopeConfig : latencyDistributionConfig.getScopeConfigs()) {
-      latencyScopeMeters.add(new LatencyScopeMeter(id, scopeConfig));
-    }
-  }
-
-  public void record(long nanoLatency) {
-    if (nanoLatency < 0) {
-      return;
-    }
-
-    for (LatencyScopeMeter latencyScopeMeter : latencyScopeMeters) {
-      if (latencyScopeMeter.update(nanoLatency)) {
-        return;
-      }
-    }
-  }
-
-  @Override
-  public void calcMeasurements(long msNow, long secondInterval) {
-    List<Measurement> measurements = new ArrayList<>();
-    calcMeasurements(measurements, msNow, secondInterval);
-    allMeasurements = measurements;
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    latencyScopeMeters.forEach(latencyScopeMeter -> measurements.add(latencyScopeMeter.createMeasurement(msNow)));
-  }
-}
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java
deleted file mode 100644
index d5cd26074..000000000
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java
+++ /dev/null
@@ -1,47 +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.servicecomb.foundation.metrics.meter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-public class TestLatencyDistributionMeter {
-
-  @Test
-  public void testMeasure() {
-    Id id = Mockito.mock(Id.class);
-    LatencyDistributionMeter latencyDistributionMeter = new LatencyDistributionMeter(id, "0,1,3,10");
-    latencyDistributionMeter.record(TimeUnit.MILLISECONDS.toNanos(1L));
-    latencyDistributionMeter.record(TimeUnit.MILLISECONDS.toNanos(5L));
-    latencyDistributionMeter.record(TimeUnit.MILLISECONDS.toNanos(2L));
-    List<Measurement> measurements = new ArrayList<>();
-    latencyDistributionMeter.calcMeasurements(measurements, 0L, 0L);
-    Assertions.assertEquals(4, measurements.size());
-    Assertions.assertEquals(0, ((int) (measurements.get(0).value())));
-    Assertions.assertEquals(2, ((int) (measurements.get(1).value())));
-    Assertions.assertEquals(1, ((int) (measurements.get(2).value())));
-    Assertions.assertEquals(0, ((int) (measurements.get(3).value())));
-  }
-}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index 1ffbe068a..34ef22121 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -16,81 +16,65 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.time.Duration;
+import java.util.concurrent.TimeUnit;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
-import org.apache.servicecomb.foundation.metrics.meter.LatencyDistributionMeter;
-import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
-import io.micrometer.core.instrument.Measurement;
-
-
-public abstract class AbstractInvocationMeter extends AbstractPeriodMeter {
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.Timer;
 
+public abstract class AbstractInvocationMeter {
   //total time
-  private final SimpleTimer totalTimer;
+  private final Timer totalTimer;
 
   // prepare time
-  private final SimpleTimer prepareTimer;
-
-  // latency distribution
-  private final LatencyDistributionMeter latencyDistributionMeter;
+  private final Timer prepareTimer;
 
   protected final MetricsBootstrapConfig metricsBootstrapConfig;
 
-  public AbstractInvocationMeter(Id id, MetricsBootstrapConfig metricsBootstrapConfig) {
-    this.id = id;
+  public AbstractInvocationMeter(MeterRegistry meterRegistry, String name, Tags tags,
+      MetricsBootstrapConfig metricsBootstrapConfig) {
     this.metricsBootstrapConfig = metricsBootstrapConfig;
-    latencyDistributionMeter = createLatencyDistribution(MeterInvocationConst.TAG_LATENCY_DISTRIBUTION);
-    totalTimer = createStageTimer(InvocationStageTrace.STAGE_TOTAL);
-    prepareTimer = createStageTimer(InvocationStageTrace.STAGE_PREPARE);
-  }
 
-  protected LatencyDistributionMeter createLatencyDistribution(String tagValue) {
-    return new LatencyDistributionMeter(id.withTag(MeterInvocationConst.TAG_TYPE, tagValue),
-        metricsBootstrapConfig.getLatencyDistribution());
+    Timer.Builder totalBuilder = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_TOTAL));
+    if (!StringUtils.isEmpty(metricsBootstrapConfig.getLatencyDistribution())) {
+      totalBuilder.sla(toDuration(metricsBootstrapConfig.getLatencyDistribution()));
+    }
+    this.totalTimer = totalBuilder.register(meterRegistry);
+    this.prepareTimer = Timer.builder(name).tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE
+        , MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PREPARE)).register(meterRegistry);
   }
 
-  protected SimpleTimer createStageTimer(String stageValue) {
-    return createTimer(id.withTag(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE)
-        .withTag(MeterInvocationConst.TAG_STAGE, stageValue));
-  }
+  protected static Duration[] toDuration(String config) {
+    config = config.trim() + "," + Long.MAX_VALUE;
+    String[] array = config.split("\\s*,+\\s*");
+    Duration[] result = new Duration[array.length];
 
-  protected SimpleTimer createTimer(String tagKey, String tagValue) {
-    return createTimer(id.withTag(tagKey, tagValue));
-  }
+    for (int idx = 0; idx < array.length - 1; idx++) {
+      long msMin = Long.parseLong(array[idx]);
+      long msMax = Long.parseLong(array[idx + 1]);
+      if (msMin >= msMax) {
+        String msg = String.format("invalid latency scope, min=%s, max=%s.", array[idx], array[idx + 1]);
+        throw new IllegalStateException(msg);
+      }
+
+      result[idx] = Duration.ofMillis(msMin);
+    }
+    result[array.length - 1] = Duration.ofMillis(Long.MAX_VALUE);
 
-  protected SimpleTimer createTimer(Id timerId) {
-    return new SimpleTimer(timerId);
+    return result;
   }
 
   public void onInvocationFinish(InvocationFinishEvent event) {
     InvocationStageTrace stageTrace = event.getInvocation().getInvocationStageTrace();
-    latencyDistributionMeter.record(stageTrace.calcTotal());
-    totalTimer.record(stageTrace.calcTotal());
-    prepareTimer.record(stageTrace.calcPrepare());
-  }
-
-  @Override
-  public void calcMeasurements(long msNow, long secondInterval) {
-    List<Measurement> measurements = new ArrayList<>(3);
-    calcMeasurements(measurements, msNow, secondInterval);
-    allMeasurements = measurements;
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    latencyDistributionMeter.calcMeasurements(measurements, msNow, secondInterval);
-    totalTimer.calcMeasurements(measurements, msNow, secondInterval);
-    prepareTimer.calcMeasurements(measurements, msNow, secondInterval);
-  }
-
-  @Override
-  public boolean hasExpired() {
-    return super.hasExpired();
+    totalTimer.record(stageTrace.calcTotal(), TimeUnit.NANOSECONDS);
+    prepareTimer.record(stageTrace.calcPrepare(), TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
index ce9283e3d..6c696a570 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
@@ -25,10 +25,6 @@ import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.swagger.invocation.Response;
 
-import com.netflix.spectator.api.SpectatorUtils;
-
-import io.micrometer.core.instrument.Meter.Id;
-import io.micrometer.core.instrument.Meter.Type;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tags;
 
@@ -68,20 +64,16 @@ public abstract class AbstractInvocationMeters {
     }
 
     return metersMap.computeIfAbsent(keyBuilder.toString(), k -> {
-      Id id = new Id(MeterInvocationConst.INVOCATION_NAME, Tags.empty()
+      AbstractInvocationMeter meter = createMeter(MeterInvocationConst.INVOCATION_NAME, Tags.empty()
           .and(MeterInvocationConst.TAG_ROLE, invocationName)
           .and(MeterInvocationConst.TAG_TRANSPORT, invocation.getRealTransportName())
           .and(MeterInvocationConst.TAG_OPERATION, invocation.getMicroserviceQualifiedName())
-          .and(MeterInvocationConst.TAG_STATUS, String.valueOf(response.getStatusCode())),
-          null, null, Type.OTHER);
-
-      AbstractInvocationMeter meter = createMeter(id);
-      SpectatorUtils.registerMeter(registry, meter);
+          .and(MeterInvocationConst.TAG_STATUS, String.valueOf(response.getStatusCode())));
       return meter;
     });
   }
 
-  protected abstract AbstractInvocationMeter createMeter(Id id);
+  protected abstract AbstractInvocationMeter createMeter(String name, Tags tags);
 
   public void onInvocationStart(InvocationStartEvent event) {
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
index cc575ad3c..d0b4c08f7 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeter.java
@@ -16,34 +16,47 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.Timer;
 
 public class ConsumerInvocationMeter extends AbstractInvocationMeter {
-  private final SimpleTimer consumerEncodeRequestTimer;
+  private final Timer consumerEncodeRequestTimer;
 
-  private final SimpleTimer consumerDecodeResponseTimer;
+  private final Timer consumerDecodeResponseTimer;
 
-  private final SimpleTimer consumerGetConnectionTimer;
+  private final Timer consumerGetConnectionTimer;
 
-  private final SimpleTimer consumerSendRequestTimer;
+  private final Timer consumerSendRequestTimer;
 
-  private final SimpleTimer consumerWaitResponseTimer;
+  private final Timer consumerWaitResponseTimer;
 
-  public ConsumerInvocationMeter(Id id, MetricsBootstrapConfig metricsBootstrapConfig) {
-    super(id, metricsBootstrapConfig);
-    consumerSendRequestTimer = createStageTimer(InvocationStageTrace.STAGE_CONSUMER_SEND);
-    consumerGetConnectionTimer = createStageTimer(InvocationStageTrace.STAGE_CONSUMER_CONNECTION);
-    consumerEncodeRequestTimer = createStageTimer(InvocationStageTrace.STAGE_CONSUMER_ENCODE_REQUEST);
-    consumerDecodeResponseTimer = createStageTimer(InvocationStageTrace.STAGE_CONSUMER_DECODE_RESPONSE);
-    consumerWaitResponseTimer = createStageTimer(InvocationStageTrace.STAGE_CONSUMER_WAIT);
+  public ConsumerInvocationMeter(MeterRegistry meterRegistry, String name, Tags tags,
+      MetricsBootstrapConfig metricsBootstrapConfig) {
+    super(meterRegistry, name, tags, metricsBootstrapConfig);
+    consumerSendRequestTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_CONSUMER_SEND)).register(meterRegistry);
+    consumerGetConnectionTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_CONSUMER_CONNECTION)).register(meterRegistry);
+    consumerEncodeRequestTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_CONSUMER_ENCODE_REQUEST))
+        .register(meterRegistry);
+    consumerDecodeResponseTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_CONSUMER_DECODE_RESPONSE))
+        .register(meterRegistry);
+    consumerWaitResponseTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_CONSUMER_WAIT)).register(meterRegistry);
   }
 
   @Override
@@ -51,21 +64,10 @@ public class ConsumerInvocationMeter extends AbstractInvocationMeter {
     super.onInvocationFinish(event);
 
     InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
-    consumerEncodeRequestTimer.record(invocationStageTrace.calcConsumerEncodeRequest());
-    consumerSendRequestTimer.record(invocationStageTrace.calcConsumerSendRequest());
-    consumerGetConnectionTimer.record(invocationStageTrace.calcConnection());
-    consumerWaitResponseTimer.record(invocationStageTrace.calcWait());
-    consumerDecodeResponseTimer.record(invocationStageTrace.calcConsumerDecodeResponse());
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    super.calcMeasurements(measurements, msNow, secondInterval);
-
-    consumerSendRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
-    consumerGetConnectionTimer.calcMeasurements(measurements, msNow, secondInterval);
-    consumerEncodeRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
-    consumerWaitResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
-    consumerDecodeResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    consumerEncodeRequestTimer.record(invocationStageTrace.calcConsumerEncodeRequest(), TimeUnit.NANOSECONDS);
+    consumerSendRequestTimer.record(invocationStageTrace.calcConsumerSendRequest(), TimeUnit.NANOSECONDS);
+    consumerGetConnectionTimer.record(invocationStageTrace.calcConnection(), TimeUnit.NANOSECONDS);
+    consumerWaitResponseTimer.record(invocationStageTrace.calcWait(), TimeUnit.NANOSECONDS);
+    consumerDecodeResponseTimer.record(invocationStageTrace.calcConsumerDecodeResponse(), TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
index d46faa803..842122e08 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
@@ -18,8 +18,8 @@ package org.apache.servicecomb.metrics.core.meter.invocation;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 
-import io.micrometer.core.instrument.Meter.Id;
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
 public class ConsumerInvocationMeters extends AbstractInvocationMeters {
   public ConsumerInvocationMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
@@ -27,7 +27,7 @@ public class ConsumerInvocationMeters extends AbstractInvocationMeters {
   }
 
   @Override
-  protected AbstractInvocationMeter createMeter(Id id) {
-    return new ConsumerInvocationMeter(id, this.metricsBootstrapConfig);
+  protected AbstractInvocationMeter createMeter(String name, Tags tags) {
+    return new ConsumerInvocationMeter(registry, name, tags, this.metricsBootstrapConfig);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
index 89284ecd8..32fe7aa92 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeter.java
@@ -17,28 +17,37 @@
 
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.Timer;
 
 public class EdgeInvocationMeter extends ConsumerInvocationMeter {
-  private final SimpleTimer providerDecodeRequestTimer;
-
-  private final SimpleTimer providerEncodeResponseTimer;
-
-  private final SimpleTimer sendResponseTimer;
-
-  public EdgeInvocationMeter(Id id, MetricsBootstrapConfig metricsBootstrapConfig) {
-    super(id, metricsBootstrapConfig);
-    providerDecodeRequestTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_DECODE_REQUEST);
-    providerEncodeResponseTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_ENCODE_RESPONSE);
-    sendResponseTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_SEND);
+  private final Timer providerDecodeRequestTimer;
+
+  private final Timer providerEncodeResponseTimer;
+
+  private final Timer sendResponseTimer;
+
+  public EdgeInvocationMeter(MeterRegistry meterRegistry, String name, Tags tags,
+      MetricsBootstrapConfig metricsBootstrapConfig) {
+    super(meterRegistry, name, tags, metricsBootstrapConfig);
+    providerDecodeRequestTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_DECODE_REQUEST))
+        .register(meterRegistry);
+    providerEncodeResponseTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_ENCODE_RESPONSE))
+        .register(meterRegistry);
+    sendResponseTimer = Timer.builder(name).tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_SEND))
+        .register(meterRegistry);
   }
 
   @Override
@@ -46,17 +55,8 @@ public class EdgeInvocationMeter extends ConsumerInvocationMeter {
     super.onInvocationFinish(event);
     InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
 
-    providerDecodeRequestTimer.record(invocationStageTrace.calcProviderDecodeRequest());
-    providerEncodeResponseTimer.record(invocationStageTrace.calcProviderEncodeResponse());
-    sendResponseTimer.record(invocationStageTrace.calcProviderSendResponse());
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    super.calcMeasurements(measurements, msNow, secondInterval);
-
-    providerDecodeRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
-    providerEncodeResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
-    sendResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    providerDecodeRequestTimer.record(invocationStageTrace.calcProviderDecodeRequest(), TimeUnit.NANOSECONDS);
+    providerEncodeResponseTimer.record(invocationStageTrace.calcProviderEncodeResponse(), TimeUnit.NANOSECONDS);
+    sendResponseTimer.record(invocationStageTrace.calcProviderSendResponse(), TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
index 872a811b7..ecdbd3670 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
@@ -19,8 +19,8 @@ package org.apache.servicecomb.metrics.core.meter.invocation;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 
-import io.micrometer.core.instrument.Meter.Id;
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
 public class EdgeInvocationMeters extends ConsumerInvocationMeters {
   public EdgeInvocationMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
@@ -28,7 +28,7 @@ public class EdgeInvocationMeters extends ConsumerInvocationMeters {
   }
 
   @Override
-  protected AbstractInvocationMeter createMeter(Id id) {
-    return new EdgeInvocationMeter(id, metricsBootstrapConfig);
+  protected AbstractInvocationMeter createMeter(String name, Tags tags) {
+    return new EdgeInvocationMeter(registry, name, tags, metricsBootstrapConfig);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
index f5727613d..2ed55e5e0 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeter.java
@@ -16,35 +16,49 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.Timer;
 
 public class ProducerInvocationMeter extends AbstractInvocationMeter {
-  private final SimpleTimer executorQueueTimer;
+  private final Timer executorQueueTimer;
 
-  private final SimpleTimer executionTimer;
+  private final Timer executionTimer;
 
-  private final SimpleTimer providerDecodeRequestTimer;
+  private final Timer providerDecodeRequestTimer;
 
-  private final SimpleTimer providerEncodeResponseTimer;
+  private final Timer providerEncodeResponseTimer;
 
-  private final SimpleTimer sendResponseTimer;
+  private final Timer sendResponseTimer;
 
-  public ProducerInvocationMeter(Id id, MetricsBootstrapConfig metricsBootstrapConfig) {
-    super(id, metricsBootstrapConfig);
-
-    executorQueueTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_QUEUE);
-    executionTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_BUSINESS);
-    providerDecodeRequestTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_DECODE_REQUEST);
-    providerEncodeResponseTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_ENCODE_RESPONSE);
-    sendResponseTimer = createStageTimer(InvocationStageTrace.STAGE_PROVIDER_SEND);
+  public ProducerInvocationMeter(MeterRegistry meterRegistry, String name, Tags tags,
+      MetricsBootstrapConfig metricsBootstrapConfig) {
+    super(meterRegistry, name, tags, metricsBootstrapConfig);
+    executorQueueTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_QUEUE))
+        .register(meterRegistry);
+    executionTimer = Timer.builder(name).tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_BUSINESS))
+        .register(meterRegistry);
+    providerDecodeRequestTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_DECODE_REQUEST))
+        .register(meterRegistry);
+    providerEncodeResponseTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_ENCODE_RESPONSE))
+        .register(meterRegistry);
+    sendResponseTimer = Timer.builder(name)
+        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
+            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PROVIDER_SEND))
+        .register(meterRegistry);
   }
 
   @Override
@@ -52,21 +66,10 @@ public class ProducerInvocationMeter extends AbstractInvocationMeter {
     super.onInvocationFinish(event);
 
     InvocationStageTrace invocationStageTrace = event.getInvocation().getInvocationStageTrace();
-    executorQueueTimer.record(invocationStageTrace.calcQueue());
-    executionTimer.record(invocationStageTrace.calcBusinessExecute());
-    providerDecodeRequestTimer.record(invocationStageTrace.calcProviderDecodeRequest());
-    providerEncodeResponseTimer.record(invocationStageTrace.calcProviderEncodeResponse());
-    sendResponseTimer.record(invocationStageTrace.calcProviderSendResponse());
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    super.calcMeasurements(measurements, msNow, secondInterval);
-
-    executorQueueTimer.calcMeasurements(measurements, msNow, secondInterval);
-    executionTimer.calcMeasurements(measurements, msNow, secondInterval);
-    providerDecodeRequestTimer.calcMeasurements(measurements, msNow, secondInterval);
-    providerEncodeResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
-    sendResponseTimer.calcMeasurements(measurements, msNow, secondInterval);
+    executorQueueTimer.record(invocationStageTrace.calcQueue(), TimeUnit.NANOSECONDS);
+    executionTimer.record(invocationStageTrace.calcBusinessExecute(), TimeUnit.NANOSECONDS);
+    providerDecodeRequestTimer.record(invocationStageTrace.calcProviderDecodeRequest(), TimeUnit.NANOSECONDS);
+    providerEncodeResponseTimer.record(invocationStageTrace.calcProviderEncodeResponse(), TimeUnit.NANOSECONDS);
+    sendResponseTimer.record(invocationStageTrace.calcProviderSendResponse(), TimeUnit.NANOSECONDS);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
index 60e86493c..bf4f84104 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
@@ -18,8 +18,8 @@ package org.apache.servicecomb.metrics.core.meter.invocation;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 
-import io.micrometer.core.instrument.Meter.Id;
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
 public class ProducerInvocationMeters extends AbstractInvocationMeters {
   public ProducerInvocationMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
@@ -27,7 +27,7 @@ public class ProducerInvocationMeters extends AbstractInvocationMeters {
   }
 
   @Override
-  protected AbstractInvocationMeter createMeter(Id id) {
-    return new ProducerInvocationMeter(id, metricsBootstrapConfig);
+  protected AbstractInvocationMeter createMeter(String name, Tags tags) {
+    return new ProducerInvocationMeter(registry, name, tags, metricsBootstrapConfig);
   }
 }


(servicecomb-java-chassis) 09/11: [SCB-2838]using micrometer to replace spectator part7: use step histogram

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit a8881743729273aca14884d107217edc68d8626e
Author: liubao <bi...@qq.com>
AuthorDate: Fri Dec 1 14:47:20 2023 +0800

    [SCB-2838]using micrometer to replace spectator part7: use step histogram
---
 dependencies/default/pom.xml                       |   7 --
 .../metrics/publish/MeasurementTree.java           |  40 +++-----
 .../publish/spectator/TestMeasurementTree.java     |   4 +-
 .../metrics/core/MetricsCoreConfiguration.java     |   3 +-
 .../metrics/core/SimpleMeterRegistryExt.java       |  63 +++++++++++++
 ...nConst.java => StepDistributionSummaryExt.java} |  32 +++----
 .../meter/invocation/AbstractInvocationMeter.java  |  33 ++++---
 .../meter/invocation/MeterInvocationConst.java     |   2 +
 .../metrics/core/publish/PublishUtils.java         |   7 +-
 .../core/TestInvocationMetersInitializer.java      | 100 ++++++++++----------
 .../publish/TestInvocationPublishModelFactory.java | 105 +++++++++++----------
 .../metrics/core/publish/TestPublishUtils.java     |  12 +--
 .../model/invocation/TestOperationPerf.java        |   8 +-
 .../model/invocation/TestOperationPerfGroup.java   |   8 +-
 .../core/publish/model/invocation/Utils.java       |   3 +-
 15 files changed, 234 insertions(+), 193 deletions(-)

diff --git a/dependencies/default/pom.xml b/dependencies/default/pom.xml
index 74e5b9b3f..67cdfbfbd 100644
--- a/dependencies/default/pom.xml
+++ b/dependencies/default/pom.xml
@@ -89,7 +89,6 @@
     <servlet-api.version>6.0.0</servlet-api.version>
     <slf4j.version>1.7.36</slf4j.version>
     <snakeyaml.version>1.33</snakeyaml.version>
-    <spectator.version>1.7.3</spectator.version>
     <spring.version>6.0.9</spring.version>
     <spring-boot.version>3.0.7</spring-boot.version>
     <swagger.version>2.2.19</swagger.version>
@@ -189,12 +188,6 @@
         <version>${protobuf.version}</version>
       </dependency>
 
-      <dependency>
-        <groupId>com.netflix.spectator</groupId>
-        <artifactId>spectator-reg-servo</artifactId>
-        <version>${spectator.version}</version>
-      </dependency>
-
       <dependency>
         <groupId>com.squareup.okhttp3</groupId>
         <artifactId>okhttp</artifactId>
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
index 88e6eda69..a03c4739e 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
@@ -17,27 +17,21 @@
 package org.apache.servicecomb.foundation.metrics.publish;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 
+import io.micrometer.core.instrument.DistributionSummary;
 import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.Meter.Id;
 import io.micrometer.core.instrument.Statistic;
 import io.micrometer.core.instrument.Tag;
-import io.micrometer.core.instrument.Timer;
 import io.micrometer.core.instrument.distribution.CountAtBucket;
 import io.micrometer.core.instrument.distribution.HistogramSnapshot;
 
 // like select * from meters group by ......
 // but output a tree not a table
 public class MeasurementTree extends MeasurementNode {
-  public static final String TAG_LATENCY_DISTRIBUTION = "latencyDistribution";
-
-  public static final String TAG_TYPE = "type";
-
   public MeasurementTree() {
     super(null, null, null);
   }
@@ -48,30 +42,18 @@ public class MeasurementTree extends MeasurementNode {
   // only id name exists in groupConfig will accept, others will be ignored
   public void from(Iterator<Meter> meters, MeasurementGroupConfig groupConfig) {
     meters.forEachRemaining(meter -> {
-      // This code snip is not very good design. But timer is quite special.
-      if (meter instanceof Timer timer) {
-        HistogramSnapshot snapshot = timer.takeSnapshot();
-        List<Measurement> summary = Arrays.asList(new Measurement(snapshot::count, Statistic.COUNT),
-            new Measurement(() -> snapshot.total(TimeUnit.MILLISECONDS), Statistic.TOTAL_TIME),
-            new Measurement(() -> snapshot.max(TimeUnit.MILLISECONDS), Statistic.MAX));
-        from(meter.getId(), summary, groupConfig);
-
+      // This code snip is not very good design. But DistributionSummary is quite special.
+      if (meter instanceof DistributionSummary distributionSummary) {
+        HistogramSnapshot snapshot = distributionSummary.takeSnapshot();
         CountAtBucket[] countAtBuckets = snapshot.histogramCounts();
-        if (countAtBuckets.length > 2) {
-          List<Measurement> distributions = new ArrayList<>(countAtBuckets.length);
-          for (int i = 0; i < countAtBuckets.length; i++) {
-            final int index = i;
-            if (index == 0) {
-              distributions.add(new Measurement(() -> countAtBuckets[index].count(),
-                  Statistic.COUNT));
-              continue;
-            }
-            distributions.add(new Measurement(() -> countAtBuckets[index].count() - countAtBuckets[index - 1].count(),
-                Statistic.COUNT));
-          }
-
-          from(meter.getId().withTag(Tag.of(TAG_TYPE, TAG_LATENCY_DISTRIBUTION)), distributions, groupConfig);
+        List<Measurement> distributions = new ArrayList<>(countAtBuckets.length);
+        for (CountAtBucket countAtBucket : countAtBuckets) {
+          final double value = countAtBucket.count();
+          distributions.add(new Measurement(() -> value,
+              Statistic.COUNT));
         }
+
+        from(meter.getId(), distributions, groupConfig);
         return;
       }
 
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
index 234147a1f..d21354be5 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
@@ -54,8 +54,8 @@ public class TestMeasurementTree {
 
   @Test
   public void from() {
-    timer.record(10, TimeUnit.MILLISECONDS);
-    timer.record(2, TimeUnit.MILLISECONDS);
+    timer.record(10, TimeUnit.SECONDS);
+    timer.record(2, TimeUnit.SECONDS);
 
     MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2");
     tree.from(registry.getMeters().iterator(), config);
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
index 661fc7a1d..338b2183d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
@@ -31,7 +31,6 @@ import org.springframework.core.env.Environment;
 import io.micrometer.core.instrument.Clock;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.simple.CountingMode;
-import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 
 @Configuration
 public class MetricsCoreConfiguration {
@@ -43,7 +42,7 @@ public class MetricsCoreConfiguration {
   @Bean
   @ConditionalOnMissingBean
   public MeterRegistry meterRegistry(MetricsBootstrapConfig config) {
-    return new SimpleMeterRegistry(s -> {
+    return new SimpleMeterRegistryExt(s -> {
       if ("simple.step".equals(s)) {
         return Duration.ofMillis(config.getMsPollInterval()).toString();
       }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/SimpleMeterRegistryExt.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/SimpleMeterRegistryExt.java
new file mode 100644
index 000000000..592ec2af1
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/SimpleMeterRegistryExt.java
@@ -0,0 +1,63 @@
+/*
+ * 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.servicecomb.metrics.core;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.DistributionSummary;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.cumulative.CumulativeDistributionSummary;
+import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
+import io.micrometer.core.instrument.distribution.HistogramGauges;
+import io.micrometer.core.instrument.distribution.StepBucketHistogram;
+import io.micrometer.core.instrument.simple.SimpleConfig;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
+
+/**
+ * Custom SimpleMeterRegistry to support StepDistributionSummary
+ */
+public class SimpleMeterRegistryExt extends SimpleMeterRegistry {
+  private final SimpleConfig config;
+
+  public SimpleMeterRegistryExt(SimpleConfig config, Clock clock) {
+    super(config, clock);
+    this.config = config;
+  }
+
+  @Override
+  protected DistributionSummary newDistributionSummary(Meter.Id id,
+      DistributionStatisticConfig distributionStatisticConfig, double scale) {
+    DistributionStatisticConfig merged = distributionStatisticConfig
+        .merge(DistributionStatisticConfig.builder().expiry(config.step()).build());
+
+    DistributionSummary summary;
+    switch (config.mode()) {
+      case CUMULATIVE:
+        summary = new CumulativeDistributionSummary(id, clock, merged, scale, false);
+        break;
+      case STEP:
+      default:
+        summary = new StepDistributionSummaryExt(id, clock, merged, scale, config.step().toMillis(),
+            new StepBucketHistogram(clock, config.step().toMillis(), distributionStatisticConfig,
+                false, false));
+        break;
+    }
+
+    HistogramGauges.registerWithCommonFormat(summary, this);
+
+    return summary;
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/StepDistributionSummaryExt.java
similarity index 55%
copy from metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
copy to metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/StepDistributionSummaryExt.java
index fac87d55e..519f903a7 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/StepDistributionSummaryExt.java
@@ -14,23 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.metrics.core.meter.invocation;
-
-public interface MeterInvocationConst {
-  String INVOCATION_NAME = "servicecomb.invocation";
-
-  // consumer or producer
-  String TAG_ROLE = "role";
-
-  String TAG_OPERATION = "operation";
-
-  String TAG_TRANSPORT = "transport";
-
-  String TAG_TYPE = "type";
-
-  String TAG_STAGE = "stage";
-
-  String TAG_STATUS = "status";
-
-  String EDGE_INVOCATION_NAME = "EDGE";
+package org.apache.servicecomb.metrics.core;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.distribution.DistributionStatisticConfig;
+import io.micrometer.core.instrument.distribution.Histogram;
+import io.micrometer.core.instrument.step.StepDistributionSummary;
+
+public class StepDistributionSummaryExt extends StepDistributionSummary {
+  public StepDistributionSummaryExt(Id id, Clock clock,
+      DistributionStatisticConfig distributionStatisticConfig, double scale, long stepMillis,
+      Histogram histogram) {
+    super(id, clock, distributionStatisticConfig, scale, stepMillis, histogram);
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index 1ced47feb..e0bb9d549 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -25,11 +25,15 @@ import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.meter.LatencyDistributionConfig;
 
+import io.micrometer.core.instrument.DistributionSummary;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tags;
 import io.micrometer.core.instrument.Timer;
 
 public abstract class AbstractInvocationMeter {
+  // total time distribution
+  private final DistributionSummary totalSummary;
+
   //total time
   private final Timer totalTimer;
 
@@ -42,22 +46,24 @@ public abstract class AbstractInvocationMeter {
       MetricsBootstrapConfig metricsBootstrapConfig) {
     this.metricsBootstrapConfig = metricsBootstrapConfig;
 
-    Timer.Builder totalBuilder = Timer.builder(name)
-        .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
-            MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_TOTAL));
     if (!StringUtils.isEmpty(metricsBootstrapConfig.getLatencyDistribution())) {
-      totalBuilder.sla(toDuration(metricsBootstrapConfig.getLatencyDistribution()))
-          .distributionStatisticExpiry(Duration.ofMillis(metricsBootstrapConfig.getMsPollInterval()));
+      totalSummary = DistributionSummary.builder(name)
+          .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_DISTRIBUTION))
+          .distributionStatisticExpiry(Duration.ofMillis(metricsBootstrapConfig.getMsPollInterval()))
+          .serviceLevelObjectives(toSla(metricsBootstrapConfig.getLatencyDistribution())).register(meterRegistry);
+    } else {
+      totalSummary = null;
     }
-    this.totalTimer = totalBuilder.register(meterRegistry);
+    this.totalTimer = Timer.builder(name).tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE
+        , MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_TOTAL)).register(meterRegistry);
     this.prepareTimer = Timer.builder(name).tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE
         , MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_PREPARE)).register(meterRegistry);
   }
 
-  protected static Duration[] toDuration(String config) {
+  protected static double[] toSla(String config) {
     config = config.trim() + "," + LatencyDistributionConfig.MAX_LATENCY;
     String[] array = config.split("\\s*,+\\s*");
-    Duration[] result = new Duration[array.length];
+    double[] result = new double[array.length];
 
     for (int idx = 0; idx < array.length - 1; idx++) {
       long msMin = Long.parseLong(array[idx]);
@@ -67,12 +73,12 @@ public abstract class AbstractInvocationMeter {
         throw new IllegalStateException(msg);
       }
 
-      result[idx] = Duration.ofMillis(msMin);
+      result[idx] = msMin;
     }
-    result[array.length - 1] = Duration.ofMillis(LatencyDistributionConfig.MAX_LATENCY);
+    result[array.length - 1] = LatencyDistributionConfig.MAX_LATENCY;
 
-    if (result[0].toMillis() == 0) {
-      Duration[] target = new Duration[result.length - 1];
+    if (Double.compare(0, result[0]) == 0) {
+      double[] target = new double[result.length - 1];
       System.arraycopy(result, 1, target, 0, target.length);
       return target;
     }
@@ -84,5 +90,8 @@ public abstract class AbstractInvocationMeter {
     InvocationStageTrace stageTrace = event.getInvocation().getInvocationStageTrace();
     totalTimer.record(stageTrace.calcTotal(), TimeUnit.NANOSECONDS);
     prepareTimer.record(stageTrace.calcPrepare(), TimeUnit.NANOSECONDS);
+    if (totalSummary != null) {
+      totalSummary.record(TimeUnit.NANOSECONDS.toMillis(stageTrace.calcTotal()));
+    }
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
index fac87d55e..2a377e432 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
@@ -30,6 +30,8 @@ public interface MeterInvocationConst {
 
   String TAG_STAGE = "stage";
 
+  String TAG_DISTRIBUTION = "distribution";
+
   String TAG_STATUS = "status";
 
   String EDGE_INVOCATION_NAME = "EDGE";
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
index 9bf2cb6f9..9c761aaa5 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
@@ -20,7 +20,6 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup;
@@ -36,8 +35,8 @@ public final class PublishUtils {
   public static PerfInfo createPerfInfo(MeasurementNode stageNode) {
     PerfInfo perfInfo = new PerfInfo();
     perfInfo.setTotalRequests(stageNode.findChild(Statistic.COUNT.name()).summary());
-    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.TOTAL_TIME.name()).summary());
-    perfInfo.setMsMaxLatency(stageNode.findChild(Statistic.MAX.name()).summary());
+    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.TOTAL_TIME.name()).summary() * 1000);
+    perfInfo.setMsMaxLatency(stageNode.findChild(Statistic.MAX.name()).summary() * 1000);
     return perfInfo;
   }
 
@@ -51,7 +50,7 @@ public final class PublishUtils {
       operationPerf.getStages().put(mNode.getName(), perfInfo);
     });
 
-    MeasurementNode latencyNode = statusNode.findChild(MeasurementTree.TAG_LATENCY_DISTRIBUTION);
+    MeasurementNode latencyNode = statusNode.findChild(MeterInvocationConst.TAG_DISTRIBUTION);
     if (latencyNode != null && latencyNode.getMeasurements() != null) {
       operationPerf.setLatencyDistribution(latencyNode.getMeasurements().stream()
           .map(m -> (int) m.getValue())
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
index 09963b4e4..8705f89d1 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
@@ -110,9 +110,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
         .getMeasurements();
@@ -120,9 +120,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-send")
         .getMeasurements();
@@ -130,9 +130,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.0E-5");
+        "statistic='TOTAL_TIME', value=1.0E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=5.0E-6");
+        "statistic='MAX', value=5.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
         .getMeasurements();
@@ -140,9 +140,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-encode")
         .getMeasurements();
@@ -151,9 +151,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=8.0E-6");
+        "statistic='TOTAL_TIME', value=8.0E-9");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=4.0E-6");
+        "statistic='MAX', value=4.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
         .getMeasurements();
@@ -161,9 +161,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "wait")
         .getMeasurements();
@@ -171,9 +171,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-decode")
         .getMeasurements();
@@ -181,9 +181,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
   }
 
   @Test
@@ -236,9 +236,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
         .getMeasurements();
@@ -246,9 +246,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-send")
         .getMeasurements();
@@ -256,9 +256,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.0E-5");
+        "statistic='TOTAL_TIME', value=1.0E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=5.0E-6");
+        "statistic='MAX', value=5.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
         .getMeasurements();
@@ -266,9 +266,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-encode")
         .getMeasurements();
@@ -276,9 +276,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=8.0E-6");
+        "statistic='TOTAL_TIME', value=8.0E-9");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=4.0E-6");
+        "statistic='MAX', value=4.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "wait")
         .getMeasurements();
@@ -286,9 +286,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-decode")
         .getMeasurements();
@@ -296,9 +296,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.6E-5");
+        "statistic='TOTAL_TIME', value=1.6E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=8.0E-6");
+        "statistic='MAX', value=8.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-decode")
         .getMeasurements();
@@ -306,9 +306,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-encode")
         .getMeasurements();
@@ -316,9 +316,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-send")
         .getMeasurements();
@@ -326,9 +326,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
   }
 
   @Test
@@ -375,9 +375,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
         .getMeasurements();
@@ -385,9 +385,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "queue")
         .getMeasurements();
@@ -395,9 +395,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "execute")
         .getMeasurements();
@@ -405,9 +405,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-decode")
         .getMeasurements();
@@ -415,9 +415,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-encode")
         .getMeasurements();
@@ -425,9 +425,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-send")
         .getMeasurements();
@@ -435,8 +435,8 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-5");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-6");
+        "statistic='MAX', value=9.0E-9");
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
index d0310e48c..8473f0434 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
@@ -44,6 +44,7 @@ import io.vertx.core.json.Json;
 public class TestInvocationPublishModelFactory {
   EventBus eventBus = new EventBus();
 
+  // not step mode.
   MeterRegistry meterRegistry = new SimpleMeterRegistry();
 
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
@@ -86,18 +87,18 @@ public class TestInvocationPublishModelFactory {
                       "stages" : {
                         "consumer-encode" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "prepare" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "wait" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "total" : {
                           "totalRequests" : 1.0,
@@ -106,34 +107,34 @@ public class TestInvocationPublishModelFactory {
                         },
                         "consumer-send" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "connection" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "consumer-decode" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         }
                       },
-                      "latencyDistribution" : [ 1, 0, 0 ]
+                      "latencyDistribution" : [ 1, 1, 1 ]
                     } ],
                     "summary" : {
                       "operation" : "",
                       "stages" : {
                         "consumer-encode" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "prepare" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "total" : {
                           "totalRequests" : 1.0,
@@ -142,26 +143,26 @@ public class TestInvocationPublishModelFactory {
                         },
                         "wait" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "consumer-send" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "connection" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         },
                         "consumer-decode" : {
                           "totalRequests" : 1.0,
-                          "msTotalTime" : 1.0E-6,
-                          "msMaxLatency" : 1.0E-6
+                          "msTotalTime" : 1.0000000000000002E-6,
+                          "msMaxLatency" : 1.0000000000000002E-6
                         }
                       },
-                      "latencyDistribution" : [ 1, 0, 0 ]
+                      "latencyDistribution" : [ 1, 1, 1 ]
                     }
                   }
                 }
@@ -185,18 +186,18 @@ public class TestInvocationPublishModelFactory {
                     "stages" : {
                       "consumer-encode" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "prepare" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "wait" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "total" : {
                         "totalRequests" : 1.0,
@@ -205,34 +206,34 @@ public class TestInvocationPublishModelFactory {
                       },
                       "consumer-send" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "connection" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "consumer-decode" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       }
                     },
-                    "latencyDistribution" : [ 1, 0, 0 ]
+                    "latencyDistribution" : [ 1, 1, 1 ]
                   } ],
                   "summary" : {
                     "operation" : "",
                     "stages" : {
                       "consumer-encode" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "prepare" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "total" : {
                         "totalRequests" : 1.0,
@@ -241,26 +242,26 @@ public class TestInvocationPublishModelFactory {
                       },
                       "wait" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "consumer-send" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "connection" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       },
                       "consumer-decode" : {
                         "totalRequests" : 1.0,
-                        "msTotalTime" : 1.0E-6,
-                        "msMaxLatency" : 1.0E-6
+                        "msTotalTime" : 1.0000000000000002E-6,
+                        "msMaxLatency" : 1.0000000000000002E-6
                       }
                     },
-                    "latencyDistribution" : [ 1, 0, 0 ]
+                    "latencyDistribution" : [ 1, 1, 1 ]
                   }
                 }
               }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
index 66fb62f2f..cb4508337 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
@@ -44,8 +44,8 @@ public class TestPublishUtils {
     PerfInfo perf = PublishUtils.createPerfInfo(stageNode);
 
     Assertions.assertEquals(10, perf.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perf.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perf.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perf.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perf.getMsMaxLatency(), 0);
   }
 
   @Test
@@ -55,8 +55,8 @@ public class TestPublishUtils {
     PerfInfo perfInfo = opPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
     Integer[] latencyDistribution = opPerf.getLatencyDistribution();
     Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
     Assertions.assertEquals(2, latencyDistribution.length);
     Assertions.assertEquals(1, latencyDistribution[0].intValue());
     Assertions.assertEquals(2, latencyDistribution[1].intValue());
@@ -76,8 +76,8 @@ public class TestPublishUtils {
     PerfInfo perfInfo = group.getSummary().findStage(InvocationStageTrace.STAGE_TOTAL);
     Integer[] latencyDistribution = group.getSummary().getLatencyDistribution();
     Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
     Assertions.assertEquals(2, latencyDistribution.length);
     Assertions.assertEquals(1, latencyDistribution[0].intValue());
     Assertions.assertEquals(2, latencyDistribution[1].intValue());
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java
index 2090f21a8..f5948016c 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java
@@ -36,12 +36,12 @@ public class TestOperationPerf {
 
     PerfInfo perfInfo = opPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
     Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
 
     perfInfo = opPerf.findStage(InvocationStageTrace.STAGE_PROVIDER_BUSINESS);
     Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java
index 9f4fa492f..7dda01408 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java
@@ -48,12 +48,12 @@ public class TestOperationPerfGroup {
 
     PerfInfo perfInfo = summary.findStage(InvocationStageTrace.STAGE_TOTAL);
     Assertions.assertEquals(20, perfInfo.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
 
     perfInfo = summary.findStage(InvocationStageTrace.STAGE_PROVIDER_BUSINESS);
     Assertions.assertEquals(20, perfInfo.getTotalRequests(), 0);
-    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
index c48a1b5b6..17a62c575 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
@@ -21,7 +21,6 @@ import java.util.List;
 
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.PublishUtils;
 
@@ -61,7 +60,7 @@ public class Utils {
     Id id = initId;
     MeasurementNode statusNode = new MeasurementNode(status, id, new HashMap<>());
     MeasurementNode typeNode = new MeasurementNode(MeterInvocationConst.TAG_STAGE, id, new HashMap<>());
-    MeasurementNode latencyNode = new MeasurementNode(MeasurementTree.TAG_LATENCY_DISTRIBUTION, id,
+    MeasurementNode latencyNode = new MeasurementNode(MeterInvocationConst.TAG_DISTRIBUTION, id,
         new HashMap<>());
     List<Measurement> measurements = latencyNode.getMeasurements();
     measurements.add(new Measurement(() -> 1, Statistic.VALUE));


(servicecomb-java-chassis) 05/11: [SCB-2838]using micrometer to replace spectator part3: ThreadPool

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 1ac6afbfe8baa2b07a521e4d38dfb99fac324c3e
Author: liubao <bi...@qq.com>
AuthorDate: Mon Nov 27 17:36:30 2023 +0800

    [SCB-2838]using micrometer to replace spectator part3: ThreadPool
---
 .../metrics/publish/spectator/MeasurementNode.java | 21 +++++++--
 .../metrics/publish/spectator/MeasurementTree.java | 10 ++--
 .../publish/spectator/TestDefaultTagFinder.java    | 10 ++--
 .../publish/spectator/TestMeasurementNode.java     | 28 ++++++-----
 .../publish/spectator/TestMeasurementTree.java     | 35 +++++++-------
 .../ThreadPoolMonitorPublishModelFactory.java      | 35 +++++++-------
 .../metrics/core/ThreadPoolMetersInitializer.java  | 55 ++++++++++++++++------
 7 files changed, 119 insertions(+), 75 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
index 272f6b87e..6cace285b 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
@@ -22,21 +22,29 @@ import java.util.List;
 import java.util.Map;
 
 import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
 
 public class MeasurementNode implements Comparable<MeasurementNode> {
   private final String name;
 
+  private final Id id;
+
   private final List<Measurement> measurements = new ArrayList<>();
 
   private Map<String, MeasurementNode> children;
 
-  public MeasurementNode(String name, Map<String, MeasurementNode> children) {
+  public MeasurementNode(String name, Id id, Map<String, MeasurementNode> children) {
     this.name = name;
+    this.id = id;
     this.children = children;
   }
 
   public String getName() {
-    return name;
+    return id.getName();
+  }
+
+  public Id getId() {
+    return id;
   }
 
   public Map<String, MeasurementNode> getChildren() {
@@ -62,13 +70,16 @@ public class MeasurementNode implements Comparable<MeasurementNode> {
     return node;
   }
 
-  public MeasurementNode addChild(String childName, Measurement measurement) {
+  public MeasurementNode addChild(String childName, Id id, Measurement measurement) {
     if (children == null) {
       children = new LinkedHashMap<>();
     }
 
-    MeasurementNode node = children.computeIfAbsent(childName, name -> new MeasurementNode(name, null));
-    node.addMeasurement(measurement);
+    MeasurementNode node = children.computeIfAbsent(childName, name -> new MeasurementNode(name, id, null));
+
+    if (measurement != null) {
+      node.addMeasurement(measurement);
+    }
 
     return node;
   }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
index e2dbd268b..a165ca935 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
@@ -28,7 +28,7 @@ import io.micrometer.core.instrument.Tag;
 // but output a tree not a table
 public class MeasurementTree extends MeasurementNode {
   public MeasurementTree() {
-    super(null, null);
+    super(null, null, null);
   }
 
   // groupConfig:
@@ -44,7 +44,7 @@ public class MeasurementTree extends MeasurementNode {
 
   public void from(Id id, Iterable<Measurement> measurements, MeasurementGroupConfig groupConfig) {
     for (Measurement measurement : measurements) {
-      MeasurementNode node = addChild(id.getName(), measurement);
+      MeasurementNode node = addChild(id.getName(), id, null);
 
       List<TagFinder> tagFinders = groupConfig.findTagFinders(id.getName());
       if (tagFinders == null) {
@@ -60,11 +60,13 @@ public class MeasurementTree extends MeasurementNode {
           throw new IllegalStateException(
               String.format("tag key \"%s\" not exist in %s",
                   tagFinder.getTagKey(),
-                  measurement));
+                  id));
         }
 
-        node = node.addChild(tag.getValue(), measurement);
+        node = node.addChild(tag.getValue(), id, null);
       }
+
+      node.addChild(measurement.getStatistic().name(), id, measurement);
     }
   }
 }
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java
index c892b6a8b..cc9dcadcc 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java
@@ -19,11 +19,11 @@ package org.apache.servicecomb.foundation.metrics.publish.spectator;
 import java.util.Arrays;
 import java.util.List;
 
-import com.netflix.spectator.api.BasicTag;
-import com.netflix.spectator.api.Tag;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import io.micrometer.core.instrument.Tag;
+
 public class TestDefaultTagFinder {
   TagFinder finder = new DefaultTagFinder("key");
 
@@ -34,8 +34,8 @@ public class TestDefaultTagFinder {
 
   @Test
   public void readSucc() {
-    Tag tag = new BasicTag("key", "value");
-    List<Tag> tags = Arrays.asList(new BasicTag("t1", "t1v"),
+    Tag tag = Tag.of("key", "value");
+    List<Tag> tags = Arrays.asList(Tag.of("t1", "t1v"),
         tag);
 
     Assertions.assertSame(tag, finder.find(tags));
@@ -43,7 +43,7 @@ public class TestDefaultTagFinder {
 
   @Test
   public void readFail() {
-    List<Tag> tags = Arrays.asList(new BasicTag("t1", "t1v"));
+    List<Tag> tags = Arrays.asList(Tag.of("t1", "t1v"));
 
     Assertions.assertNull(finder.find(tags));
   }
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java
index 7c5691f92..a366cee54 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java
@@ -22,15 +22,19 @@ import java.util.Map;
 import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
 
-import com.netflix.spectator.api.Measurement;
-
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Meter.Type;
+import io.micrometer.core.instrument.Tags;
 import mockit.Expectations;
 import mockit.Mocked;
-import org.junit.jupiter.api.Assertions;
 
 public class TestMeasurementNode {
-  MeasurementNode node = new MeasurementNode("name", null);
+  Id id = new Id("name", Tags.empty(), null, null, Type.OTHER);
+
+  MeasurementNode node = new MeasurementNode("name", id, null);
 
   @Test
   public void getName() {
@@ -40,7 +44,7 @@ public class TestMeasurementNode {
   @Test
   public void getChildren() {
     Map<String, MeasurementNode> children = new HashMap<>();
-    node = new MeasurementNode("name", children);
+    node = new MeasurementNode("name", id, children);
 
     Assertions.assertSame(children, node.getChildren());
   }
@@ -52,24 +56,24 @@ public class TestMeasurementNode {
 
   @Test
   public void findChild_multiLevel_noMiddleChildren(@Mocked Measurement measurement) {
-    MeasurementNode c1 = node.addChild("c1", measurement);
-    c1.addChild("c2", measurement);
+    MeasurementNode c1 = node.addChild("c1", id, measurement);
+    c1.addChild("c2", id, measurement);
 
     Assertions.assertNull(node.findChild("c1_notExist", "c2"));
   }
 
   @Test
   public void findChild_multiLevel_ok(@Mocked Measurement measurement) {
-    MeasurementNode c1 = node.addChild("c1", measurement);
-    MeasurementNode c2 = c1.addChild("c2", measurement);
+    MeasurementNode c1 = node.addChild("c1", id, measurement);
+    MeasurementNode c2 = c1.addChild("c2", id, measurement);
 
     Assertions.assertSame(c2, node.findChild("c1", "c2"));
   }
 
   @Test
   public void addChild(@Mocked Measurement measurement) {
-    MeasurementNode c1 = node.addChild("c1", measurement);
-    MeasurementNode c2 = node.addChild("c2", measurement);
+    MeasurementNode c1 = node.addChild("c1", id, measurement);
+    MeasurementNode c2 = node.addChild("c2", id, measurement);
 
     Assertions.assertSame(c1, node.findChild("c1"));
     Assertions.assertSame(c2, node.findChild("c2"));
@@ -86,7 +90,7 @@ public class TestMeasurementNode {
   public void summary(@Mocked Measurement measurement) {
     new Expectations() {
       {
-        measurement.value();
+        measurement.getValue();
         result = 10;
       }
     };
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
index 108831d0b..44037f7a3 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
@@ -22,18 +22,15 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Statistic;
-import com.netflix.spectator.api.Timer;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Timer;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 
 public class TestMeasurementTree {
   MeasurementTree tree = new MeasurementTree();
 
-  ManualClock clock = new ManualClock();
-
-  Registry registry = new DefaultRegistry(clock);
+  MeterRegistry registry = new SimpleMeterRegistry();
 
   Timer timer;
 
@@ -53,17 +50,19 @@ public class TestMeasurementTree {
 
   @Test
   public void from() {
-    timer.record(10, TimeUnit.NANOSECONDS);
-    timer.record(2, TimeUnit.NANOSECONDS);
+    timer.record(10, TimeUnit.SECONDS);
+    timer.record(2, TimeUnit.SECONDS);
 
-    MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2", Statistic.count.key());
-    tree.from(registry.iterator(), config);
+    MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2");
+    tree.from(registry.getMeters().iterator(), config);
 
     Assertions.assertEquals(2, tree.getChildren().size());
 
     MeasurementNode node = tree.findChild("id", "g1v", "g2v");
-    Assertions.assertEquals(2d, node.findChild(Statistic.count.value()).getMeasurements().get(0).value(), 0);
-    Assertions.assertEquals(12d, node.findChild(Statistic.totalTime.value()).getMeasurements().get(0).value(), 0);
+    Assertions.assertEquals(2d,
+        node.findChild(Statistic.COUNT.name()).getMeasurements().get(0).getValue(), 0);
+    Assertions.assertEquals(12d,
+        node.findChild(Statistic.TOTAL_TIME.name()).getMeasurements().get(0).getValue(), 0);
     Assertions.assertEquals(0d, tree.findChild("id_notCare").summary(), 0);
   }
 
@@ -71,7 +70,7 @@ public class TestMeasurementTree {
   public void from_withSkipOnNull() {
     try {
       MeasurementGroupConfig config = new MeasurementGroupConfig("id", new DefaultTagFinder("notExist", true));
-      tree.from(registry.iterator(), config);
+      tree.from(registry.getMeters().iterator(), config);
     } catch (Exception e) {
       Assertions.fail("should not throw exception");
     }
@@ -81,8 +80,10 @@ public class TestMeasurementTree {
   public void from_failed() {
     IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> {
       MeasurementGroupConfig config = new MeasurementGroupConfig("id", "notExist");
-      tree.from(registry.iterator(), config);
+      tree.from(registry.getMeters().iterator(), config);
     });
-    Assertions.assertEquals("tag key \"notExist\" not exist in Measurement(id:g1=g1v:g2=g2v:statistic=count:t3=t3v:t4=t4v,0,0.0)", exception.getMessage());
+    Assertions.assertEquals(
+        "tag key \"notExist\" not exist in MeterId{name='id', tags=[tag(g1=g1v),tag(g2=g2v),tag(t3=t3v),tag(t4=t4v)]}",
+        exception.getMessage());
   }
 }
diff --git a/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java b/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java
index 3b8ba946f..c631defb7 100644
--- a/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java
@@ -23,8 +23,7 @@ import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTr
 import org.apache.servicecomb.metrics.core.ThreadPoolMetersInitializer;
 import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel;
 
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Utils;
+import io.micrometer.core.instrument.Measurement;
 
 public class ThreadPoolMonitorPublishModelFactory {
   interface Setter {
@@ -47,22 +46,22 @@ public class ThreadPoolMonitorPublishModelFactory {
   }
 
   public void create() {
-    readMeasurement(ThreadPoolMonitor.TASK_COUNT,
-        (model, measurement) -> model.setAvgTaskCount(measurement.value()));
-    readMeasurement(ThreadPoolMonitor.COMPLETED_TASK_COUNT,
-        (model, measurement) -> model.setAvgCompletedTaskCount(measurement.value()));
-    readMeasurement(ThreadPoolMonitor.CURRENT_THREADS_BUSY,
-        (model, measurement) -> model.setCurrentThreadsBusy((int) measurement.value()));
-    readMeasurement(ThreadPoolMonitor.MAX_THREADS,
-        (model, measurement) -> model.setMaxThreads((int) measurement.value()));
-    readMeasurement(ThreadPoolMonitor.POOL_SIZE,
-        (model, measurement) -> model.setPoolSize((int) measurement.value()));
-    readMeasurement(ThreadPoolMonitor.CORE_POOL_SIZE,
-        (model, measurement) -> model.setCorePoolSize((int) measurement.value()));
-    readMeasurement(ThreadPoolMonitor.QUEUE_SIZE,
-        (model, measurement) -> model.setQueueSize((int) measurement.value()));
+    readMeasurement(ThreadPoolMetersInitializer.TASK_COUNT,
+        (model, measurement) -> model.setAvgTaskCount(measurement.getValue()));
+    readMeasurement(ThreadPoolMetersInitializer.COMPLETED_TASK_COUNT,
+        (model, measurement) -> model.setAvgCompletedTaskCount(measurement.getValue()));
+    readMeasurement(ThreadPoolMetersInitializer.CURRENT_THREADS_BUSY,
+        (model, measurement) -> model.setCurrentThreadsBusy((int) measurement.getValue()));
+    readMeasurement(ThreadPoolMetersInitializer.MAX_THREADS,
+        (model, measurement) -> model.setMaxThreads((int) measurement.getValue()));
+    readMeasurement(ThreadPoolMetersInitializer.POOL_SIZE,
+        (model, measurement) -> model.setPoolSize((int) measurement.getValue()));
+    readMeasurement(ThreadPoolMetersInitializer.CORE_POOL_SIZE,
+        (model, measurement) -> model.setCorePoolSize((int) measurement.getValue()));
+    readMeasurement(ThreadPoolMetersInitializer.QUEUE_SIZE,
+        (model, measurement) -> model.setQueueSize((int) measurement.getValue()));
     readMeasurement(ThreadPoolMetersInitializer.REJECTED_COUNT,
-        (model, measurement) -> model.setRejected(measurement.value()));
+        (model, measurement) -> model.setRejected(measurement.getValue()));
   }
 
   protected void readMeasurement(String name, Setter setter) {
@@ -72,7 +71,7 @@ public class ThreadPoolMonitorPublishModelFactory {
     }
 
     for (Measurement measurement : node.getMeasurements()) {
-      String threadPoolName = Utils.getTagValue(measurement.id(), ThreadPoolMonitor.ID_TAG_NAME);
+      String threadPoolName = node.getId().getTag(ThreadPoolMetersInitializer.ID);
       if (threadPoolName == null) {
         continue;
       }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
index 1c30f3951..ebe0c019a 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
@@ -26,16 +26,34 @@ import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.GroupExecutor;
+import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
 
 import com.google.common.eventbus.EventBus;
 
+import io.micrometer.core.instrument.Gauge;
 import io.micrometer.core.instrument.MeterRegistry;
 
 public class ThreadPoolMetersInitializer implements MetricsInitializer {
-  public static String REJECTED_COUNT = "threadpool.rejectedCount";
+  public static final String ID = "id";
+
+  public static final String REJECTED_COUNT = "threadpool.rejectedCount";
+
+  public static final String TASK_COUNT = "threadpool.taskCount";
+
+  public static final String COMPLETED_TASK_COUNT = "threadpool.completedTaskCount";
+
+  public static final String CURRENT_THREADS_BUSY = "threadpool.currentThreadsBusy";
+
+  public static final String MAX_THREADS = "threadpool.maxThreads";
+
+  public static final String POOL_SIZE = "threadpool.poolSize";
+
+  public static final String CORE_POOL_SIZE = "threadpool.corePoolSize";
+
+  public static final String QUEUE_SIZE = "threadpool.queueSize";
 
   private MeterRegistry meterRegistry;
 
@@ -57,7 +75,7 @@ public class ThreadPoolMetersInitializer implements MetricsInitializer {
         continue;
       }
 
-      if (GroupExecutor.class.isInstance(executor)) {
+      if (executor instanceof GroupExecutor) {
         createThreadPoolMeters(entry.getKey(), (GroupExecutor) executor);
         continue;
       }
@@ -84,20 +102,29 @@ public class ThreadPoolMetersInitializer implements MetricsInitializer {
   }
 
   protected void createThreadPoolMeters(String threadPoolName, Executor executor) {
-    if (!ThreadPoolExecutor.class.isInstance(executor)) {
+    if (!(executor instanceof ThreadPoolExecutor threadPoolExecutor)) {
       return;
     }
 
-    // TODO: add thread pool meter
-//    ThreadPoolMonitor.attach(registry, (ThreadPoolExecutor) executor, threadPoolName);
-//
-//    if (executor instanceof ThreadPoolExecutorEx) {
-//      Tag idTag = new BasicTag("id", threadPoolName);
-//
-//      PolledMeter.using(registry)
-//          .withName(REJECTED_COUNT)
-//          .withTag(idTag)
-//          .monitorMonotonicCounter((ThreadPoolExecutorEx) executor, ThreadPoolExecutorEx::getRejectedCount);
-//    }
+    Gauge.builder(TASK_COUNT, threadPoolExecutor::getTaskCount).tags(ID, threadPoolName)
+        .register(meterRegistry);
+    Gauge.builder(COMPLETED_TASK_COUNT, threadPoolExecutor::getCompletedTaskCount).tags(ID, threadPoolName)
+        .register(meterRegistry);
+    Gauge.builder(CURRENT_THREADS_BUSY, threadPoolExecutor::getActiveCount).tags(ID, threadPoolName)
+        .register(meterRegistry);
+    Gauge.builder(MAX_THREADS, threadPoolExecutor::getMaximumPoolSize).tags(ID, threadPoolName)
+        .register(meterRegistry);
+    Gauge.builder(POOL_SIZE, threadPoolExecutor::getPoolSize).tags(ID, threadPoolName)
+        .register(meterRegistry);
+    Gauge.builder(CORE_POOL_SIZE, threadPoolExecutor::getCorePoolSize).tags(ID, threadPoolName)
+        .register(meterRegistry);
+    Gauge.builder(QUEUE_SIZE, () -> threadPoolExecutor.getQueue().size()).tags(ID, threadPoolName)
+        .register(meterRegistry);
+
+    if (executor instanceof ThreadPoolExecutorEx) {
+      Gauge.builder(REJECTED_COUNT, () -> ((ThreadPoolExecutorEx) (executor)).getRejectedCount())
+          .tags(ID, threadPoolName)
+          .register(meterRegistry);
+    }
   }
 }


(servicecomb-java-chassis) 11/11: [SCB-2838]fix checkstyle

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 32397b91e07b71786ffcc8de189b77ad6fa3ed27
Author: liubao <bi...@qq.com>
AuthorDate: Fri Dec 1 16:01:19 2023 +0800

    [SCB-2838]fix checkstyle
---
 .../apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java    | 2 +-
 .../org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java     | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
index b33d30d8c..e5b30fa73 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
@@ -42,7 +42,7 @@ public class InterfaceUsage {
 
   public InterfaceUsage(MeterRegistry meterRegistry, String name, Tags tags, String interfaceName) {
     this.interfaceName = interfaceName;
-    tags.and(Tag.of(INTERFACE, name));
+    tags = tags.and(Tag.of(INTERFACE, name));
 
     // recv/Bps
     receive = new NetStat(0);
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
index 28865a3fd..53bf98f9a 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
@@ -35,7 +35,6 @@ import org.junit.jupiter.api.Assertions;
 
 import com.google.common.eventbus.EventBus;
 import com.google.common.io.CharSource;
-import com.google.common.io.Files;
 
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.simple.SimpleMeterRegistry;


(servicecomb-java-chassis) 01/11: [SCB-2838]using micrometer to replace spectator part1: MetricsInitializer

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 7bc6d7f84eee1c56732b5498c20dd6f38bbc38fb
Author: liubao <bi...@qq.com>
AuthorDate: Sat Nov 25 10:02:13 2023 +0800

    [SCB-2838]using micrometer to replace spectator part1: MetricsInitializer
---
 foundations/foundation-metrics/pom.xml             |  4 +-
 .../com/netflix/spectator/api/SpectatorUtils.java  | 16 ++--
 .../foundation/metrics/MetricsBootstrap.java       | 18 +++--
 .../foundation/metrics/MetricsInitializer.java     |  9 +--
 .../foundation/metrics/PolledEvent.java            | 17 +---
 .../metrics/meter/AbstractPeriodMeter.java         |  4 +-
 .../metrics/meter/LatencyScopeMeter.java           | 12 +--
 .../foundation/metrics/meter/PeriodMeter.java      |  5 +-
 .../foundation/metrics/meter/SimpleTimer.java      |  6 +-
 .../publish/spectator/DefaultTagFinder.java        |  5 +-
 .../metrics/publish/spectator/MeasurementNode.java |  4 +-
 .../metrics/publish/spectator/MeasurementTree.java | 21 +++--
 .../metrics/publish/spectator/TagFinder.java       |  2 +-
 .../metrics/registry/GlobalRegistry.java           | 92 ++--------------------
 .../foundation/metrics/TestMetricsBootstrap.java   | 12 ++-
 .../foundation/metrics/meter/TestSimpleTimer.java  |  9 ++-
 .../metrics/core/DefaultRegistryInitializer.java   | 63 ---------------
 .../metrics/core/InvocationMetersInitializer.java  | 14 ++--
 .../metrics/core/MetricsCoreConfiguration.java     |  5 --
 .../metrics/core/OsMetersInitializer.java          | 11 +--
 .../metrics/core/ThreadPoolMetersInitializer.java  | 36 ++++-----
 .../metrics/core/VertxMetersInitializer.java       | 20 ++---
 .../metrics/core/meter/ConsumerMeters.java         |  6 +-
 .../servicecomb/metrics/core/meter/EdgeMeters.java |  6 +-
 .../metrics/core/meter/ProducerMeters.java         |  6 +-
 .../meter/invocation/AbstractInvocationMeter.java  |  4 +-
 .../meter/invocation/AbstractInvocationMeters.java | 28 +++----
 .../meter/invocation/ConsumerInvocationMeters.java |  8 +-
 .../meter/invocation/EdgeInvocationMeters.java     |  8 +-
 .../meter/invocation/ProducerInvocationMeters.java |  8 +-
 .../metrics/core/meter/os/CpuMeter.java            | 15 ++--
 .../metrics/core/meter/os/NetMeter.java            | 16 ++--
 .../servicecomb/metrics/core/meter/os/OsMeter.java | 12 +--
 .../core/meter/os/cpu/AbstractCpuUsage.java        |  3 +-
 .../metrics/core/meter/os/cpu/OsCpuUsage.java      |  2 +-
 .../metrics/core/meter/os/cpu/ProcessCpuUsage.java |  2 +-
 .../metrics/core/meter/os/net/InterfaceUsage.java  | 10 ++-
 .../metrics/core/meter/os/net/NetStat.java         |  3 +-
 .../metrics/core/meter/vertx/EndpointMeter.java    | 22 +++---
 .../core/meter/vertx/HttpClientEndpointsMeter.java |  7 +-
 .../core/meter/vertx/VertxEndpointsMeter.java      | 10 ++-
 .../metrics/core/publish/DefaultLogPublisher.java  | 14 ++--
 .../metrics/core/publish/PublishModelFactory.java  |  3 +-
 .../core/TestDefaultRegistryInitializer.java       | 73 -----------------
 .../metrics/core/meter/os/TestOsMeter.java         | 25 +++---
 .../metrics/prometheus/PrometheusPublisher.java    | 43 +++++-----
 .../basic/integration/MetricsEndpointImpl.java     | 35 ++++----
 47 files changed, 256 insertions(+), 498 deletions(-)

diff --git a/foundations/foundation-metrics/pom.xml b/foundations/foundation-metrics/pom.xml
index ba0193e70..aca8ad61d 100644
--- a/foundations/foundation-metrics/pom.xml
+++ b/foundations/foundation-metrics/pom.xml
@@ -32,8 +32,8 @@
       <artifactId>foundation-common</artifactId>
     </dependency>
     <dependency>
-      <groupId>com.netflix.spectator</groupId>
-      <artifactId>spectator-reg-servo</artifactId>
+      <groupId>io.micrometer</groupId>
+      <artifactId>micrometer-core</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
diff --git a/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
index cccc7107f..400b8cb4b 100644
--- a/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
@@ -16,21 +16,15 @@
  */
 package com.netflix.spectator.api;
 
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
+
 public final class SpectatorUtils {
   private SpectatorUtils() {
   }
 
-  public static Id createDefaultId(String name) {
-    return new DefaultId(name);
-  }
-
-  public static void removeExpiredMeters(Registry registry) {
-    if (registry instanceof AbstractRegistry) {
-      ((AbstractRegistry) registry).removeExpiredMeters();
-    }
-  }
-
-  public static void registerMeter(Registry registry, Meter meter) {
+  public static void registerMeter(MeterRegistry registry, Meter meter) {
+    registry.counter()
     if (!(registry instanceof AbstractRegistry)) {
       throw new IllegalStateException("registry must be a AbstractRegistry, class=" + registry.getClass().getName());
     }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
index 5b014afe8..2521650f6 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
@@ -22,7 +22,6 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -31,10 +30,12 @@ import org.springframework.core.env.Environment;
 import com.google.common.eventbus.EventBus;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 
+import io.micrometer.core.instrument.MeterRegistry;
+
 public class MetricsBootstrap {
   private static final Logger LOGGER = LoggerFactory.getLogger(MetricsBootstrap.class);
 
-  private GlobalRegistry globalRegistry;
+  private MeterRegistry meterRegistry;
 
   private EventBus eventBus;
 
@@ -57,15 +58,19 @@ public class MetricsBootstrap {
     this.metricsInitializers = metricsInitializers;
   }
 
-  public void start(GlobalRegistry globalRegistry, EventBus eventBus) {
-    this.globalRegistry = globalRegistry;
+  @Autowired
+  public void setMeterRegistry(MeterRegistry meterRegistry) {
+    this.meterRegistry = meterRegistry;
+  }
+
+  public void start(EventBus eventBus) {
     this.eventBus = eventBus;
     this.executorService = Executors.newScheduledThreadPool(1,
         new ThreadFactoryBuilder()
             .setNameFormat("spectator-poller-%d")
             .build());
 
-    metricsInitializers.forEach(initializer -> initializer.init(globalRegistry, eventBus, config));
+    metricsInitializers.forEach(initializer -> initializer.init(this.meterRegistry, eventBus, config));
     startPoll();
   }
 
@@ -87,8 +92,7 @@ public class MetricsBootstrap {
 
   public synchronized void pollMeters() {
     try {
-      long secondInterval = TimeUnit.MILLISECONDS.toSeconds(config.getMsPollInterval());
-      PolledEvent polledEvent = globalRegistry.poll(secondInterval);
+      PolledEvent polledEvent = new PolledEvent(meterRegistry.getMeters());
       eventBus.post(polledEvent);
     } catch (Throwable e) {
       LOGGER.error("poll meters error. ", e);
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java
index 88201dcb2..3cb0b8f95 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java
@@ -16,19 +16,16 @@
  */
 package org.apache.servicecomb.foundation.metrics;
 
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
-
 import com.google.common.eventbus.EventBus;
 
+import io.micrometer.core.instrument.MeterRegistry;
+
 public interface MetricsInitializer {
   default int getOrder() {
     return 0;
   }
 
-  /**
-   * if create new registry, must add to globalRegistry
-   */
-  void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config);
+  void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config);
 
   default void destroy() {
 
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java
index 6b7c3018c..0814f9614 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java
@@ -18,17 +18,14 @@ package org.apache.servicecomb.foundation.metrics;
 
 import java.util.List;
 
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
+import io.micrometer.core.instrument.Meter;
+
 
 public class PolledEvent {
   private List<Meter> meters;
 
-  private List<Measurement> measurements;
-
-  public PolledEvent(List<Meter> meters, List<Measurement> measurements) {
+  public PolledEvent(List<Meter> meters) {
     this.meters = meters;
-    this.measurements = measurements;
   }
 
   public List<Meter> getMeters() {
@@ -38,12 +35,4 @@ public class PolledEvent {
   public void setMeters(List<Meter> meters) {
     this.meters = meters;
   }
-
-  public List<Measurement> getMeasurements() {
-    return measurements;
-  }
-
-  public void setMeasurements(List<Measurement> measurements) {
-    this.measurements = measurements;
-  }
 }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
index d9e2f46d5..bd8672e5a 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
@@ -19,8 +19,8 @@ package org.apache.servicecomb.foundation.metrics.meter;
 import java.util.Collections;
 import java.util.List;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+
 
 public abstract class AbstractPeriodMeter implements PeriodMeter {
   protected Id id;
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java
index 114f930f0..506375d09 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java
@@ -19,8 +19,10 @@ package org.apache.servicecomb.foundation.metrics.meter;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.LongAdder;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Tag;
 
 public class LatencyScopeMeter {
   private final Id scopeId;
@@ -36,8 +38,8 @@ public class LatencyScopeMeter {
   public LatencyScopeMeter(Id latencyDistributionId, LatencyScopeConfig config) {
     nanoMin = TimeUnit.MILLISECONDS.toNanos(config.getMsMin());
     nanoMax = TimeUnit.MILLISECONDS.toNanos(config.getMsMax());
-    scopeId = latencyDistributionId.withTag("scope",
-        String.format("[%d,%s)", config.getMsMin(), config.getMsMax() == Long.MAX_VALUE ? "" : config.getMsMax()));
+    scopeId = latencyDistributionId.withTag(Tag.of("scope",
+        String.format("[%d,%s)", config.getMsMin(), config.getMsMax() == Long.MAX_VALUE ? "" : config.getMsMax())));
   }
 
   public boolean update(long nanoLatency) {
@@ -54,6 +56,6 @@ public class LatencyScopeMeter {
     long deltaTimes = currentTimes - lastTimes;
     this.lastTimes = currentTimes;
 
-    return new Measurement(scopeId, msNow, deltaTimes);
+    return new Measurement(() -> deltaTimes, Statistic.VALUE);
   }
 }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
index f91d781e1..4fa57f13e 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
@@ -18,8 +18,9 @@ package org.apache.servicecomb.foundation.metrics.meter;
 
 import java.util.List;
 
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter;
+
 
 public interface PeriodMeter extends Meter {
   void calcMeasurements(long msNow, long secondInterval);
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
index 09803a471..f1860a783 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
@@ -21,10 +21,8 @@ import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.LongAdder;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Statistic;
-import com.netflix.spectator.impl.AtomicDouble;
+
+import io.micrometer.core.instrument.Measurement;
 
 /**
  * ServoTimer is too slow
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java
index 17d3d9a73..31af35c7a 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java
@@ -16,7 +16,8 @@
  */
 package org.apache.servicecomb.foundation.metrics.publish.spectator;
 
-import com.netflix.spectator.api.Tag;
+
+import io.micrometer.core.instrument.Tag;
 
 public class DefaultTagFinder implements TagFinder {
   private final String tagKey;
@@ -45,7 +46,7 @@ public class DefaultTagFinder implements TagFinder {
   @Override
   public Tag find(Iterable<Tag> tags) {
     for (Tag tag : tags) {
-      if (tag.key().equals(tagKey)) {
+      if (tag.getKey().equals(tagKey)) {
         return tag;
       }
     }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
index c138bea15..272f6b87e 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
@@ -21,7 +21,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
 
 public class MeasurementNode implements Comparable<MeasurementNode> {
   private final String name;
@@ -84,7 +84,7 @@ public class MeasurementNode implements Comparable<MeasurementNode> {
   public double summary() {
     double result = 0;
     for (Measurement measurement : measurements) {
-      result += measurement.value();
+      result += measurement.getValue();
     }
 
     return result;
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
index 79101fa16..e2dbd268b 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
@@ -19,10 +19,10 @@ package org.apache.servicecomb.foundation.metrics.publish.spectator;
 import java.util.Iterator;
 import java.util.List;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
-import com.netflix.spectator.api.Tag;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Tag;
 
 // like select * from meters group by ......
 // but output a tree not a table
@@ -38,22 +38,21 @@ public class MeasurementTree extends MeasurementNode {
   public void from(Iterator<Meter> meters, MeasurementGroupConfig groupConfig) {
     meters.forEachRemaining(meter -> {
       Iterable<Measurement> measurements = meter.measure();
-      from(measurements, groupConfig);
+      from(meter.getId(), measurements, groupConfig);
     });
   }
 
-  public void from(Iterable<Measurement> measurements, MeasurementGroupConfig groupConfig) {
+  public void from(Id id, Iterable<Measurement> measurements, MeasurementGroupConfig groupConfig) {
     for (Measurement measurement : measurements) {
-      Id id = measurement.id();
-      MeasurementNode node = addChild(id.name(), measurement);
+      MeasurementNode node = addChild(id.getName(), measurement);
 
-      List<TagFinder> tagFinders = groupConfig.findTagFinders(id.name());
+      List<TagFinder> tagFinders = groupConfig.findTagFinders(id.getName());
       if (tagFinders == null) {
         continue;
       }
 
       for (TagFinder tagFinder : tagFinders) {
-        Tag tag = tagFinder.find(id.tags());
+        Tag tag = tagFinder.find(id.getTags());
         if (tag == null) {
           if (tagFinder.skipOnNull()) {
             break;
@@ -64,7 +63,7 @@ public class MeasurementTree extends MeasurementNode {
                   measurement));
         }
 
-        node = node.addChild(tag.value(), measurement);
+        node = node.addChild(tag.getValue(), measurement);
       }
     }
   }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java
index 0762afb8d..a3c893b4b 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java
@@ -16,7 +16,7 @@
  */
 package org.apache.servicecomb.foundation.metrics.publish.spectator;
 
-import com.netflix.spectator.api.Tag;
+import io.micrometer.core.instrument.Tag;
 
 public interface TagFinder {
   static TagFinder build(Object obj) {
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
index 25e85b134..453c86495 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
@@ -16,99 +16,19 @@
  */
 package org.apache.servicecomb.foundation.metrics.registry;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
-import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
-
-import com.netflix.spectator.api.Clock;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.SpectatorUtils;
-
-public class GlobalRegistry {
-  private final Clock clock;
 
-  private final List<Registry> registries = new CopyOnWriteArrayList<>();
+import io.micrometer.core.instrument.MeterRegistry;
 
-  private Registry defaultRegistry;
 
-  public GlobalRegistry() {
-    this(Clock.SYSTEM);
-  }
-
-  public GlobalRegistry(Clock clock) {
-    this.clock = clock;
-  }
-
-  public Clock getClock() {
-    return clock;
-  }
-
-  public List<Registry> getRegistries() {
-    return registries;
-  }
-
-  public Registry getDefaultRegistry() {
-    return defaultRegistry;
-  }
-
-  public synchronized void add(Registry registry) {
-    if (registries.isEmpty()) {
-      defaultRegistry = registry;
-    }
-    registries.add(registry);
-  }
-
-  public synchronized void remove(Registry registry) {
-    registries.remove(registry);
-    if (registry != defaultRegistry) {
-      return;
-    }
-
-    if (registries.isEmpty()) {
-      defaultRegistry = null;
-      return;
-    }
-
-    defaultRegistry = registries.get(0);
-  }
-
-  public synchronized void removeAll() {
-    registries.clear();
-    defaultRegistry = null;
-  }
+public class GlobalRegistry {
+  private final MeterRegistry meterRegistry;
 
-  @SuppressWarnings("unchecked")
-  public <T extends Registry> T find(Class<T> cls) {
-    for (Registry registry : registries) {
-      if (cls.isAssignableFrom(registry.getClass())) {
-        return (T) registry;
-      }
-    }
-    return null;
+  public GlobalRegistry(MeterRegistry meterRegistry) {
+    this.meterRegistry = meterRegistry;
   }
 
   public PolledEvent poll(long secondInterval) {
-    long msNow = clock.wallTime();
-    List<Meter> meters = new ArrayList<>();
-    List<Measurement> measurements = new ArrayList<>();
-    for (Registry registry : registries) {
-      SpectatorUtils.removeExpiredMeters(registry);
-
-      for (Meter meter : registry) {
-        if (meter instanceof PeriodMeter) {
-          ((PeriodMeter) meter).calcMeasurements(msNow, secondInterval);
-        }
-
-        meters.add(meter);
-        meter.measure().forEach(measurements::add);
-      }
-    }
-
-    return new PolledEvent(meters, measurements);
+    return new PolledEvent(this.meterRegistry.getMeters());
   }
 }
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
index 466a0c5f1..02deb078b 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
@@ -25,7 +25,6 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.ScheduledExecutorService;
 
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.jupiter.api.Assertions;
@@ -36,13 +35,12 @@ import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.EventBus;
 
+import io.micrometer.core.instrument.MeterRegistry;
 import mockit.Deencapsulation;
 
 public class TestMetricsBootstrap {
   MetricsBootstrap bootstrap = new MetricsBootstrap();
 
-  GlobalRegistry globalRegistry = new GlobalRegistry();
-
   EventBus eventBus = new EventBus();
 
   Environment environment = Mockito.mock(Environment.class);
@@ -63,14 +61,14 @@ public class TestMetricsBootstrap {
     List<MetricsInitializer> initList = new ArrayList<>();
     MetricsInitializer metricsInitializer = new MetricsInitializer() {
       @Override
-      public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+      public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
         initList.add(this);
       }
     };
 
     bootstrap.setMetricsInitializers(Arrays.asList(metricsInitializer, metricsInitializer));
 
-    bootstrap.start(globalRegistry, eventBus);
+    bootstrap.start(eventBus);
     bootstrap.shutdown();
 
     MatcherAssert.assertThat(initList, Matchers.contains(metricsInitializer, metricsInitializer));
@@ -87,7 +85,7 @@ public class TestMetricsBootstrap {
       }
 
       @Override
-      public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+      public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
       }
 
       @Override
@@ -103,7 +101,7 @@ public class TestMetricsBootstrap {
       }
 
       @Override
-      public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+      public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
       }
 
       @Override
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
index 47b60ec47..adc08f1bb 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
@@ -16,12 +16,15 @@
  */
 package org.apache.servicecomb.foundation.metrics.meter;
 
-import com.netflix.spectator.api.SpectatorUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Meter.Type;
+import io.micrometer.core.instrument.Tags;
+
 public class TestSimpleTimer {
-  SimpleTimer timer = new SimpleTimer(SpectatorUtils.createDefaultId("name"));
+  SimpleTimer timer = new SimpleTimer(new Id("test", Tags.empty(), null, null, Type.TIMER));
 
   @Test
   public void measure() {
@@ -35,6 +38,6 @@ public class TestSimpleTimer {
         "[Measurement(name:statistic=count,1,1.0), Measurement(name:statistic=totalTime,1,3.0000000000000004E-9), Measurement(name:statistic=max,1,4.0E-9)]",
         timer.measure().toString());
     Assertions.assertFalse(timer.hasExpired());
-    Assertions.assertEquals("name", timer.id().name());
+    Assertions.assertEquals("name", timer.id().getName());
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java
deleted file mode 100644
index d48898c6b..000000000
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/DefaultRegistryInitializer.java
+++ /dev/null
@@ -1,63 +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.servicecomb.metrics.core;
-
-import java.time.Duration;
-
-import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
-
-import com.google.common.eventbus.EventBus;
-import com.netflix.servo.DefaultMonitorRegistry;
-
-public class DefaultRegistryInitializer implements MetricsInitializer {
-  public static final String SERVO_POLLERS = "servo.pollers";
-
-  private GlobalRegistry globalRegistry;
-
-  @SuppressWarnings("deprecation")
-  private com.netflix.spectator.servo.ServoRegistry registry;
-
-  // create registry before init meters
-  @Override
-  public int getOrder() {
-    return -10;
-  }
-
-  @Override
-  @SuppressWarnings("deprecation")
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    this.globalRegistry = globalRegistry;
-
-    // spectator move poll gauges from inline to background executor
-    // we need to set the interval to unify value
-    System.setProperty("spectator.api.gaugePollingFrequency", Duration.ofMillis(config.getMsPollInterval()).toString());
-
-    System.setProperty(SERVO_POLLERS, String.valueOf(config.getMsPollInterval()));
-    registry = new com.netflix.spectator.servo.ServoRegistry();
-    globalRegistry.add(registry);
-  }
-
-  @Override
-  public void destroy() {
-    if (registry != null) {
-      DefaultMonitorRegistry.getInstance().unregister(registry);
-      globalRegistry.remove(registry);
-    }
-  }
-}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
index 33912e987..4777fa347 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/InvocationMetersInitializer.java
@@ -21,7 +21,6 @@ import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.event.InvocationStartEvent;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.ConsumerMeters;
 import org.apache.servicecomb.metrics.core.meter.EdgeMeters;
 import org.apache.servicecomb.metrics.core.meter.ProducerMeters;
@@ -30,7 +29,8 @@ import org.apache.servicecomb.metrics.core.meter.invocation.AbstractInvocationMe
 import com.google.common.eventbus.AllowConcurrentEvents;
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
-import com.netflix.spectator.api.Registry;
+
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class InvocationMetersInitializer implements MetricsInitializer {
   private ConsumerMeters consumerMeters;
@@ -40,12 +40,10 @@ public class InvocationMetersInitializer implements MetricsInitializer {
   private EdgeMeters edgeMeters;
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    Registry registry = globalRegistry.getDefaultRegistry();
-
-    consumerMeters = new ConsumerMeters(registry, config);
-    producerMeters = new ProducerMeters(registry, config);
-    edgeMeters = new EdgeMeters(registry, config);
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    consumerMeters = new ConsumerMeters(meterRegistry, config);
+    producerMeters = new ProducerMeters(meterRegistry, config);
+    edgeMeters = new EdgeMeters(meterRegistry, config);
 
     eventBus.register(this);
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
index 91d6ea2a5..5d1dc7f60 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
@@ -42,11 +42,6 @@ public class MetricsCoreConfiguration {
     return new DefaultLogPublisher();
   }
 
-  @Bean
-  public DefaultRegistryInitializer defaultRegistryInitializer() {
-    return new DefaultRegistryInitializer();
-  }
-
   @Bean
   public InvocationMetersInitializer invocationMetersInitializer() {
     return new InvocationMetersInitializer();
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
index 88f01393f..03b6660ff 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
@@ -19,15 +19,14 @@ package org.apache.servicecomb.metrics.core;
 import org.apache.commons.lang3.SystemUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.SpectatorUtils;
+
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class OsMetersInitializer implements MetricsInitializer {
   private static final Logger LOGGER = LoggerFactory.getLogger(OsMetersInitializer.class);
@@ -43,15 +42,13 @@ public class OsMetersInitializer implements MetricsInitializer {
   }
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     if (!isOsLinux) {
       LOGGER.info("only support linux os to collect cpu and net info");
       return;
     }
 
-    Registry registry = globalRegistry.getDefaultRegistry();
-    osMeter = new OsMeter(registry);
-    SpectatorUtils.registerMeter(registry, osMeter);
+    osMeter = new OsMeter(meterRegistry);
   }
 
   public OsMeter getOsMeter() {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
index ad0123391..1c30f3951 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
@@ -26,27 +26,22 @@ import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.GroupExecutor;
-import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.BasicTag;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Tag;
-import com.netflix.spectator.api.patterns.PolledMeter;
-import com.netflix.spectator.api.patterns.ThreadPoolMonitor;
+
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class ThreadPoolMetersInitializer implements MetricsInitializer {
   public static String REJECTED_COUNT = "threadpool.rejectedCount";
 
-  private Registry registry;
+  private MeterRegistry meterRegistry;
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    registry = globalRegistry.getDefaultRegistry();
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    this.meterRegistry = meterRegistry;
 
     createThreadPoolMeters();
   }
@@ -93,15 +88,16 @@ public class ThreadPoolMetersInitializer implements MetricsInitializer {
       return;
     }
 
-    ThreadPoolMonitor.attach(registry, (ThreadPoolExecutor) executor, threadPoolName);
-
-    if (executor instanceof ThreadPoolExecutorEx) {
-      Tag idTag = new BasicTag("id", threadPoolName);
-
-      PolledMeter.using(registry)
-          .withName(REJECTED_COUNT)
-          .withTag(idTag)
-          .monitorMonotonicCounter((ThreadPoolExecutorEx) executor, ThreadPoolExecutorEx::getRejectedCount);
-    }
+    // TODO: add thread pool meter
+//    ThreadPoolMonitor.attach(registry, (ThreadPoolExecutor) executor, threadPoolName);
+//
+//    if (executor instanceof ThreadPoolExecutorEx) {
+//      Tag idTag = new BasicTag("id", threadPoolName);
+//
+//      PolledMeter.using(registry)
+//          .withName(REJECTED_COUNT)
+//          .withTag(idTag)
+//          .monitorMonotonicCounter((ThreadPoolExecutorEx) executor, ThreadPoolExecutorEx::getRejectedCount);
+//    }
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
index dd70b3873..51cee1400 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
@@ -18,16 +18,16 @@ package org.apache.servicecomb.metrics.core;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.vertx.SharedVertxFactory;
 import org.apache.servicecomb.metrics.core.meter.vertx.HttpClientEndpointsMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.ServerEndpointsMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.VertxEndpointsMeter;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.SpectatorUtils;
+
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
 
 public class VertxMetersInitializer implements MetricsInitializer {
   public static final String VERTX_ENDPOINTS = "servicecomb.vertx.endpoints";
@@ -39,23 +39,19 @@ public class VertxMetersInitializer implements MetricsInitializer {
   public static final String ENDPOINTS_SERVER = "server";
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    Registry registry = globalRegistry.getDefaultRegistry();
-
-    Id endpointsId = registry.createId(VERTX_ENDPOINTS);
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    Id endpointsId = new Id(VERTX_ENDPOINTS, null, null, null, null);
     VertxEndpointsMeter clientMeter = new HttpClientEndpointsMeter(
-        endpointsId.withTag(ENDPOINTS_TYPE, ENDPOINTS_CLINET),
+        endpointsId.withTag(Tag.of(ENDPOINTS_TYPE, ENDPOINTS_CLINET)),
         SharedVertxFactory.getMetricsFactory(config.getEnvironment())
             .getVertxMetrics()
             .getClientEndpointMetricManager()
             .getClientEndpointMetricMap());
-    SpectatorUtils.registerMeter(registry, clientMeter);
 
     VertxEndpointsMeter serverMeter = new ServerEndpointsMeter(
-        endpointsId.withTag(ENDPOINTS_TYPE, ENDPOINTS_SERVER),
+        endpointsId.withTag(Tag.of(ENDPOINTS_TYPE, ENDPOINTS_SERVER)),
         SharedVertxFactory.getMetricsFactory(config.getEnvironment())
             .getVertxMetrics()
             .getServerEndpointMetricMap());
-    SpectatorUtils.registerMeter(registry, serverMeter);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ConsumerMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ConsumerMeters.java
index bea132203..ccd7f49f6 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ConsumerMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ConsumerMeters.java
@@ -20,13 +20,13 @@ import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.metrics.core.meter.invocation.AbstractInvocationMeters;
 import org.apache.servicecomb.metrics.core.meter.invocation.ConsumerInvocationMeters;
 
-import com.netflix.spectator.api.Registry;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class ConsumerMeters {
   private final AbstractInvocationMeters invocationMeters;
 
-  public ConsumerMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
-    invocationMeters = new ConsumerInvocationMeters(registry, metricsBootstrapConfig);
+  public ConsumerMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
+    invocationMeters = new ConsumerInvocationMeters(meterRegistry, metricsBootstrapConfig);
   }
 
   public AbstractInvocationMeters getInvocationMeters() {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java
index 6da929165..b81403e89 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/EdgeMeters.java
@@ -21,14 +21,14 @@ import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.metrics.core.meter.invocation.AbstractInvocationMeters;
 import org.apache.servicecomb.metrics.core.meter.invocation.EdgeInvocationMeters;
 
-import com.netflix.spectator.api.Registry;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class EdgeMeters {
   private final AbstractInvocationMeters invocationMeters;
 
 
-  public EdgeMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
-    this.invocationMeters = new EdgeInvocationMeters(registry, metricsBootstrapConfig);
+  public EdgeMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
+    this.invocationMeters = new EdgeInvocationMeters(meterRegistry, metricsBootstrapConfig);
   }
 
   public AbstractInvocationMeters getInvocationMeters() {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ProducerMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ProducerMeters.java
index abe415864..1822b940f 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ProducerMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ProducerMeters.java
@@ -20,13 +20,13 @@ import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.metrics.core.meter.invocation.AbstractInvocationMeters;
 import org.apache.servicecomb.metrics.core.meter.invocation.ProducerInvocationMeters;
 
-import com.netflix.spectator.api.Registry;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class ProducerMeters {
   private final AbstractInvocationMeters invocationMeters;
 
-  public ProducerMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
-    invocationMeters = new ProducerInvocationMeters(registry, metricsBootstrapConfig);
+  public ProducerMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
+    invocationMeters = new ProducerInvocationMeters(meterRegistry, metricsBootstrapConfig);
   }
 
   public AbstractInvocationMeters getInvocationMeters() {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index 362ae1dfb..1ffbe068a 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -26,8 +26,8 @@ import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
 import org.apache.servicecomb.foundation.metrics.meter.LatencyDistributionMeter;
 import org.apache.servicecomb.foundation.metrics.meter.SimpleTimer;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+
 
 public abstract class AbstractInvocationMeter extends AbstractPeriodMeter {
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
index bca004e65..ce9283e3d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeters.java
@@ -25,12 +25,15 @@ import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.swagger.invocation.Response;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Registry;
 import com.netflix.spectator.api.SpectatorUtils;
 
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Meter.Type;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+
 public abstract class AbstractInvocationMeters {
-  protected Registry registry;
+  protected MeterRegistry registry;
 
   private final Map<String, AbstractInvocationMeter> metersMap = new ConcurrentHashMapEx<>();
 
@@ -39,13 +42,13 @@ public abstract class AbstractInvocationMeters {
 
   protected MetricsBootstrapConfig metricsBootstrapConfig;
 
-  public AbstractInvocationMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
+  public AbstractInvocationMeters(MeterRegistry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
     this.registry = registry;
     this.metricsBootstrapConfig = metricsBootstrapConfig;
   }
 
   protected AbstractInvocationMeter getOrCreateMeters(Invocation invocation, Response response) {
-    // build string key is faster then use Id to locate timer directly
+    // build string key is faster than use Id to locate timer directly
     StringBuilder keyBuilder = new StringBuilder(maxKeyLen);
     String invocationName;
     //check edge
@@ -65,15 +68,12 @@ public abstract class AbstractInvocationMeters {
     }
 
     return metersMap.computeIfAbsent(keyBuilder.toString(), k -> {
-      Id id = registry.createId(MeterInvocationConst.INVOCATION_NAME,
-          MeterInvocationConst.TAG_ROLE,
-          invocationName,
-          MeterInvocationConst.TAG_TRANSPORT,
-          invocation.getRealTransportName(),
-          MeterInvocationConst.TAG_OPERATION,
-          invocation.getMicroserviceQualifiedName(),
-          MeterInvocationConst.TAG_STATUS,
-          String.valueOf(response.getStatusCode()));
+      Id id = new Id(MeterInvocationConst.INVOCATION_NAME, Tags.empty()
+          .and(MeterInvocationConst.TAG_ROLE, invocationName)
+          .and(MeterInvocationConst.TAG_TRANSPORT, invocation.getRealTransportName())
+          .and(MeterInvocationConst.TAG_OPERATION, invocation.getMicroserviceQualifiedName())
+          .and(MeterInvocationConst.TAG_STATUS, String.valueOf(response.getStatusCode())),
+          null, null, Type.OTHER);
 
       AbstractInvocationMeter meter = createMeter(id);
       SpectatorUtils.registerMeter(registry, meter);
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
index fd0729ca7..d46faa803 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ConsumerInvocationMeters.java
@@ -18,12 +18,12 @@ package org.apache.servicecomb.metrics.core.meter.invocation;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Registry;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class ConsumerInvocationMeters extends AbstractInvocationMeters {
-  public ConsumerInvocationMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
-    super(registry, metricsBootstrapConfig);
+  public ConsumerInvocationMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
+    super(meterRegistry, metricsBootstrapConfig);
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
index 2a5b0bddd..872a811b7 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/EdgeInvocationMeters.java
@@ -19,12 +19,12 @@ package org.apache.servicecomb.metrics.core.meter.invocation;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Registry;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class EdgeInvocationMeters extends ConsumerInvocationMeters {
-  public EdgeInvocationMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
-    super(registry, metricsBootstrapConfig);
+  public EdgeInvocationMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
+    super(meterRegistry, metricsBootstrapConfig);
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
index fefe50708..60e86493c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/ProducerInvocationMeters.java
@@ -18,12 +18,12 @@ package org.apache.servicecomb.metrics.core.meter.invocation;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Registry;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class ProducerInvocationMeters extends AbstractInvocationMeters {
-  public ProducerInvocationMeters(Registry registry, MetricsBootstrapConfig metricsBootstrapConfig) {
-    super(registry, metricsBootstrapConfig);
+  public ProducerInvocationMeters(MeterRegistry meterRegistry, MetricsBootstrapConfig metricsBootstrapConfig) {
+    super(meterRegistry, metricsBootstrapConfig);
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
index 587c11419..fdc7e8022 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
@@ -23,8 +23,11 @@ import org.apache.servicecomb.metrics.core.meter.os.cpu.ProcessCpuUsage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Tag;
+
 
 public class CpuMeter {
   private static final Logger LOGGER = LoggerFactory.getLogger(CpuMeter.class);
@@ -36,8 +39,8 @@ public class CpuMeter {
   private final ProcessCpuUsage processCpuUsage;
 
   public CpuMeter(Id id) {
-    allCpuUsage = new OsCpuUsage(id.withTag(OsMeter.OS_TYPE, OsMeter.OS_TYPE_ALL_CPU));
-    processCpuUsage = new ProcessCpuUsage(id.withTag(OsMeter.OS_TYPE, OsMeter.OS_TYPE_PROCESS_CPU));
+    allCpuUsage = new OsCpuUsage(id.withTag(Tag.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_ALL_CPU)));
+    processCpuUsage = new ProcessCpuUsage(id.withTag(Tag.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_PROCESS_CPU)));
 
     //must refresh all first
     update();
@@ -47,8 +50,8 @@ public class CpuMeter {
 
   public void calcMeasurements(List<Measurement> measurements, long msNow) {
     update();
-    measurements.add(new Measurement(allCpuUsage.getId(), msNow, allCpuUsage.getUsage()));
-    measurements.add(new Measurement(processCpuUsage.getId(), msNow, processCpuUsage.getUsage()));
+    measurements.add(new Measurement(() -> allCpuUsage.getUsage(), Statistic.VALUE));
+    measurements.add(new Measurement(() -> processCpuUsage.getUsage(), Statistic.VALUE));
   }
 
   public void update() {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
index 5c9bc69cc..d7893095b 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
@@ -31,10 +31,10 @@ import org.apache.servicecomb.metrics.core.meter.os.net.NetStat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.netflix.spectator.api.BasicTag;
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Tag;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Tag;
+
 
 public class NetMeter {
   private static final Logger LOGGER = LoggerFactory.getLogger(NetMeter.class);
@@ -43,13 +43,13 @@ public class NetMeter {
 
   public static final String INTERFACE = "interface";
 
-  public static final Tag TAG_RECEIVE = new BasicTag(STATISTIC, "receive");
+  public static final Tag TAG_RECEIVE = Tag.of(STATISTIC, "receive");
 
-  public static final Tag TAG_PACKETS_RECEIVE = new BasicTag(STATISTIC, "receivePackets");
+  public static final Tag TAG_PACKETS_RECEIVE = Tag.of(STATISTIC, "receivePackets");
 
-  public static final Tag TAG_SEND = new BasicTag(STATISTIC, "send");
+  public static final Tag TAG_SEND = Tag.of(STATISTIC, "send");
 
-  public static final Tag TAG_PACKETS_SEND = new BasicTag(STATISTIC, "sendPackets");
+  public static final Tag TAG_PACKETS_SEND = Tag.of(STATISTIC, "sendPackets");
 
   private final Id id;
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
index 8bc157c17..7425e28fc 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
@@ -22,8 +22,10 @@ import java.util.List;
 import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Registry;
+
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
 
 /**
  * name=os type=cpu value = 0
@@ -48,10 +50,10 @@ public class OsMeter extends AbstractPeriodMeter {
 
   private final NetMeter netMeter;
 
-  public OsMeter(Registry registry) {
-    this.id = registry.createId(OS_NAME);
+  public OsMeter(MeterRegistry meterRegistry) {
+    this.id = Id.
     cpuMeter = new CpuMeter(id);
-    netMeter = new NetMeter(id.withTag(OS_TYPE, OS_TYPE_NET));
+    netMeter = new NetMeter(id.withTag(Tag.of(OS_TYPE, OS_TYPE_NET)));
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java
index 375a64875..8605edeb5 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java
@@ -16,7 +16,8 @@
  */
 package org.apache.servicecomb.metrics.core.meter.os.cpu;
 
-import com.netflix.spectator.api.Id;
+
+import io.micrometer.core.instrument.Meter.Id;
 
 public abstract class AbstractCpuUsage {
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java
index 364ca10b4..8b40f212c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java
@@ -18,7 +18,7 @@ package org.apache.servicecomb.metrics.core.meter.os.cpu;
 
 import java.io.IOException;
 
-import com.netflix.spectator.api.Id;
+import io.micrometer.core.instrument.Meter.Id;
 
 /*
  * unit : 1 jiffies
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java
index 00ec8cb5e..6ab7ad828 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java
@@ -18,7 +18,7 @@ package org.apache.servicecomb.metrics.core.meter.os.cpu;
 
 import java.io.IOException;
 
-import com.netflix.spectator.api.Id;
+import io.micrometer.core.instrument.Meter.Id;
 
 /*
  * unit : 1 jiffies
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
index c29d9598f..a72217894 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
@@ -25,8 +25,10 @@ import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_SEND;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Tag;
 
 public class InterfaceUsage {
   private final String name;
@@ -35,7 +37,7 @@ public class InterfaceUsage {
 
   public InterfaceUsage(Id id, String name) {
     this.name = name;
-    id = id.withTag(INTERFACE, name);
+    id = id.withTag(Tag.of(INTERFACE, name));
     init(id);
   }
 
@@ -52,7 +54,7 @@ public class InterfaceUsage {
   }
 
   public void calcMeasurements(List<Measurement> measurements, long msNow) {
-    netStats.forEach(netStat -> measurements.add(new Measurement(netStat.getId(), msNow, netStat.getRate())));
+    netStats.forEach(netStat -> measurements.add(new Measurement(() -> netStat.getRate(), Statistic.VALUE)));
   }
 
   public void update(String interfaceData, long secondInterval) {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java
index 3d3f08b70..48b3d9d7d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java
@@ -16,7 +16,8 @@
  */
 package org.apache.servicecomb.metrics.core.meter.os.net;
 
-import com.netflix.spectator.api.Id;
+
+import io.micrometer.core.instrument.Meter.Id;
 
 public class NetStat {
   private final int index;
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
index d0ce37bc6..2217c8204 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
@@ -21,8 +21,10 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Tag;
+
 
 public class EndpointMeter {
   private static final double SNV_MILLI_SECONDS = 1.0 / TimeUnit.MILLISECONDS.toNanos(1L);
@@ -76,15 +78,15 @@ public class EndpointMeter {
   private long lastLatency;
 
   public EndpointMeter(Id id, DefaultEndpointMetric metric) {
-    id = id.withTag(ADDRESS, metric.getAddress());
+    id = id.withTag(Tag.of(ADDRESS, metric.getAddress()));
     this.id = id;
-    idConnect = id.withTag(STATISTIC, CONNECT_COUNT);
-    idDisconnect = id.withTag(STATISTIC, DISCONNECT_COUNT);
-    idConnections = id.withTag(STATISTIC, CONNECTIONS);
-    idBytesRead = id.withTag(STATISTIC, BYTES_READ);
-    idBytesWritten = id.withTag(STATISTIC, BYTES_WRITTEN);
-    idRequests = id.withTag(STATISTIC, REQUESTS);
-    idLatency = id.withTag(STATISTIC, LATENCY);
+    idConnect = id.withTag(Tag.of(STATISTIC, CONNECT_COUNT);
+    idDisconnect = id.withTag(Tag.of(STATISTIC, DISCONNECT_COUNT));
+    idConnections = id.withTag(Tag.of(STATISTIC, CONNECTIONS));
+    idBytesRead = id.withTag(Tag.of(STATISTIC, BYTES_READ));
+    idBytesWritten = id.withTag(Tag.of(STATISTIC, BYTES_WRITTEN));
+    idRequests = id.withTag(Tag.of(STATISTIC, REQUESTS));
+    idLatency = id.withTag(Tag.of(STATISTIC, LATENCY));
     this.metric = metric;
   }
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
index 57430bae4..a8c3c4db9 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
@@ -20,11 +20,12 @@ import java.util.Map;
 
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import com.netflix.spectator.api.Id;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class HttpClientEndpointsMeter extends VertxEndpointsMeter {
-  public <T extends DefaultEndpointMetric> HttpClientEndpointsMeter(Id id, Map<String, T> endpointMetricMap) {
-    super(id, endpointMetricMap);
+  public <T extends DefaultEndpointMetric> HttpClientEndpointsMeter(MeterRegistry meterRegistry, Id id,
+      Map<String, T> endpointMetricMap) {
+    super(meterRegistry, id, endpointMetricMap);
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
index ab7f4d95d..7bed21427 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
@@ -24,17 +24,21 @@ import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
 
 public class VertxEndpointsMeter extends AbstractPeriodMeter {
   private final Map<String, DefaultEndpointMetric> endpointMetricMap;
 
+  private final MeterRegistry meterRegistry;
+
   private final Map<String, EndpointMeter> endpointMeterMap = new ConcurrentHashMapEx<>();
 
   @SuppressWarnings("unchecked")
-  public <T extends DefaultEndpointMetric> VertxEndpointsMeter(Id id, Map<String, T> endpointMetricMap) {
+  public <T extends DefaultEndpointMetric> VertxEndpointsMeter(MeterRegistry meterRegistry, Id id,
+      Map<String, T> endpointMetricMap) {
     this.id = id;
+    this.meterRegistry = meterRegistry;
     this.endpointMetricMap = (Map<String, DefaultEndpointMetric>) endpointMetricMap;
   }
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index b9d20995b..2f45238d9 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -31,7 +31,6 @@ import org.apache.servicecomb.foundation.metrics.meter.LatencyDistributionConfig
 import org.apache.servicecomb.foundation.metrics.meter.LatencyScopeConfig;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
 import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
@@ -50,8 +49,9 @@ import org.springframework.core.env.Environment;
 import com.google.common.base.Strings;
 import com.google.common.eventbus.EventBus;
 import com.google.common.eventbus.Subscribe;
-import com.netflix.spectator.api.Meter;
 
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
 import io.vertx.core.Vertx;
 
 public class DefaultLogPublisher implements MetricsInitializer {
@@ -102,7 +102,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
   }
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     if (!environment.getProperty(ENABLED, boolean.class, false)) {
       return;
     }
@@ -181,10 +181,10 @@ public class DefaultLogPublisher implements MetricsInitializer {
 
     StringBuilder tmpSb = new StringBuilder();
     for (MeasurementNode interfaceNode : netNode.getChildren().values()) {
-      double sendRate = interfaceNode.findChild(NetMeter.TAG_SEND.value()).summary();
-      double sendPacketsRate = interfaceNode.findChild(NetMeter.TAG_PACKETS_SEND.value()).summary();
-      double receiveRate = interfaceNode.findChild(NetMeter.TAG_RECEIVE.value()).summary();
-      double receivePacketsRate = interfaceNode.findChild(NetMeter.TAG_PACKETS_RECEIVE.value()).summary();
+      double sendRate = interfaceNode.findChild(NetMeter.TAG_SEND.getValue()).summary();
+      double sendPacketsRate = interfaceNode.findChild(NetMeter.TAG_PACKETS_SEND.getValue()).summary();
+      double receiveRate = interfaceNode.findChild(NetMeter.TAG_RECEIVE.getValue()).summary();
+      double receivePacketsRate = interfaceNode.findChild(NetMeter.TAG_PACKETS_RECEIVE.getValue()).summary();
       if (sendRate == 0 && receiveRate == 0 && receivePacketsRate == 0 && sendPacketsRate == 0) {
         continue;
       }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
index 69e1d7b3f..68aaad35c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
@@ -31,9 +31,10 @@ import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 
-import com.netflix.spectator.api.Meter;
 import com.netflix.spectator.api.patterns.ThreadPoolMonitorPublishModelFactory;
 
+import io.micrometer.core.instrument.Meter;
+
 public class PublishModelFactory {
   private final MeasurementTree tree;
 
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java
deleted file mode 100644
index 35fcd4ede..000000000
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestDefaultRegistryInitializer.java
+++ /dev/null
@@ -1,73 +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.servicecomb.metrics.core;
-
-import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN;
-import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.DEFAULT_METRICS_WINDOW_TIME;
-import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.METRICS_WINDOW_TIME;
-
-import java.util.List;
-
-import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
-import org.junit.Test;
-import org.junit.jupiter.api.Assertions;
-import org.mockito.Mockito;
-import org.springframework.core.env.Environment;
-
-import com.google.common.eventbus.EventBus;
-import com.netflix.servo.DefaultMonitorRegistry;
-import com.netflix.spectator.api.Registry;
-
-import mockit.Deencapsulation;
-
-public class TestDefaultRegistryInitializer {
-  GlobalRegistry globalRegistry = new GlobalRegistry();
-
-  List<Registry> registries = Deencapsulation.getField(globalRegistry, "registries");
-
-  DefaultRegistryInitializer registryInitializer = new DefaultRegistryInitializer();
-
-  Environment environment = Mockito.mock(Environment.class);
-
-  @Test
-  @SuppressWarnings("deprecation")
-  public void init() {
-    Mockito.when(environment.getProperty(METRICS_WINDOW_TIME, int.class, DEFAULT_METRICS_WINDOW_TIME))
-        .thenReturn(DEFAULT_METRICS_WINDOW_TIME);
-    Mockito.when(environment.getProperty(
-            CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
-        .thenReturn(7);
-    registryInitializer.init(globalRegistry, new EventBus(), new MetricsBootstrapConfig(environment));
-
-    Assertions.assertEquals(-10, registryInitializer.getOrder());
-    Assertions.assertTrue(globalRegistry.getDefaultRegistry() instanceof com.netflix.spectator.servo.ServoRegistry);
-    Assertions.assertEquals(1, registries.size());
-    Assertions.assertEquals(0, DefaultMonitorRegistry.getInstance().getRegisteredMonitors().size());
-
-    registryInitializer.destroy();
-
-    Assertions.assertEquals(0, registries.size());
-    Assertions.assertEquals(0, DefaultMonitorRegistry.getInstance().getRegisteredMonitors().size());
-  }
-
-  @Test
-  public void destroy_notInit() {
-    // should not throw exception
-    registryInitializer.destroy();
-  }
-}
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
index 375627d9b..6f71a126d 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
@@ -28,23 +28,22 @@ import java.util.List;
 import org.apache.commons.io.FileUtils;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.CpuUtils;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+import org.mockito.Mockito;
 
 import com.google.common.collect.Lists;
 import com.google.common.io.CharSource;
 import com.google.common.io.Files;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Registry;
 
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
-import org.junit.jupiter.api.Assertions;
 
 public class TestOsMeter {
-  Registry registry = new DefaultRegistry(new ManualClock());
+  MeterRegistry meterRegistry = Mockito.mock(MeterRegistry.class);
 
   @Test
   public void testCalcMeasurement(@Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
@@ -91,7 +90,7 @@ public class TestOsMeter {
         result = "1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1";
       }
     };
-    OsMeter osMeter = new OsMeter(registry);
+    OsMeter osMeter = new OsMeter(meterRegistry);
     list.clear();
     list.add("useless");
     list.add("useless");
@@ -105,11 +104,11 @@ public class TestOsMeter {
     osMeter.calcMeasurements(1, 1);
     ArrayList<Measurement> measurements = Lists.newArrayList(osMeter.measure());
     Assertions.assertEquals(6, measurements.size());
-    Assertions.assertEquals(0.875, measurements.get(0).value(), 0.0);
-    Assertions.assertEquals(0.5, measurements.get(1).value(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(2).value(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(3).value(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(4).value(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(5).value(), 0.0);
+    Assertions.assertEquals(0.875, measurements.get(0).getValue(), 0.0);
+    Assertions.assertEquals(0.5, measurements.get(1).getValue(), 0.0);
+    Assertions.assertEquals(1.0, measurements.get(2).getValue(), 0.0);
+    Assertions.assertEquals(1.0, measurements.get(3).getValue(), 0.0);
+    Assertions.assertEquals(1.0, measurements.get(4).getValue(), 0.0);
+    Assertions.assertEquals(1.0, measurements.get(5).getValue(), 0.0);
   }
 }
diff --git a/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java b/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java
index 12ae5041d..19cd28d51 100644
--- a/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java
+++ b/metrics/metrics-integration/metrics-prometheus/src/main/java/org/apache/servicecomb/metrics/prometheus/PrometheusPublisher.java
@@ -25,18 +25,17 @@ import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Tag;
 
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
 import io.prometheus.client.Collector;
 import io.prometheus.client.Collector.MetricFamilySamples.Sample;
 import io.prometheus.client.CollectorRegistry;
@@ -49,7 +48,7 @@ public class PrometheusPublisher extends Collector implements Collector.Describa
 
   private HTTPServer httpServer;
 
-  private GlobalRegistry globalRegistry;
+  private MeterRegistry meterRegistry;
 
   private Environment environment;
 
@@ -59,8 +58,8 @@ public class PrometheusPublisher extends Collector implements Collector.Describa
   }
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    this.globalRegistry = globalRegistry;
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    this.meterRegistry = meterRegistry;
 
     //prometheus default port allocation is here : https://github.com/prometheus/prometheus/wiki/Default-port-allocations
     String address = environment.getProperty(METRICS_PROMETHEUS_ADDRESS, String.class, "0.0.0.0:9696");
@@ -87,18 +86,14 @@ public class PrometheusPublisher extends Collector implements Collector.Describa
   @Override
   public List<MetricFamilySamples> describe() {
     List<MetricFamilySamples> familySamples = new ArrayList<>();
-    if (globalRegistry == null) {
-      return familySamples;
-    }
 
     List<Sample> samples = new ArrayList<>();
-    for (Registry registry : globalRegistry.getRegistries()) {
-      for (Meter meter : registry) {
-        meter.measure().forEach(measurement -> {
-          Sample sample = convertMeasurementToSample(measurement);
-          samples.add(sample);
-        });
-      }
+
+    for (Meter meter : this.meterRegistry.getMeters()) {
+      meter.measure().forEach(measurement -> {
+        Sample sample = convertMeasurementToSample(meter, measurement);
+        samples.add(sample);
+      });
     }
 
     familySamples.add(new MetricFamilySamples("ServiceComb_Metrics", Type.UNKNOWN, "ServiceComb Metrics", samples));
@@ -106,20 +101,20 @@ public class PrometheusPublisher extends Collector implements Collector.Describa
     return familySamples;
   }
 
-  protected Sample convertMeasurementToSample(Measurement measurement) {
-    String prometheusName = measurement.id().name().replace(".", "_");
+  protected Sample convertMeasurementToSample(Meter meter, Measurement measurement) {
+    String prometheusName = meter.getId().getName().replace(".", "_");
     List<String> labelNames = new ArrayList<>();
     List<String> labelValues = new ArrayList<>();
 
     labelNames.add("appId");
     labelValues.add(BootStrapProperties.readApplication(environment));
 
-    for (Tag tag : measurement.id().tags()) {
-      labelNames.add(tag.key());
-      labelValues.add(tag.value());
+    for (Tag tag : meter.getId().getTags()) {
+      labelNames.add(tag.getKey());
+      labelValues.add(tag.getValue());
     }
 
-    return new Sample(prometheusName, labelNames, labelValues, measurement.value());
+    return new Sample(prometheusName, labelNames, labelValues, measurement.getValue());
   }
 
   @Override
diff --git a/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java b/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java
index 6cb73136d..65103dbb2 100644
--- a/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java
+++ b/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java
@@ -24,38 +24,33 @@ import java.util.stream.StreamSupport;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Meter;
-import com.netflix.spectator.api.Registry;
+
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.MeterRegistry;
 
 @RestSchema(schemaId = MetricsEndpoint.NAME, schemaInterface = MetricsEndpoint.class)
 public class MetricsEndpointImpl implements MetricsInitializer, MetricsEndpoint {
-  private GlobalRegistry globalRegistry;
+  private MeterRegistry meterRegistry;
 
   @Override
-  public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    this.globalRegistry = globalRegistry;
+  public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
+    this.meterRegistry = meterRegistry;
   }
 
   @Override
   public Map<String, Double> measure() {
     Map<String, Double> measurements = new LinkedHashMap<>();
-    if (globalRegistry == null) {
-      return measurements;
-    }
-
     StringBuilder sb = new StringBuilder();
-    for (Registry registry : globalRegistry.getRegistries()) {
-      for (Meter meter : registry) {
-        meter.measure().forEach(measurement -> {
-          String key = idToString(measurement.id(), sb);
-          measurements.put(key, measurement.value());
-        });
-      }
+
+    for (Meter meter : this.meterRegistry.getMeters()) {
+      meter.measure().forEach(measurement -> {
+        String key = idToString(meter.getId(), sb);
+        measurements.put(key, measurement.getValue());
+      });
     }
 
     return measurements;
@@ -65,10 +60,10 @@ public class MetricsEndpointImpl implements MetricsInitializer, MetricsEndpoint
   // idName(tag1=value1,tag2=value2)
   protected String idToString(Id id, StringBuilder sb) {
     sb.setLength(0);
-    sb.append(id.name()).append('(');
+    sb.append(id.getName()).append('(');
     sb.append(StreamSupport
         .stream(id
-            .tags()
+            .getTags()
             .spliterator(), false)
         .map(Object::toString)
         .collect(


(servicecomb-java-chassis) 04/11: [SCB-2838]using micrometer to replace spectator part3: OsMeter

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 07e85f0acc2cd7620253103c55d7b5814d0601b9
Author: liubao <bi...@qq.com>
AuthorDate: Mon Nov 27 11:57:27 2023 +0800

    [SCB-2838]using micrometer to replace spectator part3: OsMeter
---
 .../foundation/metrics/MetricsBootstrap.java       |  6 +++
 .../metrics/meter/AbstractPeriodMeter.java         | 42 ----------------
 .../foundation/metrics/meter/PeriodMeter.java      |  2 +-
 .../metrics/core/OsMetersInitializer.java          | 10 +++-
 .../metrics/core/meter/os/CpuMeter.java            | 41 ++++++++--------
 .../metrics/core/meter/os/NetMeter.java            | 47 ++++++++----------
 .../servicecomb/metrics/core/meter/os/OsMeter.java | 28 ++++-------
 .../core/meter/os/cpu/AbstractCpuUsage.java        | 13 -----
 .../metrics/core/meter/os/cpu/OsCpuUsage.java      |  5 +-
 .../metrics/core/meter/os/cpu/ProcessCpuUsage.java |  5 +-
 .../metrics/core/meter/os/net/InterfaceUsage.java  | 56 +++++++++++-----------
 .../metrics/core/meter/os/net/NetStat.java         | 11 +----
 12 files changed, 93 insertions(+), 173 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
index 2521650f6..72be58c9d 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
@@ -22,6 +22,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -91,6 +92,11 @@ public class MetricsBootstrap {
   }
 
   public synchronized void pollMeters() {
+    metricsInitializers.forEach(initializer -> {
+      if (initializer instanceof PeriodMeter) {
+        ((PeriodMeter) initializer).poll(System.currentTimeMillis(), config.getMsPollInterval());
+      }
+    });
     try {
       PolledEvent polledEvent = new PolledEvent(meterRegistry.getMeters());
       eventBus.post(polledEvent);
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
deleted file mode 100644
index bd8672e5a..000000000
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java
+++ /dev/null
@@ -1,42 +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.servicecomb.foundation.metrics.meter;
-
-import java.util.Collections;
-import java.util.List;
-
-import io.micrometer.core.instrument.Measurement;
-
-
-public abstract class AbstractPeriodMeter implements PeriodMeter {
-  protected Id id;
-
-  protected List<Measurement> allMeasurements = Collections.emptyList();
-
-  public Id id() {
-    return id;
-  }
-
-  @Override
-  public Iterable<Measurement> measure() {
-    return allMeasurements;
-  }
-
-  public boolean hasExpired() {
-    return false;
-  }
-}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
index 3fcbf41bd..a846d0817 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
@@ -17,5 +17,5 @@
 package org.apache.servicecomb.foundation.metrics.meter;
 
 public interface PeriodMeter {
-  void calcMeasurements(long msNow, long secondInterval);
+  void poll(long msNow, long secondInterval);
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
index 03b6660ff..2c5b0e28a 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/OsMetersInitializer.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.metrics.core;
 import org.apache.commons.lang3.SystemUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -28,7 +29,7 @@ import com.google.common.eventbus.EventBus;
 
 import io.micrometer.core.instrument.MeterRegistry;
 
-public class OsMetersInitializer implements MetricsInitializer {
+public class OsMetersInitializer implements MetricsInitializer, PeriodMeter {
   private static final Logger LOGGER = LoggerFactory.getLogger(OsMetersInitializer.class);
 
   private OsMeter osMeter;
@@ -54,4 +55,11 @@ public class OsMetersInitializer implements MetricsInitializer {
   public OsMeter getOsMeter() {
     return osMeter;
   }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    if (osMeter != null) {
+      osMeter.poll(msNow, secondInterval);
+    }
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
index fdc7e8022..f7d7f83b2 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
@@ -16,20 +16,21 @@
  */
 package org.apache.servicecomb.metrics.core.meter.os;
 
-import java.util.List;
+import java.io.IOException;
 
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.OsCpuUsage;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.ProcessCpuUsage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.micrometer.core.instrument.Measurement;
-import io.micrometer.core.instrument.Meter.Id;
-import io.micrometer.core.instrument.Statistic;
-import io.micrometer.core.instrument.Tag;
+import com.google.common.annotations.VisibleForTesting;
 
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
-public class CpuMeter {
+public class CpuMeter implements PeriodMeter {
   private static final Logger LOGGER = LoggerFactory.getLogger(CpuMeter.class);
 
   // read from /proc/stat
@@ -38,35 +39,33 @@ public class CpuMeter {
   // read from /proc/self/stat /proc/uptime
   private final ProcessCpuUsage processCpuUsage;
 
-  public CpuMeter(Id id) {
-    allCpuUsage = new OsCpuUsage(id.withTag(Tag.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_ALL_CPU)));
-    processCpuUsage = new ProcessCpuUsage(id.withTag(Tag.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_PROCESS_CPU)));
+  public CpuMeter(MeterRegistry meterRegistry, String name) {
+    allCpuUsage = new OsCpuUsage();
+    processCpuUsage = new ProcessCpuUsage();
 
-    //must refresh all first
-    update();
-    allCpuUsage.setUsage(0);
-    processCpuUsage.setUsage(0);
-  }
+    Gauge.builder(name, allCpuUsage::getUsage).tags(Tags.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_ALL_CPU))
+        .register(meterRegistry);
 
-  public void calcMeasurements(List<Measurement> measurements, long msNow) {
-    update();
-    measurements.add(new Measurement(() -> allCpuUsage.getUsage(), Statistic.VALUE));
-    measurements.add(new Measurement(() -> processCpuUsage.getUsage(), Statistic.VALUE));
+    Gauge.builder(name, processCpuUsage::getUsage).tags(Tags.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_PROCESS_CPU))
+        .register(meterRegistry);
   }
 
-  public void update() {
+  @Override
+  public void poll(long msNow, long secondInterval) {
     try {
       allCpuUsage.update();
       processCpuUsage.update();
-    } catch (Throwable e) {
-      LOGGER.error("Failed to update usage", e);
+    } catch (IOException e) {
+      LOGGER.error("Failed to update cpu usage", e);
     }
   }
 
+  @VisibleForTesting
   public OsCpuUsage getAllCpuUsage() {
     return allCpuUsage;
   }
 
+  @VisibleForTesting
   public ProcessCpuUsage getProcessCpuUsage() {
     return processCpuUsage;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
index d7893095b..28427801b 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
@@ -19,24 +19,22 @@ package org.apache.servicecomb.metrics.core.meter.os;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.metrics.core.meter.os.net.InterfaceUsage;
-import org.apache.servicecomb.metrics.core.meter.os.net.NetStat;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.micrometer.core.instrument.Measurement;
-import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Tags;
 
 
-public class NetMeter {
+public class NetMeter implements PeriodMeter {
   private static final Logger LOGGER = LoggerFactory.getLogger(NetMeter.class);
 
   public static final String STATISTIC = "statistic";
@@ -51,23 +49,24 @@ public class NetMeter {
 
   public static final Tag TAG_PACKETS_SEND = Tag.of(STATISTIC, "sendPackets");
 
-  private final Id id;
-
   private final Map<String, InterfaceUsage> interfaceUsageMap = new ConcurrentHashMap<>();
 
-  public NetMeter(Id id) {
-    this.id = id;
-    // init lastRxBytes, lastRxPackets, lastTxBytes, lastTxPackets
-    refreshNet(1);
-    interfaceUsageMap.values().forEach(interfaceUsage -> interfaceUsage.getNetStats().forEach(NetStat::clearRate));
-  }
+  protected final MeterRegistry meterRegistry;
 
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    refreshNet(secondInterval);
+  protected final String name;
 
-    interfaceUsageMap.values().forEach(interfaceUsage -> interfaceUsage.calcMeasurements(measurements, msNow));
+  protected final Tags tags;
+
+  public NetMeter(MeterRegistry meterRegistry, String name, Tags tags) {
+    this.meterRegistry = meterRegistry;
+    this.name = name;
+    this.tags = tags;
   }
 
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    refreshNet(secondInterval);
+  }
 
   /*
    * Inter-|   Receive                                                            |  Transmit
@@ -79,7 +78,6 @@ public class NetMeter {
     try {
       File file = new File("/proc/net/dev");
       List<String> netInfo = FileUtils.readLines(file, StandardCharsets.UTF_8);
-      Set<String> nameSet = new HashSet<>();
 
       //the first two lines is useless
       for (int i = 2; i < netInfo.size(); i++) {
@@ -90,19 +88,12 @@ public class NetMeter {
           continue;
         }
 
-        String name = strings[0].trim();
-        nameSet.add(name);
+        String interfaceName = strings[0].trim();
 
-        InterfaceUsage interfaceUsage = interfaceUsageMap.computeIfAbsent(name, key -> new InterfaceUsage(id, key));
+        InterfaceUsage interfaceUsage = interfaceUsageMap.computeIfAbsent(interfaceName,
+            key -> new InterfaceUsage(meterRegistry, name, tags, key));
         interfaceUsage.update(strings[1], secondInterval);
       }
-
-      // clear deleted interfaces
-      for (String interfaceName : interfaceUsageMap.keySet()) {
-        if (!nameSet.contains(interfaceName)) {
-          this.interfaceUsageMap.remove(interfaceName);
-        }
-      }
     } catch (IOException e) {
       LOGGER.error("Failed to read net info/", e);
     }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
index 7425e28fc..832773012 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/OsMeter.java
@@ -16,16 +16,12 @@
  */
 package org.apache.servicecomb.metrics.core.meter.os;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 
 import com.google.common.annotations.VisibleForTesting;
 
-import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.MeterRegistry;
-import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Tags;
 
 /**
  * name=os type=cpu value = 0
@@ -35,7 +31,7 @@ import io.micrometer.core.instrument.Tag;
  * name=os type=net interface=eth0 statistic=sendPackets value=100
  * name=os type=net interface=eth0 statistic=receivePackets value=100
  */
-public class OsMeter extends AbstractPeriodMeter {
+public class OsMeter implements PeriodMeter {
   public static final String OS_NAME = "os";
 
   public static final String OS_TYPE = "type";
@@ -51,22 +47,14 @@ public class OsMeter extends AbstractPeriodMeter {
   private final NetMeter netMeter;
 
   public OsMeter(MeterRegistry meterRegistry) {
-    this.id = Id.
-    cpuMeter = new CpuMeter(id);
-    netMeter = new NetMeter(id.withTag(Tag.of(OS_TYPE, OS_TYPE_NET)));
-  }
-
-  @Override
-  public void calcMeasurements(long msNow, long secondInterval) {
-    List<Measurement> measurements = new ArrayList<>();
-    calcMeasurements(measurements, msNow, secondInterval);
-    allMeasurements = measurements;
+    cpuMeter = new CpuMeter(meterRegistry, OS_NAME);
+    netMeter = new NetMeter(meterRegistry, OS_NAME, Tags.of(OS_TYPE, OS_TYPE_NET));
   }
 
   @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    cpuMeter.calcMeasurements(measurements, msNow);
-    netMeter.calcMeasurements(measurements, msNow, secondInterval);
+  public void poll(long msNow, long secondInterval) {
+    cpuMeter.poll(msNow, secondInterval);
+    netMeter.poll(msNow, secondInterval);
   }
 
   @VisibleForTesting
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java
index 8605edeb5..fb2eaa45b 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/AbstractCpuUsage.java
@@ -17,12 +17,7 @@
 package org.apache.servicecomb.metrics.core.meter.os.cpu;
 
 
-import io.micrometer.core.instrument.Meter.Id;
-
 public abstract class AbstractCpuUsage {
-
-  protected Id id;
-
   protected double usage;
 
   protected int cpuCount = Runtime.getRuntime().availableProcessors();
@@ -38,14 +33,6 @@ public abstract class AbstractCpuUsage {
     }
   }
 
-  public AbstractCpuUsage(Id id) {
-    this.id = id;
-  }
-
-  public Id getId() {
-    return id;
-  }
-
   public double getUsage() {
     return usage;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java
index 8b40f212c..09ac5bc7b 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/OsCpuUsage.java
@@ -18,8 +18,6 @@ package org.apache.servicecomb.metrics.core.meter.os.cpu;
 
 import java.io.IOException;
 
-import io.micrometer.core.instrument.Meter.Id;
-
 /*
  * unit : 1 jiffies
  * more details :
@@ -37,8 +35,7 @@ public class OsCpuUsage extends AbstractCpuUsage {
 
   private final Period idle = new Period();
 
-  public OsCpuUsage(Id id) {
-    super(id);
+  public OsCpuUsage() {
   }
 
   public void update() throws IOException {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java
index 6ab7ad828..1e0f55e68 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/cpu/ProcessCpuUsage.java
@@ -18,8 +18,6 @@ package org.apache.servicecomb.metrics.core.meter.os.cpu;
 
 import java.io.IOException;
 
-import io.micrometer.core.instrument.Meter.Id;
-
 /*
  * unit : 1 jiffies
  * more details :
@@ -41,8 +39,7 @@ public class ProcessCpuUsage extends AbstractCpuUsage {
 
   private final int userHZ = CpuUtils.calcHertz();
 
-  public ProcessCpuUsage(Id id) {
-    super(id);
+  public ProcessCpuUsage() {
   }
 
   public void update() throws IOException {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
index a72217894..432975bfa 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
@@ -22,51 +22,49 @@ import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_PACKETS_
 import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_RECEIVE;
 import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_SEND;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import io.micrometer.core.instrument.Measurement;
-import io.micrometer.core.instrument.Meter.Id;
-import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Tags;
 
 public class InterfaceUsage {
-  private final String name;
+  private final String interfaceName;
 
-  private final List<NetStat> netStats = new ArrayList<>();
+  private final NetStat receive;
 
-  public InterfaceUsage(Id id, String name) {
-    this.name = name;
-    id = id.withTag(Tag.of(INTERFACE, name));
-    init(id);
-  }
+  private final NetStat send;
+
+  private final NetStat packetsReceive;
+
+  private final NetStat packetsSend;
+
+  public InterfaceUsage(MeterRegistry meterRegistry, String name, Tags tags, String interfaceName) {
+    this.interfaceName = interfaceName;
+    tags.and(Tag.of(INTERFACE, name));
 
-  private void init(Id id) {
     // recv/Bps
-    netStats.add(new NetStat(id.withTag(TAG_RECEIVE), 0));
+    receive = new NetStat(0);
+    Gauge.builder(name, receive::getRate).tags(tags.and(TAG_RECEIVE, null)).register(meterRegistry);
     // send/Bps
-    netStats.add(new NetStat(id.withTag(TAG_SEND), 8));
-
+    send = new NetStat(8);
+    Gauge.builder(name, send::getRate).tags(tags.and(TAG_SEND, null)).register(meterRegistry);
     // recv/pps
-    netStats.add(new NetStat(id.withTag(TAG_PACKETS_RECEIVE), 1));
+    packetsReceive = new NetStat(1);
+    Gauge.builder(name, packetsReceive::getRate).tags(tags.and(TAG_PACKETS_RECEIVE, null)).register(meterRegistry);
     // send/pps
-    netStats.add(new NetStat(id.withTag(TAG_PACKETS_SEND), 9));
-  }
-
-  public void calcMeasurements(List<Measurement> measurements, long msNow) {
-    netStats.forEach(netStat -> measurements.add(new Measurement(() -> netStat.getRate(), Statistic.VALUE)));
+    packetsSend = new NetStat(9);
+    Gauge.builder(name, packetsSend::getRate).tags(tags.and(TAG_PACKETS_SEND, null)).register(meterRegistry);
   }
 
   public void update(String interfaceData, long secondInterval) {
     String[] netInfo = interfaceData.trim().split("\\s+");
-    netStats.forEach(netStat -> netStat.update(netInfo, secondInterval));
+    receive.update(netInfo, secondInterval);
+    send.update(netInfo, secondInterval);
+    packetsReceive.update(netInfo, secondInterval);
+    packetsSend.update(netInfo, secondInterval);
   }
 
   public String getName() {
-    return name;
-  }
-
-  public List<NetStat> getNetStats() {
-    return netStats;
+    return interfaceName;
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java
index 48b3d9d7d..fac707dce 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/NetStat.java
@@ -17,21 +17,16 @@
 package org.apache.servicecomb.metrics.core.meter.os.net;
 
 
-import io.micrometer.core.instrument.Meter.Id;
-
 public class NetStat {
   private final int index;
 
-  private final Id id;
-
   // send/recv bytes/packets
   private long lastValue;
 
   // Bps/pps
   private double rate;
 
-  public NetStat(Id id, int index) {
-    this.id = id;
+  public NetStat(int index) {
     this.index = index;
   }
 
@@ -56,8 +51,4 @@ public class NetStat {
   public int getIndex() {
     return index;
   }
-
-  public Id getId() {
-    return id;
-  }
 }


(servicecomb-java-chassis) 06/11: [SCB-2838]using micrometer to replace spectator part4: remove spectator and fix UT

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 82d4432434f9facf29e6ce4cb3be2e341fcdeedf
Author: liubao <bi...@qq.com>
AuthorDate: Wed Nov 29 17:53:59 2023 +0800

    [SCB-2838]using micrometer to replace spectator part4: remove spectator and fix UT
---
 .../metrics/meter/LatencyDistributionConfig.java   |   4 +-
 .../metrics/publish/spectator/MeasurementNode.java |   2 +-
 .../metrics/publish/spectator/MeasurementTree.java |  33 +-
 foundations/foundation-test-scaffolding/pom.xml    |   4 +-
 .../metric/DefaultClientEndpointMetricManager.java |  22 --
 .../monitor/MetricsMonitorDataProvider.java        |   3 +-
 .../metrics/core/MetricsBootListener.java          |  11 +-
 .../metrics/core/ThreadPoolMetersInitializer.java  |   2 +-
 .../metrics/core/VertxMetersInitializer.java       |  17 +-
 .../ThreadPoolMonitorPublishModelFactory.java      |   2 +-
 .../meter/invocation/AbstractInvocationMeter.java  |  11 +-
 .../meter/invocation/MeterInvocationConst.java     |   4 +-
 .../metrics/core/meter/os/CpuMeter.java            |   9 +-
 .../metrics/core/meter/os/NetMeter.java            |   1 +
 .../metrics/core/meter/os/net/InterfaceUsage.java  |  30 +-
 .../metrics/core/meter/vertx/EndpointMeter.java    | 101 +++--
 .../core/meter/vertx/HttpClientEndpointMeter.java  |  13 +-
 .../core/meter/vertx/HttpClientEndpointsMeter.java |   1 -
 .../core/meter/vertx/ServerEndpointMeter.java      |  20 +-
 .../core/meter/vertx/VertxEndpointsMeter.java      |  15 +-
 .../metrics/core/publish/DefaultLogPublisher.java  |   2 +-
 .../metrics/core/publish/PublishModelFactory.java  |  11 +-
 .../metrics/core/publish/PublishUtils.java         |  10 +-
 .../servicecomb/metrics/core/AssertUtil.java       |  12 +-
 .../core/TestInvocationMetersInitializer.java      | 419 +++++++++++++--------
 .../metrics/core/TestOsMeterInitializer.java       |  42 +--
 .../core/TestThreadPoolMetersInitializer.java      |  60 ++-
 .../metrics/core/TestVertxMetersInitializer.java   |  42 +--
 .../metrics/core/meter/os/TestCpuMeter.java        |  42 ++-
 .../metrics/core/meter/os/TestNetMeter.java        | 214 ++++++-----
 .../metrics/core/meter/os/TestOsMeter.java         |  31 +-
 .../core/publish/TestDefaultLogPublisher.java      |  44 ++-
 .../publish/TestInvocationPublishModelFactory.java | 388 ++++++++++---------
 .../metrics/core/publish/TestPublishUtils.java     |   2 +-
 .../publish/TestThreadPoolPublishModelFactory.java |  28 +-
 .../core/publish/model/invocation/Utils.java       |  43 +--
 .../prometheus/TestPrometheusPublisher.java        |  23 +-
 .../basic/integration/MetricsEndpointImpl.java     |  16 +-
 .../basic/integration/TestMetricsEndpointImpl.java |  49 +--
 39 files changed, 989 insertions(+), 794 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java
index 2a341cfa1..d46469702 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java
@@ -24,6 +24,8 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class LatencyDistributionConfig {
+  public static final Long MAX_LATENCY = 60 * 60 * 1000L;
+
   private static final Logger LOGGER = LoggerFactory.getLogger(LatencyDistributionConfig.class);
 
   private final List<LatencyScopeConfig> scopeConfigs = new ArrayList<>();
@@ -36,7 +38,7 @@ public class LatencyDistributionConfig {
     if (StringUtils.isEmpty(config)) {
       return;
     }
-    config = config.trim() + "," + Long.MAX_VALUE;
+    config = config.trim() + "," + MAX_LATENCY;
     String[] array = config.split("\\s*,+\\s*");
     try {
       for (int idx = 0; idx < array.length - 1; idx++) {
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
index 6cace285b..b357f758e 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
@@ -40,7 +40,7 @@ public class MeasurementNode implements Comparable<MeasurementNode> {
   }
 
   public String getName() {
-    return id.getName();
+    return this.name;
   }
 
   public Id getId() {
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
index a165ca935..c372a3304 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
@@ -16,17 +16,26 @@
  */
 package org.apache.servicecomb.foundation.metrics.publish.spectator;
 
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
 import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Statistic;
 import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Timer;
+import io.micrometer.core.instrument.distribution.CountAtBucket;
+import io.micrometer.core.instrument.distribution.HistogramSnapshot;
 
 // like select * from meters group by ......
 // but output a tree not a table
 public class MeasurementTree extends MeasurementNode {
+  public static final String TAG_LATENCY_DISTRIBUTION = "latencyDistribution";
+
+  public static final String TAG_TYPE = "type";
+
   public MeasurementTree() {
     super(null, null, null);
   }
@@ -39,12 +48,32 @@ public class MeasurementTree extends MeasurementNode {
     meters.forEachRemaining(meter -> {
       Iterable<Measurement> measurements = meter.measure();
       from(meter.getId(), measurements, groupConfig);
+
+      // This code snip is not very good design. But timer is quite special.
+      if (meter instanceof Timer) {
+        HistogramSnapshot snapshot = ((Timer) meter).takeSnapshot();
+        CountAtBucket[] countAtBuckets = snapshot.histogramCounts();
+        if (countAtBuckets.length > 2) {
+          List<Measurement> latency = new ArrayList<>(countAtBuckets.length);
+          for (int i = 0; i < countAtBuckets.length; i++) {
+            final int index = i;
+            if (index == 0) {
+              latency.add(new Measurement(() -> countAtBuckets[index].count(),
+                  Statistic.VALUE));
+              continue;
+            }
+            latency.add(new Measurement(() -> countAtBuckets[index].count() - countAtBuckets[index - 1].count(),
+                Statistic.VALUE));
+          }
+          from(meter.getId().withTag(Tag.of(TAG_TYPE, TAG_LATENCY_DISTRIBUTION)), latency, groupConfig);
+        }
+      }
     });
   }
 
   public void from(Id id, Iterable<Measurement> measurements, MeasurementGroupConfig groupConfig) {
     for (Measurement measurement : measurements) {
-      MeasurementNode node = addChild(id.getName(), id, null);
+      MeasurementNode node = addChild(id.getName(), id, measurement);
 
       List<TagFinder> tagFinders = groupConfig.findTagFinders(id.getName());
       if (tagFinders == null) {
@@ -63,7 +92,7 @@ public class MeasurementTree extends MeasurementNode {
                   id));
         }
 
-        node = node.addChild(tag.getValue(), id, null);
+        node = node.addChild(tag.getValue(), id, measurement);
       }
 
       node.addChild(measurement.getStatistic().name(), id, measurement);
diff --git a/foundations/foundation-test-scaffolding/pom.xml b/foundations/foundation-test-scaffolding/pom.xml
index a149ef9de..b3cc9f897 100644
--- a/foundations/foundation-test-scaffolding/pom.xml
+++ b/foundations/foundation-test-scaffolding/pom.xml
@@ -41,8 +41,8 @@
       <scope>provided</scope>
     </dependency>
     <dependency>
-      <groupId>com.netflix.spectator</groupId>
-      <artifactId>spectator-reg-servo</artifactId>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java
index a6ece5cac..17977a468 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java
@@ -16,8 +16,6 @@
  */
 package org.apache.servicecomb.foundation.vertx.metrics.metric;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -30,10 +28,6 @@ import com.google.common.annotations.VisibleForTesting;
 import io.vertx.core.Vertx;
 
 public class DefaultClientEndpointMetricManager {
-  public interface ChangeListener {
-    void endpointsChanged();
-  }
-
   private final MetricsOptionsEx metricsOptionsEx;
 
   // to avoid save too many endpoint that not exist any more
@@ -49,22 +43,15 @@ public class DefaultClientEndpointMetricManager {
   // so must lock the logic
   private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
 
-  private final List<ChangeListener> changeListeners = new ArrayList<>();
-
   public DefaultClientEndpointMetricManager(MetricsOptionsEx metricsOptionsEx) {
     this.metricsOptionsEx = metricsOptionsEx;
   }
 
-  public void addChangeListener(ChangeListener listener) {
-    this.changeListeners.add(listener);
-  }
-
   public DefaultClientEndpointMetric getOrCreateEndpointMetric(String address) {
     rwlock.readLock().lock();
     try {
       if (clientEndpointMetricMap.get(address) == null) {
         clientEndpointMetricMap.put(address, new DefaultClientEndpointMetric(address));
-        onChanged();
       }
       return clientEndpointMetricMap.get(address);
     } finally {
@@ -83,31 +70,22 @@ public class DefaultClientEndpointMetricManager {
 
   @VisibleForTesting
   public void onCheckClientEndpointMetricExpired(long periodic) {
-    boolean changed = false;
     for (DefaultClientEndpointMetric metric : clientEndpointMetricMap.values()) {
       if (metric.isExpired(metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano())) {
         rwlock.writeLock().lock();
         try {
           if (metric.isExpired(metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano())) {
             clientEndpointMetricMap.remove(metric.getAddress());
-            changed = true;
           }
         } finally {
           rwlock.writeLock().unlock();
         }
       }
     }
-    if (changed) {
-      onChanged();
-    }
   }
 
   public void setVertx(Vertx vertx) {
     vertx.setPeriodic(metricsOptionsEx.getCheckClientEndpointMetricIntervalInMilliseconds(),
         this::onCheckClientEndpointMetricExpired);
   }
-
-  private void onChanged() {
-    this.changeListeners.forEach(ChangeListener::endpointsChanged);
-  }
 }
diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java
index b56c5c2a2..4829fb22a 100644
--- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java
+++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java
@@ -38,7 +38,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.Subscribe;
-import com.netflix.spectator.api.Meter;
+
+import io.micrometer.core.instrument.Meter;
 
 /**
  * Monitor data based on metrics-core module.
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java
index 540b10ed9..eb9e43475 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsBootListener.java
@@ -19,15 +19,10 @@ package org.apache.servicecomb.metrics.core;
 import org.apache.servicecomb.core.BootListener;
 import org.apache.servicecomb.foundation.common.event.EventManager;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrap;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 
 public class MetricsBootListener implements BootListener {
   private final MetricsBootstrap metricsBootstrap;
 
-  public MetricsBootstrap getMetricsBootstrap() {
-    return metricsBootstrap;
-  }
-
   public MetricsBootListener(MetricsBootstrap metricsBootstrap) {
     this.metricsBootstrap = metricsBootstrap;
   }
@@ -37,9 +32,13 @@ public class MetricsBootListener implements BootListener {
 
   }
 
+  public MetricsBootstrap getMetricsBootstrap() {
+    return metricsBootstrap;
+  }
+
   @Override
   public void onAfterRegistry(BootEvent event) {
-    metricsBootstrap.start(new GlobalRegistry(), EventManager.getEventBus());
+    metricsBootstrap.start(EventManager.getEventBus());
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
index ebe0c019a..a2a307b4a 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
@@ -101,7 +101,7 @@ public class ThreadPoolMetersInitializer implements MetricsInitializer {
     }
   }
 
-  protected void createThreadPoolMeters(String threadPoolName, Executor executor) {
+  public void createThreadPoolMeters(String threadPoolName, Executor executor) {
     if (!(executor instanceof ThreadPoolExecutor threadPoolExecutor)) {
       return;
     }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
index dbc093ab1..8240fabd4 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
@@ -18,6 +18,7 @@ package org.apache.servicecomb.metrics.core;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.foundation.vertx.SharedVertxFactory;
 import org.apache.servicecomb.metrics.core.meter.vertx.HttpClientEndpointsMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.ServerEndpointsMeter;
@@ -27,7 +28,7 @@ import com.google.common.eventbus.EventBus;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tags;
 
-public class VertxMetersInitializer implements MetricsInitializer {
+public class VertxMetersInitializer implements MetricsInitializer, PeriodMeter {
   public static final String VERTX_ENDPOINTS = "servicecomb.vertx.endpoints";
 
   public static final String ENDPOINTS_TYPE = "type";
@@ -36,18 +37,28 @@ public class VertxMetersInitializer implements MetricsInitializer {
 
   public static final String ENDPOINTS_SERVER = "server";
 
+  private HttpClientEndpointsMeter httpClientEndpointsMeter;
+
+  private ServerEndpointsMeter serverEndpointsMeter;
+
   @Override
   public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    new HttpClientEndpointsMeter(meterRegistry, VERTX_ENDPOINTS,
+    httpClientEndpointsMeter = new HttpClientEndpointsMeter(meterRegistry, VERTX_ENDPOINTS,
         Tags.of(ENDPOINTS_TYPE, ENDPOINTS_CLIENT),
         SharedVertxFactory.getMetricsFactory(config.getEnvironment())
             .getVertxMetrics()
             .getClientEndpointMetricManager());
 
-    new ServerEndpointsMeter(meterRegistry, VERTX_ENDPOINTS,
+    serverEndpointsMeter = new ServerEndpointsMeter(meterRegistry, VERTX_ENDPOINTS,
         Tags.of(ENDPOINTS_TYPE, ENDPOINTS_SERVER),
         SharedVertxFactory.getMetricsFactory(config.getEnvironment())
             .getVertxMetrics()
             .getServerEndpointMetricMap());
   }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    httpClientEndpointsMeter.poll(msNow, secondInterval);
+    serverEndpointsMeter.poll(msNow, secondInterval);
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
similarity index 98%
rename from metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java
rename to metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
index c631defb7..d6b7fb7bf 100644
--- a/metrics/metrics-core/src/main/java/com/netflix/spectator/api/patterns/ThreadPoolMonitorPublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.netflix.spectator.api.patterns;
+package org.apache.servicecomb.metrics.core.meter;
 
 import java.util.Map;
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index 34ef22121..bf7bb0429 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
+import org.apache.servicecomb.foundation.metrics.meter.LatencyDistributionConfig;
 
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tags;
@@ -53,7 +54,7 @@ public abstract class AbstractInvocationMeter {
   }
 
   protected static Duration[] toDuration(String config) {
-    config = config.trim() + "," + Long.MAX_VALUE;
+    config = config.trim() + "," + LatencyDistributionConfig.MAX_LATENCY;
     String[] array = config.split("\\s*,+\\s*");
     Duration[] result = new Duration[array.length];
 
@@ -67,7 +68,13 @@ public abstract class AbstractInvocationMeter {
 
       result[idx] = Duration.ofMillis(msMin);
     }
-    result[array.length - 1] = Duration.ofMillis(Long.MAX_VALUE);
+    result[array.length - 1] = Duration.ofMillis(LatencyDistributionConfig.MAX_LATENCY);
+
+    if (result[0].toMillis() == 0) {
+      Duration[] target = new Duration[result.length - 1];
+      System.arraycopy(result, 1, target, 0, target.length);
+      return target;
+    }
 
     return result;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
index ab0ab0b34..fd5d53f9e 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
@@ -16,7 +16,7 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import com.netflix.spectator.api.Statistic;
+import io.micrometer.core.instrument.Statistic;
 
 public interface MeterInvocationConst {
   String INVOCATION_NAME = "servicecomb.invocation";
@@ -36,7 +36,7 @@ public interface MeterInvocationConst {
 
   String TAG_STATUS = "status";
 
-  String TAG_STATISTIC = Statistic.count.key();
+  String TAG_STATISTIC = Statistic.COUNT.name();
 
   String EDGE_INVOCATION_NAME = "EDGE";
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
index f7d7f83b2..388a24d61 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/CpuMeter.java
@@ -16,8 +16,6 @@
  */
 package org.apache.servicecomb.metrics.core.meter.os;
 
-import java.io.IOException;
-
 import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.OsCpuUsage;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.ProcessCpuUsage;
@@ -48,6 +46,11 @@ public class CpuMeter implements PeriodMeter {
 
     Gauge.builder(name, processCpuUsage::getUsage).tags(Tags.of(OsMeter.OS_TYPE, OsMeter.OS_TYPE_PROCESS_CPU))
         .register(meterRegistry);
+
+    // read initial data, and cannot calculate usage, set to 0 first.
+    poll(0, 0);
+    allCpuUsage.setUsage(0);
+    processCpuUsage.setUsage(0);
   }
 
   @Override
@@ -55,7 +58,7 @@ public class CpuMeter implements PeriodMeter {
     try {
       allCpuUsage.update();
       processCpuUsage.update();
-    } catch (IOException e) {
+    } catch (Throwable e) {
       LOGGER.error("Failed to update cpu usage", e);
     }
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
index 28427801b..9cdf72318 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/NetMeter.java
@@ -61,6 +61,7 @@ public class NetMeter implements PeriodMeter {
     this.meterRegistry = meterRegistry;
     this.name = name;
     this.tags = tags;
+    poll(0, 0);
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
index 432975bfa..b33d30d8c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/os/net/InterfaceUsage.java
@@ -22,6 +22,8 @@ import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_PACKETS_
 import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_RECEIVE;
 import static org.apache.servicecomb.metrics.core.meter.os.NetMeter.TAG_SEND;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import io.micrometer.core.instrument.Gauge;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
@@ -44,16 +46,16 @@ public class InterfaceUsage {
 
     // recv/Bps
     receive = new NetStat(0);
-    Gauge.builder(name, receive::getRate).tags(tags.and(TAG_RECEIVE, null)).register(meterRegistry);
+    Gauge.builder(name, receive::getRate).tags(tags.and(TAG_RECEIVE)).register(meterRegistry);
     // send/Bps
     send = new NetStat(8);
-    Gauge.builder(name, send::getRate).tags(tags.and(TAG_SEND, null)).register(meterRegistry);
+    Gauge.builder(name, send::getRate).tags(tags.and(TAG_SEND)).register(meterRegistry);
     // recv/pps
     packetsReceive = new NetStat(1);
-    Gauge.builder(name, packetsReceive::getRate).tags(tags.and(TAG_PACKETS_RECEIVE, null)).register(meterRegistry);
+    Gauge.builder(name, packetsReceive::getRate).tags(tags.and(TAG_PACKETS_RECEIVE)).register(meterRegistry);
     // send/pps
     packetsSend = new NetStat(9);
-    Gauge.builder(name, packetsSend::getRate).tags(tags.and(TAG_PACKETS_SEND, null)).register(meterRegistry);
+    Gauge.builder(name, packetsSend::getRate).tags(tags.and(TAG_PACKETS_SEND)).register(meterRegistry);
   }
 
   public void update(String interfaceData, long secondInterval) {
@@ -64,6 +66,26 @@ public class InterfaceUsage {
     packetsSend.update(netInfo, secondInterval);
   }
 
+  @VisibleForTesting
+  public NetStat getReceive() {
+    return receive;
+  }
+
+  @VisibleForTesting
+  public NetStat getSend() {
+    return send;
+  }
+
+  @VisibleForTesting
+  public NetStat getPacketsReceive() {
+    return packetsReceive;
+  }
+
+  @VisibleForTesting
+  public NetStat getPacketsSend() {
+    return packetsSend;
+  }
+
   public String getName() {
     return interfaceName;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
index 3624ef441..f00cf22e0 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
@@ -18,6 +18,7 @@ package org.apache.servicecomb.metrics.core.meter.vertx;
 
 import java.util.concurrent.TimeUnit;
 
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
 import io.micrometer.core.instrument.Gauge;
@@ -25,7 +26,7 @@ import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
 import io.micrometer.core.instrument.Tags;
 
-public class EndpointMeter {
+public class EndpointMeter implements PeriodMeter {
   private static final double SNV_MILLI_SECONDS = 1.0 / TimeUnit.MILLISECONDS.toNanos(1L);
 
   public static final String ADDRESS = "address";
@@ -64,72 +65,60 @@ public class EndpointMeter {
 
   private final Gauge latency;
 
+  private long currentConnectCount;
+
   private long lastConnectCount;
 
+  private long currentDisconnectCount;
+
   private long lastDisconnectCount;
 
+  private long currentBytesRead;
+
   private long lastBytesRead;
 
+  private long currentBytesWritten;
+
   private long lastBytesWritten;
 
+  private long currentRequests;
+
   private long lastRequests;
 
+  private long currentRequestsForLatency;
+
   private long lastRequestsForLatency;
 
+  private long currentLatency;
+
   private long lastLatency;
 
   public EndpointMeter(MeterRegistry meterRegistry, String name, Tags tags, DefaultEndpointMetric metric) {
     this.meterRegistry = meterRegistry;
+    this.metric = metric;
 
     tags = tags.and(Tag.of(ADDRESS, metric.getAddress()));
-    connectCount = Gauge.builder(name, () -> {
-          long current = metric.getConnectCount();
-          long result = current - lastConnectCount;
-          lastConnectCount = current;
-          return result;
-        })
+    connectCount = Gauge.builder(name, () -> currentConnectCount)
         .tags(tags.and(Tag.of(STATISTIC, CONNECT_COUNT)))
         .register(meterRegistry);
-    disconnectCount = Gauge.builder(name, () -> {
-          long current = metric.getDisconnectCount();
-          long result = current - lastDisconnectCount;
-          lastDisconnectCount = current;
-          return result;
-        }).tags(tags.and(Tag.of(STATISTIC, DISCONNECT_COUNT)))
+    disconnectCount = Gauge.builder(name, () -> currentDisconnectCount)
+        .tags(tags.and(Tag.of(STATISTIC, DISCONNECT_COUNT)))
         .register(meterRegistry);
-    connections = Gauge.builder(name, () -> metric.getConnectCount() - metric.getDisconnectCount())
+    connections = Gauge.builder(name, () -> currentConnectCount - currentDisconnectCount)
         .tags(tags.and(Tag.of(STATISTIC, CONNECTIONS)))
         .register(meterRegistry);
-    bytesRead = Gauge.builder(name, () -> {
-          long current = metric.getBytesRead();
-          long result = current - lastBytesRead;
-          lastBytesRead = current;
-          return result;
-        }).tags(tags.and(Tag.of(STATISTIC, BYTES_READ)))
+    bytesRead = Gauge.builder(name, () -> currentBytesRead)
+        .tags(tags.and(Tag.of(STATISTIC, BYTES_READ)))
         .register(meterRegistry);
-    bytesWritten = Gauge.builder(name, () -> {
-          long current = metric.getBytesWritten();
-          long result = current - lastBytesWritten;
-          lastBytesWritten = current;
-          return result;
-        }).tags(tags.and(Tag.of(STATISTIC, BYTES_WRITTEN)))
+    bytesWritten = Gauge.builder(name, () -> currentBytesWritten)
+        .tags(tags.and(Tag.of(STATISTIC, BYTES_WRITTEN)))
         .register(meterRegistry);
-    requests = Gauge.builder(name, () -> {
-          long current = metric.getRequests();
-          long result = current - lastRequests;
-          lastRequests = current;
-          return result;
-        }).tags(tags.and(Tag.of(STATISTIC, REQUESTS)))
+    requests = Gauge.builder(name, () -> currentRequests)
+        .tags(tags.and(Tag.of(STATISTIC, REQUESTS)))
         .register(meterRegistry);
-    latency = Gauge.builder(name, () -> {
-          long currentLatency = metric.getLatency();
-          long currentRequests = metric.getRequests();
-          double result = currentRequests - lastRequestsForLatency == 0 ? 0 :
-              (currentLatency - lastLatency) / ((double) (currentRequests - lastRequestsForLatency)) * SNV_MILLI_SECONDS;
-          lastRequestsForLatency = currentRequests;
-          lastLatency = currentLatency;
-          return result;
-        }).tags(tags.and(Tag.of(STATISTIC, LATENCY)))
+    latency = Gauge.builder(name, () -> currentRequestsForLatency == 0 ? 0 :
+            (currentLatency) / ((double) (currentRequestsForLatency)) * SNV_MILLI_SECONDS)
+        .tags(tags.and(Tag.of(STATISTIC, LATENCY)))
         .register(meterRegistry);
   }
 
@@ -146,4 +135,34 @@ public class EndpointMeter {
     this.meterRegistry.remove(requests);
     this.meterRegistry.remove(latency);
   }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    long temp = metric.getConnectCount();
+    currentConnectCount = temp - lastConnectCount;
+    lastConnectCount = temp;
+
+    temp = metric.getDisconnectCount();
+    currentDisconnectCount = temp - lastDisconnectCount;
+    lastDisconnectCount = temp;
+
+    temp = metric.getBytesRead();
+    currentBytesRead = temp - lastBytesRead;
+    lastBytesRead = temp;
+
+    temp = metric.getBytesWritten();
+    currentBytesWritten = temp - lastBytesWritten;
+    lastBytesWritten = temp;
+
+    temp = metric.getRequests();
+    currentRequests = temp - lastRequests;
+    lastRequests = temp;
+
+    temp = metric.getRequests();
+    currentRequestsForLatency = temp - lastRequestsForLatency;
+    lastRequestsForLatency = temp;
+    temp = metric.getLatency();
+    currentLatency = temp - lastLatency;
+    lastLatency = temp;
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java
index a80f4643e..ad3143de3 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java
@@ -27,10 +27,19 @@ import io.micrometer.core.instrument.Tags;
 public class HttpClientEndpointMeter extends EndpointMeter {
   public static final String QUEUE_COUNT = "queueCount";
 
+  private long currentQueueCount;
+
   public HttpClientEndpointMeter(MeterRegistry meterRegistry, String name, Tags tags, DefaultEndpointMetric metric) {
     super(meterRegistry, name, tags, metric);
-    Gauge.builder(name, () -> ((DefaultClientEndpointMetric) metric).getQueueCount())
-        .tags(tags.and(Tag.of(STATISTIC, QUEUE_COUNT)))
+    Gauge.builder(name, () -> currentQueueCount)
+        .tags(tags.and(Tag.of(STATISTIC, QUEUE_COUNT), Tag.of(ADDRESS, metric.getAddress())))
         .register(meterRegistry);
   }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    super.poll(msNow, secondInterval);
+
+    currentQueueCount = ((DefaultClientEndpointMetric) metric).getQueueCount();
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
index 78169f6af..f68f8413c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
@@ -26,7 +26,6 @@ public class HttpClientEndpointsMeter extends VertxEndpointsMeter {
   public <T extends DefaultEndpointMetric> HttpClientEndpointsMeter(MeterRegistry meterRegistry, String name, Tags tags,
       DefaultClientEndpointMetricManager clientEndpointMetricManager) {
     super(meterRegistry, name, tags, clientEndpointMetricManager.getClientEndpointMetricMap());
-    clientEndpointMetricManager.addChangeListener(this::onChanged);
   }
 
   @Override
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java
index 2e8c6d2fb..aa16f3eed 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java
@@ -29,15 +29,21 @@ public class ServerEndpointMeter extends EndpointMeter {
 
   private long lastRejectByConnectionLimit;
 
+  private long currentRejectByConnectionLimit;
+
   public ServerEndpointMeter(MeterRegistry meterRegistry, String name, Tags tags, DefaultEndpointMetric metric) {
     super(meterRegistry, name, tags, metric);
-    Gauge.builder(name, () -> {
-          long current = ((DefaultServerEndpointMetric) metric).getRejectByConnectionLimitCount();
-          long result = current - lastRejectByConnectionLimit;
-          lastRejectByConnectionLimit = current;
-          return result;
-        })
-        .tags(tags.and(Tag.of(STATISTIC, REJECT_BY_CONNECTION_LIMIT)))
+    Gauge.builder(name, () -> currentRejectByConnectionLimit)
+        .tags(tags.and(Tag.of(STATISTIC, REJECT_BY_CONNECTION_LIMIT), Tag.of(ADDRESS, metric.getAddress())))
         .register(meterRegistry);
   }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    super.poll(msNow, secondInterval);
+
+    long current = ((DefaultServerEndpointMetric) metric).getRejectByConnectionLimitCount();
+    currentRejectByConnectionLimit = current - lastRejectByConnectionLimit;
+    lastRejectByConnectionLimit = current;
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
index 829f17746..fd4d10f0d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
@@ -19,12 +19,13 @@ package org.apache.servicecomb.metrics.core.meter.vertx;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tags;
 
-public class VertxEndpointsMeter {
+public class VertxEndpointsMeter implements PeriodMeter {
   private final Map<String, DefaultEndpointMetric> endpointMetricMap;
 
   protected final MeterRegistry meterRegistry;
@@ -42,10 +43,9 @@ public class VertxEndpointsMeter {
     this.name = name;
     this.tags = tags;
     this.endpointMetricMap = (Map<String, DefaultEndpointMetric>) endpointMetricMap;
-    syncMeters();
   }
 
-  private void syncMeters() {
+  private void syncMeters(long msNow, long secondInterval) {
     for (EndpointMeter meter : endpointMeterMap.values()) {
       if (!endpointMetricMap.containsKey(meter.getMetric().getAddress())) {
         EndpointMeter removed = endpointMeterMap.remove(meter.getMetric().getAddress());
@@ -53,7 +53,9 @@ public class VertxEndpointsMeter {
       }
     }
     for (DefaultEndpointMetric metric : endpointMetricMap.values()) {
-      endpointMeterMap.computeIfAbsent(metric.getAddress(), address -> createEndpointMeter(metric));
+      EndpointMeter updated = endpointMeterMap.computeIfAbsent(metric.getAddress(),
+          address -> createEndpointMeter(metric));
+      updated.poll(msNow, secondInterval);
     }
   }
 
@@ -61,7 +63,8 @@ public class VertxEndpointsMeter {
     return new EndpointMeter(meterRegistry, name, tags, metric);
   }
 
-  protected void onChanged() {
-    syncMeters();
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    syncMeters(msNow, secondInterval);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index 48e0d047d..4d7ae9954 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -119,7 +119,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
     latencyDistributionConfig = new LatencyDistributionConfig(config.getLatencyDistribution());
     String header;
     for (LatencyScopeConfig scopeConfig : latencyDistributionConfig.getScopeConfigs()) {
-      if (scopeConfig.getMsMax() == Long.MAX_VALUE) {
+      if (scopeConfig.getMsMax() == LatencyDistributionConfig.MAX_LATENCY) {
         header = String.format("[%d,) ", scopeConfig.getMsMin());
       } else {
         header = String.format("[%d,%d) ", scopeConfig.getMsMin(), scopeConfig.getMsMax());
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
index 68aaad35c..6554fc936 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
@@ -31,7 +31,7 @@ import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 
-import com.netflix.spectator.api.patterns.ThreadPoolMonitorPublishModelFactory;
+import org.apache.servicecomb.metrics.core.meter.ThreadPoolMonitorPublishModelFactory;
 
 import io.micrometer.core.instrument.Meter;
 
@@ -62,19 +62,16 @@ public class PublishModelFactory {
         MeterInvocationConst.TAG_OPERATION,
         MeterInvocationConst.TAG_STATUS,
         MeterInvocationConst.TAG_TYPE,
-        new DefaultTagFinder(MeterInvocationConst.TAG_STAGE, true),
-        MeterInvocationConst.TAG_STATISTIC);
+        new DefaultTagFinder(MeterInvocationConst.TAG_STAGE, true));
 
     //os config
     groupConfig.addGroup(OsMeter.OS_NAME,
         OsMeter.OS_TYPE,
-        new DefaultTagFinder(NetMeter.INTERFACE, true),
-        NetMeter.STATISTIC);
+        new DefaultTagFinder(NetMeter.INTERFACE, true));
 
     groupConfig.addGroup(VertxMetersInitializer.VERTX_ENDPOINTS,
         VertxMetersInitializer.ENDPOINTS_TYPE,
-        EndpointMeter.ADDRESS,
-        EndpointMeter.STATISTIC);
+        EndpointMeter.ADDRESS, EndpointMeter.STATISTIC);
 
     return groupConfig;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
index 3196120d7..94b9c43ab 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
@@ -26,7 +26,7 @@ import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPer
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.PerfInfo;
 
-import com.netflix.spectator.api.Statistic;
+import io.micrometer.core.instrument.Statistic;
 
 public final class PublishUtils {
   private PublishUtils() {
@@ -34,10 +34,10 @@ public final class PublishUtils {
 
   public static PerfInfo createPerfInfo(MeasurementNode stageNode) {
     PerfInfo perfInfo = new PerfInfo();
-    perfInfo.setTps(stageNode.findChild(Statistic.count.name()).summary());
-    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.totalTime.name()).summary() * 1000);
+    perfInfo.setTps(stageNode.findChild(Statistic.COUNT.name()).summary());
+    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.TOTAL_TIME.name()).summary() * 1000);
     // when UT with DefaultRegistry, there is no max value
-    MeasurementNode maxNode = stageNode.findChild(Statistic.max.name());
+    MeasurementNode maxNode = stageNode.findChild(Statistic.MAX.name());
     if (maxNode != null) {
       perfInfo.setMsMaxLatency(maxNode.summary() * 1000);
     }
@@ -57,7 +57,7 @@ public final class PublishUtils {
     MeasurementNode latencyNode = statusNode.findChild(MeterInvocationConst.TAG_LATENCY_DISTRIBUTION);
     if (latencyNode != null && latencyNode.getMeasurements() != null) {
       operationPerf.setLatencyDistribution(latencyNode.getMeasurements().stream()
-          .map(m -> (int) m.value())
+          .map(m -> (int) m.getValue())
           .toArray(Integer[]::new));
     }
     return operationPerf;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/AssertUtil.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/AssertUtil.java
index f89216299..f154ba654 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/AssertUtil.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/AssertUtil.java
@@ -16,15 +16,15 @@
  */
 package org.apache.servicecomb.metrics.core;
 
-import com.netflix.spectator.api.Measurement;
+import java.util.List;
+
 import org.junit.jupiter.api.Assertions;
 
-import java.util.List;
+import io.micrometer.core.instrument.Measurement;
 
 public class AssertUtil {
 
-    public static void assertMeasure(List<Measurement> measurements, int index, String expected) {
-        Assertions.assertEquals(String.format("Measurement(%s)", expected), measurements.get(index).toString());
-    }
-
+  public static void assertMeasure(List<Measurement> measurements, int index, String expected) {
+    Assertions.assertEquals(String.format("Measurement{%s}", expected), measurements.get(index).toString());
+  }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
index c25487746..16f9b67ad 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
@@ -38,20 +38,19 @@ import org.mockito.Mockito;
 import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Registry;
 
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Expectations;
 import mockit.Mocked;
 
 public class TestInvocationMetersInitializer {
   EventBus eventBus = new EventBus();
 
-  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
+  MeterRegistry registry = new SimpleMeterRegistry();
 
-  Registry registry = new DefaultRegistry(globalRegistry.getClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry(registry);
 
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
 
@@ -67,8 +66,7 @@ public class TestInvocationMetersInitializer {
     Mockito.when(environment.getProperty(
             CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
         .thenReturn(7);
-    globalRegistry.add(registry);
-    invocationMetersInitializer.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
+    invocationMetersInitializer.init(registry, eventBus, new MetricsBootstrapConfig(environment));
   }
 
   @Test
@@ -109,51 +107,88 @@ public class TestInvocationMetersInitializer {
     globalRegistry.poll(1);
 
     MeasurementTree tree = new MeasurementTree();
-    tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    List<Measurement> measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements();
-    Assert.assertEquals(21, measurements.size());
+    tree.from(registry.getMeters().iterator(),
+        new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME, "stage"));
+    List<Measurement> measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "total")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
     AssertUtil.assertMeasure(measurements, 0,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=count:status=0:transport=rest:type=stage,0,2.0");
+        "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
+        "statistic='TOTAL_TIME', value=1.8E-8");
     AssertUtil.assertMeasure(measurements, 2,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=total:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, 3,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, 4,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, 5,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=prepare:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, 6,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-send:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, 7,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-send:statistic=totalTime:status=0:transport=rest:type=stage,0,1.0E-8");
-    AssertUtil.assertMeasure(measurements, 8,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-send:statistic=max:status=0:transport=rest:type=stage,0,5.0E-9");
-    AssertUtil.assertMeasure(measurements, 9,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=connection:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, 10,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=connection:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, 11,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=connection:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, 12,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-encode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, 13,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-encode:statistic=totalTime:status=0:transport=rest:type=stage,0,8.0E-9");
-    AssertUtil.assertMeasure(measurements, 14,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-encode:statistic=max:status=0:transport=rest:type=stage,0,4.0E-9");
-    AssertUtil.assertMeasure(measurements, 15,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=wait:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, 16,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=wait:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, 17,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=wait:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, 18,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-decode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, 19,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-decode:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, 20,
-        "servicecomb.invocation:operation=m.s.o:role=CONSUMER:stage=consumer-decode:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-send")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.0E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=5.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-encode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=8.0E-9");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=4.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "wait")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-decode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
   }
 
   @Test
@@ -199,70 +234,108 @@ public class TestInvocationMetersInitializer {
     globalRegistry.poll(1);
 
     MeasurementTree tree = new MeasurementTree();
-    tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    List<Measurement> measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements();
-    Assert.assertEquals(30, measurements.size());
-    int i = 0;
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=total:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=prepare:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-send:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-send:statistic=totalTime:status=0:transport=rest:type=stage,0,1.0E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-send:statistic=max:status=0:transport=rest:type=stage,0,5.0E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=connection:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=connection:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=connection:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-encode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-encode:statistic=totalTime:status=0:transport=rest:type=stage,0,8.0E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-encode:statistic=max:status=0:transport=rest:type=stage,0,4.0E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=wait:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=wait:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=wait:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-decode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-decode:statistic=totalTime:status=0:transport=rest:type=stage,0,1.6E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=consumer-decode:statistic=max:status=0:transport=rest:type=stage,0,8.0E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-decode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-decode:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-decode:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-encode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-encode:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-encode:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-send:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-send:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=EDGE:stage=provider-send:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
+    tree.from(registry.getMeters().iterator(),
+        new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME, "stage"));
+
+    List<Measurement> measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "total")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-send")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.0E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=5.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-encode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=8.0E-9");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=4.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "wait")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-decode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.6E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=8.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-decode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-encode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-send")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
   }
 
   @Test
@@ -302,51 +375,77 @@ public class TestInvocationMetersInitializer {
     globalRegistry.poll(1);
 
     MeasurementTree tree = new MeasurementTree();
-    tree.from(registry.iterator(), new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME));
-    List<Measurement> measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME).getMeasurements();
-    Assert.assertEquals(21, measurements.size());
-    int i = 0;
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=total:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=total:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=total:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=prepare:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=prepare:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=prepare:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=queue:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=queue:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=queue:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=execute:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=execute:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=execute:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-decode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-decode:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-decode:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-encode:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-encode:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-encode:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-send:statistic=count:status=0:transport=rest:type=stage,0,2.0");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-send:statistic=totalTime:status=0:transport=rest:type=stage,0,1.8000000000000002E-8");
-    AssertUtil.assertMeasure(measurements, i++,
-        "servicecomb.invocation:operation=m.s.o:role=PROVIDER:stage=provider-send:statistic=max:status=0:transport=rest:type=stage,0,9.000000000000001E-9");
+    tree.from(registry.getMeters().iterator(),
+        new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME, "stage"));
+
+    List<Measurement> measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "total")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "queue")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "execute")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-decode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-encode")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
+
+    measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-send")
+        .getMeasurements();
+    Assert.assertEquals(3, measurements.size());
+    AssertUtil.assertMeasure(measurements, 0,
+        "statistic='COUNT', value=2.0");
+    AssertUtil.assertMeasure(measurements, 1,
+        "statistic='TOTAL_TIME', value=1.8E-8");
+    AssertUtil.assertMeasure(measurements, 2,
+        "statistic='MAX', value=9.0E-9");
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
index 83bc88bc2..a373e21ba 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
@@ -25,30 +25,26 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.meter.os.CpuMeter;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.CpuUtils;
 import org.apache.servicecomb.metrics.core.meter.os.net.InterfaceUsage;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
 
 import com.google.common.eventbus.EventBus;
 import com.google.common.io.Files;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
 
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
-import org.junit.jupiter.api.Assertions;
 
 public class TestOsMeterInitializer {
-  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
-
-  Registry registry = new DefaultRegistry(globalRegistry.getClock());
+  MeterRegistry registry = new SimpleMeterRegistry();
 
   @Mocked
   EventBus eventBus;
@@ -97,10 +93,11 @@ public class TestOsMeterInitializer {
         result = 2;
       }
     };
-    globalRegistry.add(registry);
+
     OsMetersInitializer osMetersInitializer = new OsMetersInitializer();
     osMetersInitializer.setOsLinux(true);
-    osMetersInitializer.init(globalRegistry, eventBus, null);
+    osMetersInitializer.init(registry, eventBus, null);
+    osMetersInitializer.poll(System.currentTimeMillis(), 1000);
     OsMeter osMeter = osMetersInitializer.getOsMeter();
     Assertions.assertNotNull(osMeter);
     Assertions.assertNotNull(osMeter.getCpuMeter());
@@ -114,25 +111,24 @@ public class TestOsMeterInitializer {
     Map<String, InterfaceUsage> interfaceInfoMap = netMeter.getInterfaceUsageMap();
     Assertions.assertEquals(1, interfaceInfoMap.size());
     InterfaceUsage eth0 = interfaceInfoMap.get("eth0");
-    Assertions.assertEquals(4, eth0.getNetStats().size());
     // recv Bps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(0L, eth0.getReceive().getLastValue());
+    Assertions.assertEquals(0, eth0.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, eth0.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, eth0.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(0L, eth0.getSend().getLastValue());
+    Assertions.assertEquals(0, eth0.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, eth0.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(0L, eth0.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(0, eth0.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, eth0.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(0L, eth0.getPacketsSend().getLastValue());
+    Assertions.assertEquals(0, eth0.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, eth0.getPacketsSend().getIndex());
   }
 
   @Test
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
index ea908c88f..dba231e87 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
@@ -16,48 +16,41 @@
  */
 package org.apache.servicecomb.metrics.core;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.RunnableScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadPoolExecutor;
 
 import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.GroupExecutor;
+import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
-import org.hamcrest.MatcherAssert;
-import org.hamcrest.Matchers;
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
 import org.mockito.Mockito;
 import org.springframework.context.ApplicationContext;
 
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.patterns.PolledMeter;
-
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
 
 public class TestThreadPoolMetersInitializer {
-  GlobalRegistry globalRegistry = new GlobalRegistry();
-
-  Registry registry = new DefaultRegistry(new ManualClock());
+  MeterRegistry registry = new SimpleMeterRegistry();
 
   ThreadPoolMetersInitializer threadPoolMetersInitializer = new ThreadPoolMetersInitializer();
 
-  ThreadPoolExecutor threadPoolExecutor = Mockito.mock(ThreadPoolExecutor.class);
+  ThreadPoolExecutorEx threadPoolExecutor = Mockito.mock(ThreadPoolExecutorEx.class);
 
   @Mocked
   BlockingQueue<Runnable> queue;
@@ -130,21 +123,26 @@ public class TestThreadPoolMetersInitializer {
       }
     };
 
-    globalRegistry.add(registry);
-    threadPoolMetersInitializer.init(globalRegistry, null, null);
-
-    PolledMeter.update(registry);
-    List<String> result = new ArrayList<>();
-    registry.iterator().forEachRemaining(meter -> result.add(meter.measure().toString()));
-
-    MatcherAssert.assertThat(result,
-        Matchers.containsInAnyOrder("[Measurement(threadpool.maxThreads:id=groupExecutor-group0,0,0.0)]",
-            "[Measurement(threadpool.rejectedTaskCount:id=groupExecutor-group0,0,0.0)]",
-            "[Measurement(threadpool.completedTaskCount:id=groupExecutor-group0,0,0.0)]",
-            "[Measurement(threadpool.currentThreadsBusy:id=groupExecutor-group0,0,0.0)]",
-            "[Measurement(threadpool.corePoolSize:id=groupExecutor-group0,0,0.0)]",
-            "[Measurement(threadpool.poolSize:id=groupExecutor-group0,0,0.0)]",
-            "[Measurement(threadpool.queueSize:id=groupExecutor-group0,0,10.0)]",
-            "[Measurement(threadpool.taskCount:id=groupExecutor-group0,0,0.0)]"));
+    threadPoolMetersInitializer.init(registry, null, null);
+
+    MeasurementTree tree = new MeasurementTree();
+    MeasurementGroupConfig group = new MeasurementGroupConfig();
+    group.addGroup("threadpool.maxThreads", "id");
+    group.addGroup("threadpool.rejectedCount", "id");
+    group.addGroup("threadpool.completedTaskCount", "id");
+    group.addGroup("threadpool.currentThreadsBusy", "id");
+    group.addGroup("threadpool.corePoolSize", "id");
+    group.addGroup("threadpool.poolSize", "id");
+    group.addGroup("threadpool.queueSize", "id");
+    group.addGroup("threadpool.taskCount", "id");
+    tree.from(registry.getMeters().iterator(), group);
+    Assertions.assertEquals(tree.findChild("threadpool.maxThreads", "groupExecutor-group0").summary(), 0, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.rejectedCount", "groupExecutor-group0").summary(), 0, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.completedTaskCount", "groupExecutor-group0").summary(), 0, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.currentThreadsBusy", "groupExecutor-group0").summary(), 0, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.corePoolSize", "groupExecutor-group0").summary(), 0, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.poolSize", "groupExecutor-group0").summary(), 0, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.queueSize", "groupExecutor-group0").summary(), 10, 0);
+    Assertions.assertEquals(tree.findChild("threadpool.taskCount", "groupExecutor-group0").summary(), 0, 0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java
index 85a91c9f9..fc2c20c8c 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestVertxMetersInitializer.java
@@ -21,13 +21,11 @@ import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.D
 import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.METRICS_WINDOW_TIME;
 import static org.apache.servicecomb.metrics.core.publish.DefaultLogPublisher.ENDPOINTS_CLIENT_DETAIL_ENABLED;
 
-import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.servicecomb.foundation.common.LegacyPropertyFactory;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
 import org.apache.servicecomb.foundation.vertx.SharedVertxFactory;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
@@ -40,14 +38,11 @@ import org.junit.jupiter.api.Assertions;
 import org.mockito.Mockito;
 import org.springframework.core.env.Environment;
 
-import com.google.common.collect.Lists;
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Meter;
-import com.netflix.spectator.api.Registry;
 
+import io.micrometer.core.instrument.Meter;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import io.vertx.core.AbstractVerticle;
 import io.vertx.core.DeploymentOptions;
 import io.vertx.core.Promise;
@@ -59,9 +54,7 @@ import io.vertx.core.http.HttpServer;
 import io.vertx.ext.web.Router;
 
 public class TestVertxMetersInitializer {
-  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
-
-  Registry registry = new DefaultRegistry(globalRegistry.getClock());
+  MeterRegistry registry = new SimpleMeterRegistry();
 
   EventBus eventBus = new EventBus();
 
@@ -135,36 +128,31 @@ public class TestVertxMetersInitializer {
             CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
         .thenReturn(7);
     Mockito.when(environment.getProperty(DefaultLogPublisher.ENABLED, boolean.class, false)).thenReturn(false);
-
-    globalRegistry.add(registry);
-    vertxMetersInitializer.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
-    logPublisher.setEnvironment(environment);
-    logPublisher.init(null, eventBus, null);
     VertxUtils
         .blockDeploy(SharedVertxFactory.getSharedVertx(environment), TestServerVerticle.class, new DeploymentOptions());
     VertxUtils
         .blockDeploy(SharedVertxFactory.getSharedVertx(environment), TestClientVerticle.class, new DeploymentOptions());
 
-    globalRegistry.poll(1);
-    List<Meter> meters = Lists.newArrayList(registry.iterator());
-    List<Measurement> measurements = new ArrayList<>();
-    for (Meter meter : meters) {
-      meter.measure().forEach(measurements::add);
-    }
+    vertxMetersInitializer.init(registry, eventBus, new MetricsBootstrapConfig(environment));
+    logPublisher.setEnvironment(environment);
+    logPublisher.init(registry, eventBus, null);
+
+    vertxMetersInitializer.poll(0, 1);
+    List<Meter> meters = registry.getMeters();
 
     LogCollector logCollector = new LogCollector();
 
-    testLog(logCollector, meters, measurements, true);
+    testLog(logCollector, meters, true);
     logCollector.clear();
-    testLog(logCollector, meters, measurements, false);
+
+    testLog(logCollector, meters, false);
 
     logCollector.teardown();
   }
 
-  private void testLog(LogCollector logCollector, List<Meter> meters, List<Measurement> measurements,
-      boolean printDetail) {
+  private void testLog(LogCollector logCollector, List<Meter> meters, boolean printDetail) {
     Mockito.when(environment.getProperty(ENDPOINTS_CLIENT_DETAIL_ENABLED, boolean.class, true)).thenReturn(printDetail);
-    logPublisher.onPolledEvent(new PolledEvent(meters, measurements));
+    logPublisher.onPolledEvent(new PolledEvent(meters));
 
     StringBuilder sb = new StringBuilder();
     logCollector.getEvents().forEach(event -> sb.append(event.getMessage()).append("\n"));
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestCpuMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestCpuMeter.java
index 8295bdcee..872dbe1fe 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestCpuMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestCpuMeter.java
@@ -26,22 +26,23 @@ import java.util.List;
 
 import org.apache.servicecomb.metrics.core.meter.os.cpu.CpuUtils;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
 
 import com.google.common.io.CharSource;
 import com.google.common.io.Files;
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
 
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
-import org.junit.jupiter.api.Assertions;
 
 public class TestCpuMeter {
 
   @Test
-  public void testRefreshCpuSuccess(@Mocked Id id, @Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
+  public void testRefreshCpuSuccess(@Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
       @Mocked CharSource charSource) throws IOException {
     new MockUp<Files>() {
       @Mock
@@ -75,7 +76,8 @@ public class TestCpuMeter {
         result = "1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1";
       }
     };
-    CpuMeter cpuMeter = new CpuMeter(id);
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    CpuMeter cpuMeter = new CpuMeter(meterRegistry, "cpu");
     Assertions.assertEquals(0.0, cpuMeter.getAllCpuUsage().getUsage(), 0.0);
     Assertions.assertEquals(0.0, cpuMeter.getProcessCpuUsage().getUsage(), 0.0);
 
@@ -85,14 +87,14 @@ public class TestCpuMeter {
         result = "2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 2 2";
       }
     };
-    cpuMeter.update();
+    cpuMeter.poll(0, 0);
 
     Assertions.assertEquals(0.875, cpuMeter.getAllCpuUsage().getUsage(), 0.0);
     Assertions.assertEquals(0.5, cpuMeter.getProcessCpuUsage().getUsage(), 0.0);
   }
 
   @Test
-  public void testRefreshError(@Mocked Id id, @Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
+  public void testRefreshError(@Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
       @Mocked CharSource charSource) throws IOException {
 
     new MockUp<Files>() {
@@ -127,7 +129,8 @@ public class TestCpuMeter {
         result = "1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1";
       }
     };
-    CpuMeter cpuMeter = new CpuMeter(id);
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    CpuMeter cpuMeter = new CpuMeter(meterRegistry, "cpu");
     Assertions.assertEquals(0.0, cpuMeter.getAllCpuUsage().getUsage(), 0.0);
     Assertions.assertEquals(0.0, cpuMeter.getProcessCpuUsage().getUsage(), 0.0);
     new Expectations() {
@@ -136,17 +139,15 @@ public class TestCpuMeter {
         result = "1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1";
       }
     };
-    cpuMeter.update();
+    cpuMeter.poll(0, 0);
 
     Assertions.assertEquals(0.0, cpuMeter.getAllCpuUsage().getUsage(), 0.0);
     Assertions.assertEquals(0.0, cpuMeter.getProcessCpuUsage().getUsage(), 0.0);
   }
 
   @Test
-  public void testCalcMeasurements(@Mocked Id id, @Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
+  public void testCalcMeasurements(@Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
       @Mocked CharSource charSource) throws IOException {
-    List<Measurement> measurements = new ArrayList<>();
-
     new MockUp<Files>() {
       @Mock
       public CharSource asCharSource(File file, Charset encoding) {
@@ -179,7 +180,9 @@ public class TestCpuMeter {
         result = "1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1";
       }
     };
-    CpuMeter cpuMeter = new CpuMeter(id);
+
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    CpuMeter cpuMeter = new CpuMeter(meterRegistry, "cpu");
 
     new Expectations() {
       {
@@ -187,13 +190,14 @@ public class TestCpuMeter {
         result = "2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 2 2";
       }
     };
-    cpuMeter.calcMeasurements(measurements, 0);
-    Assertions.assertEquals(2, measurements.size());
+
+    cpuMeter.poll(System.currentTimeMillis(), 1000);
+
+    List<Measurement> measurements = new ArrayList<>();
+    meterRegistry.getMeters().forEach(meter -> meter.measure().forEach(measurement -> measurements.add(measurement)));
     Measurement measurement = measurements.get(0);
-    Assertions.assertEquals(0, measurement.timestamp());
-    Assertions.assertEquals(0.875, measurement.value(), 0.0);
+    Assertions.assertEquals(0.5, measurement.getValue(), 0.0);
     measurement = measurements.get(1);
-    Assertions.assertEquals(0, measurement.timestamp());
-    Assertions.assertEquals(0.5, measurement.value(), 0.0);
+    Assertions.assertEquals(0.875, measurement.getValue(), 0.0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
index 89b8b49e4..60f54e3d7 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
@@ -23,20 +23,22 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.os.net.InterfaceUsage;
 import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Mock;
 import mockit.MockUp;
-import mockit.Mocked;
-import org.junit.jupiter.api.Assertions;
 
 public class TestNetMeter {
   @Test
-  public void testNetRefreshUnchanged(@Mocked Id id) {
+  public void testNetRefreshUnchanged() {
     List<String> list = new ArrayList<>();
     list.add("useless");
     list.add("useless");
@@ -47,7 +49,8 @@ public class TestNetMeter {
         return list;
       }
     };
-    NetMeter netMeter = new NetMeter(id);
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    NetMeter netMeter = new NetMeter(meterRegistry, "net", Tags.empty());
     list.remove(2);
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
     netMeter.refreshNet(1);
@@ -58,30 +61,29 @@ public class TestNetMeter {
 
     Assertions.assertEquals("eth0", eth0.getName());
 
-    Assertions.assertEquals(4, eth0.getNetStats().size());
     // recv Bps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(1L, eth0.getReceive().getLastValue());
+    Assertions.assertEquals(1, eth0.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, eth0.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, eth0.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(1L, eth0.getSend().getLastValue());
+    Assertions.assertEquals(1, eth0.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, eth0.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(1L, eth0.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, eth0.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(1L, eth0.getPacketsSend().getLastValue());
+    Assertions.assertEquals(1, eth0.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, eth0.getPacketsSend().getIndex());
   }
 
 
   @Test
-  public void testNetRefreshAdd(@Mocked Id id) {
+  public void testNetRefreshAdd() {
     List<String> list = new ArrayList<>();
     list.add("useless");
     list.add("useless");
@@ -92,7 +94,9 @@ public class TestNetMeter {
         return list;
       }
     };
-    NetMeter netMeter = new NetMeter(id);
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    NetMeter netMeter = new NetMeter(meterRegistry, "net", Tags.empty());
+    netMeter.poll(0, 0);
     Map<String, InterfaceUsage> netMap = netMeter.getInterfaceUsageMap();
     Assertions.assertEquals(1, netMap.size());
     list.remove(2);
@@ -102,53 +106,52 @@ public class TestNetMeter {
     Assertions.assertEquals(2, netMap.size());
     InterfaceUsage eth0 = netMap.get("eth0");
     Assertions.assertEquals("eth0", eth0.getName());
-    Assertions.assertEquals(4, eth0.getNetStats().size());
+
     // recv Bps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(1L, eth0.getReceive().getLastValue());
+    Assertions.assertEquals(1, eth0.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, eth0.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, eth0.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(1L, eth0.getSend().getLastValue());
+    Assertions.assertEquals(1, eth0.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, eth0.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(1L, eth0.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, eth0.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(1L, eth0.getPacketsSend().getLastValue());
+    Assertions.assertEquals(1, eth0.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, eth0.getPacketsSend().getIndex());
 
     InterfaceUsage lo = netMap.get("lo");
     Assertions.assertEquals("lo", lo.getName());
 
-    Assertions.assertEquals(4, lo.getNetStats().size());
     // recv Bps
-    Assertions.assertEquals(0L, lo.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, lo.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(0L, lo.getReceive().getLastValue());
+    Assertions.assertEquals(0, lo.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, lo.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(0L, lo.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, lo.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(0L, lo.getSend().getLastValue());
+    Assertions.assertEquals(0, lo.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, lo.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(0L, lo.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, lo.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(0L, lo.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(0, lo.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, lo.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(0L, lo.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, lo.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(0L, lo.getPacketsSend().getLastValue());
+    Assertions.assertEquals(0, lo.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, lo.getPacketsSend().getIndex());
   }
 
 
   @Test
-  public void testNetRefreshRemove(@Mocked Id id) {
+  public void testNetRefreshRemove() {
     List<String> list = new ArrayList<>();
     list.add("useless");
     list.add("useless");
@@ -160,83 +163,82 @@ public class TestNetMeter {
         return list;
       }
     };
-    NetMeter netMeter = new NetMeter(id);
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    NetMeter netMeter = new NetMeter(meterRegistry, "net", Tags.empty());
+    netMeter.poll(0, 1);
     Map<String, InterfaceUsage> netMap = netMeter.getInterfaceUsageMap();
     Assertions.assertEquals(2, netMap.size());
     InterfaceUsage lo = netMap.get("lo");
     InterfaceUsage eth0 = netMap.get("eth0");
     Assertions.assertEquals("lo", lo.getName());
-    Assertions.assertEquals(4, lo.getNetStats().size());
     // recv Bps
-    Assertions.assertEquals(0L, lo.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, lo.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(0L, lo.getReceive().getLastValue());
+    Assertions.assertEquals(0, lo.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, lo.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(0L, lo.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, lo.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(0L, lo.getSend().getLastValue());
+    Assertions.assertEquals(0, lo.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, lo.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(0L, lo.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, lo.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(0L, lo.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(0, lo.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, lo.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(0L, lo.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(0, lo.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, lo.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(0L, lo.getPacketsSend().getLastValue());
+    Assertions.assertEquals(0, lo.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, lo.getPacketsSend().getIndex());
 
     Assertions.assertEquals("eth0", eth0.getName());
-    Assertions.assertEquals(4, eth0.getNetStats().size());
     // recv Bps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(0L, eth0.getReceive().getLastValue());
+    Assertions.assertEquals(0, eth0.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, eth0.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, eth0.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(0L, eth0.getSend().getLastValue());
+    Assertions.assertEquals(0, eth0.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, eth0.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(0L, eth0.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(0, eth0.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(0L, eth0.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(0, eth0.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, eth0.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(0L, eth0.getPacketsSend().getLastValue());
+    Assertions.assertEquals(0, eth0.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, eth0.getPacketsSend().getIndex());
     list.remove(2);
     list.remove(2);
     list.add("eth0: 1 1    0    0    0     0          0          1         1 1    1      0     0     0    0    0");
     netMeter.refreshNet(1);
-    Assertions.assertNull(netMap.get("lo"));
-    Assertions.assertEquals(1, netMap.size());
+
     Assertions.assertEquals("eth0", eth0.getName());
-    Assertions.assertEquals(4, eth0.getNetStats().size());
+
     // recv Bps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(0).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(0).getRate(), 0.0);
-    Assertions.assertEquals(0, eth0.getNetStats().get(0).getIndex());
+    Assertions.assertEquals(1L, eth0.getReceive().getLastValue());
+    Assertions.assertEquals(1, eth0.getReceive().getRate(), 0.0);
+    Assertions.assertEquals(0, eth0.getReceive().getIndex());
     // send Bps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(1).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(1).getRate(), 0.0);
-    Assertions.assertEquals(8, eth0.getNetStats().get(1).getIndex());
+    Assertions.assertEquals(1L, eth0.getSend().getLastValue());
+    Assertions.assertEquals(1, eth0.getSend().getRate(), 0.0);
+    Assertions.assertEquals(8, eth0.getSend().getIndex());
 
     // recv pps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(2).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getRate(), 0.0);
-    Assertions.assertEquals(1, eth0.getNetStats().get(2).getIndex());
+    Assertions.assertEquals(1L, eth0.getPacketsReceive().getLastValue());
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getRate(), 0.0);
+    Assertions.assertEquals(1, eth0.getPacketsReceive().getIndex());
 
     // send pps
-    Assertions.assertEquals(1L, eth0.getNetStats().get(3).getLastValue());
-    Assertions.assertEquals(1, eth0.getNetStats().get(3).getRate(), 0.0);
-    Assertions.assertEquals(9, eth0.getNetStats().get(3).getIndex());
+    Assertions.assertEquals(1L, eth0.getPacketsSend().getLastValue());
+    Assertions.assertEquals(1, eth0.getPacketsSend().getRate(), 0.0);
+    Assertions.assertEquals(9, eth0.getPacketsSend().getIndex());
   }
 
 
   @Test
-  public void testCalcMeasurements(@Mocked Id id) {
+  public void testCalcMeasurements() {
     List<String> list = new ArrayList<>();
     list.add("useless");
     list.add("useless");
@@ -247,19 +249,23 @@ public class TestNetMeter {
         return list;
       }
     };
-    NetMeter netMeter = new NetMeter(id);
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+    NetMeter netMeter = new NetMeter(meterRegistry, "net", Tags.empty());
     list.remove(2);
     list.add("eth0: 3 1    0    0    0     0          0          1         3 1    1      0     0     0    0    0");
-    List<Measurement> measurements = new ArrayList<>();
-    netMeter.calcMeasurements(measurements, 0L, 1);
-    Assertions.assertEquals(4, measurements.size());
-    Measurement receive = measurements.get(0);
-    Measurement send = measurements.get(1);
-    Measurement receivePackets = measurements.get(2);
-    Measurement sendPackets = measurements.get(3);
-    Assertions.assertEquals(3.0, send.value(), 0.0);
-    Assertions.assertEquals(1.0, sendPackets.value(), 0.0);
-    Assertions.assertEquals(3.0, receive.value(), 0.0);
-    Assertions.assertEquals(1.0, receivePackets.value(), 0.0);
+    netMeter.poll(0, 1);
+
+    MeasurementTree tree = new MeasurementTree();
+    tree.from(meterRegistry.getMeters().iterator(),
+        new MeasurementGroupConfig("net", "statistic"));
+
+    Measurement receive = tree.findChild("net", "receive").getMeasurements().get(0);
+    Measurement send = tree.findChild("net", "send").getMeasurements().get(0);
+    Measurement receivePackets = tree.findChild("net", "receivePackets").getMeasurements().get(0);
+    Measurement sendPackets = tree.findChild("net", "sendPackets").getMeasurements().get(0);
+    Assertions.assertEquals(3.0, send.getValue(), 0.0);
+    Assertions.assertEquals(1.0, sendPackets.getValue(), 0.0);
+    Assertions.assertEquals(3.0, receive.getValue(), 0.0);
+    Assertions.assertEquals(1.0, receivePackets.getValue(), 0.0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
index 6f71a126d..98863c911 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
@@ -26,28 +26,28 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.CpuUtils;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
-import org.mockito.Mockito;
 
-import com.google.common.collect.Lists;
 import com.google.common.io.CharSource;
 import com.google.common.io.Files;
 
-import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Expectations;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
 
 public class TestOsMeter {
-  MeterRegistry meterRegistry = Mockito.mock(MeterRegistry.class);
-
   @Test
   public void testCalcMeasurement(@Mocked Runtime runtime, @Mocked RuntimeMXBean mxBean,
       @Mocked CharSource charSource) throws IOException {
+    MeterRegistry meterRegistry = new SimpleMeterRegistry();
+
     List<String> list = new ArrayList<>();
     list.add("useless");
     list.add("useless");
@@ -101,14 +101,17 @@ public class TestOsMeter {
         result = "2 2 2 2 2 2 2 2 2 0 0 2 2 2 2 2 2 2 2 2 2";
       }
     };
-    osMeter.calcMeasurements(1, 1);
-    ArrayList<Measurement> measurements = Lists.newArrayList(osMeter.measure());
-    Assertions.assertEquals(6, measurements.size());
-    Assertions.assertEquals(0.875, measurements.get(0).getValue(), 0.0);
-    Assertions.assertEquals(0.5, measurements.get(1).getValue(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(2).getValue(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(3).getValue(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(4).getValue(), 0.0);
-    Assertions.assertEquals(1.0, measurements.get(5).getValue(), 0.0);
+    osMeter.poll(0, 1);
+
+    MeasurementTree tree = new MeasurementTree();
+    tree.from(meterRegistry.getMeters().iterator(),
+        new MeasurementGroupConfig("os", "type"));
+
+    Assertions.assertEquals(0.875, tree.findChild("os", "cpu").getMeasurements().get(0).getValue(), 0.0);
+    Assertions.assertEquals(0.5, tree.findChild("os", "processCpu").getMeasurements().get(0).getValue(), 0.0);
+    Assertions.assertEquals(1.0, tree.findChild("os", "net").getMeasurements().get(0).getValue(), 0.0);
+    Assertions.assertEquals(1.0, tree.findChild("os", "net").getMeasurements().get(1).getValue(), 0.0);
+    Assertions.assertEquals(1.0, tree.findChild("os", "net").getMeasurements().get(2).getValue(), 0.0);
+    Assertions.assertEquals(1.0, tree.findChild("os", "net").getMeasurements().get(3).getValue(), 0.0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
index 90cf30e4c..e0b1618e8 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
@@ -32,7 +32,6 @@ import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
@@ -52,8 +51,14 @@ import org.mockito.Mockito;
 import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.Measurement;
 
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Meter.Type;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import io.vertx.core.impl.VertxImpl;
 import jakarta.ws.rs.core.Response.Status;
 import mockit.Expectations;
@@ -63,7 +68,7 @@ import mockit.MockUp;
 
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class TestDefaultLogPublisher {
-  GlobalRegistry globalRegistry = new GlobalRegistry();
+  MeterRegistry meterRegistry = new SimpleMeterRegistry();
 
   EventBus eventBus = new EventBus();
 
@@ -99,7 +104,7 @@ public class TestDefaultLogPublisher {
       }
     };
 
-    publisher.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
+    publisher.init(meterRegistry, eventBus, new MetricsBootstrapConfig(environment));
     Assertions.assertFalse(registered.value);
   }
 
@@ -114,7 +119,7 @@ public class TestDefaultLogPublisher {
       }
     };
 
-    publisher.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
+    publisher.init(meterRegistry, eventBus, new MetricsBootstrapConfig(environment));
     Assertions.assertTrue(registered.value);
   }
 
@@ -129,7 +134,7 @@ public class TestDefaultLogPublisher {
       }
     };
 
-    publisher.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
+    publisher.init(meterRegistry, eventBus, new MetricsBootstrapConfig(environment));
     Assertions.assertNull(registered.value);
   }
 
@@ -144,12 +149,12 @@ public class TestDefaultLogPublisher {
 
   @Test
   public void onPolledEvent(@Injectable VertxImpl vertxImpl, @Injectable MeasurementTree tree,
-      @Injectable GlobalRegistry globalRegistry, @Injectable EventBus eventBus) {
+      @Injectable EventBus eventBus) {
     MetricsBootstrapConfig config = Mockito.mock(MetricsBootstrapConfig.class);
     try {
       Mockito.when(environment.getProperty(DefaultLogPublisher.ENABLED, boolean.class, false)).thenReturn(true);
       Mockito.when(config.getLatencyDistribution()).thenReturn("0,1,100");
-      publisher.init(globalRegistry, eventBus, config);
+      publisher.init(meterRegistry, eventBus, config);
       new Expectations(VertxUtils.class) {
         {
           VertxUtils.getVertxMap();
@@ -188,17 +193,18 @@ public class TestDefaultLogPublisher {
       model.getEdge().setOperationPerfGroups(operationPerfGroups);
 
       model.getThreadPools().put("test", new ThreadPoolPublishModel());
-      Measurement measurement = new Measurement(null, 0L, 1.0);
+      Id id = new Id("test", Tags.empty(), null, null, Type.OTHER);
+      Measurement measurement = new Measurement(() -> 1.0, Statistic.VALUE);
 
-      MeasurementNode measurementNodeCpuAll = new MeasurementNode("allProcess", new HashMap<>());
-      MeasurementNode measurementNodeCpuProcess = new MeasurementNode("currentProcess", new HashMap<>());
-      MeasurementNode measurementNodeSend = new MeasurementNode("send", new HashMap<>());
-      MeasurementNode measurementNodeSendPacket = new MeasurementNode("sendPackets", new HashMap<>());
-      MeasurementNode measurementNodeRecv = new MeasurementNode("receive", new HashMap<>());
-      MeasurementNode measurementNodeRecvPacket = new MeasurementNode("receivePackets", new HashMap<>());
-      MeasurementNode measurementNodeEth0 = new MeasurementNode("eth0", new HashMap<>());
-      MeasurementNode measurementNodeNet = new MeasurementNode("net", new HashMap<>());
-      MeasurementNode measurementNodeOs = new MeasurementNode("os", new HashMap<>());
+      MeasurementNode measurementNodeCpuAll = new MeasurementNode("allProcess", id, new HashMap<>());
+      MeasurementNode measurementNodeCpuProcess = new MeasurementNode("currentProcess", id, new HashMap<>());
+      MeasurementNode measurementNodeSend = new MeasurementNode("send", id, new HashMap<>());
+      MeasurementNode measurementNodeSendPacket = new MeasurementNode("sendPackets", id, new HashMap<>());
+      MeasurementNode measurementNodeRecv = new MeasurementNode("receive", id, new HashMap<>());
+      MeasurementNode measurementNodeRecvPacket = new MeasurementNode("receivePackets", id, new HashMap<>());
+      MeasurementNode measurementNodeEth0 = new MeasurementNode("eth0", id, new HashMap<>());
+      MeasurementNode measurementNodeNet = new MeasurementNode("net", id, new HashMap<>());
+      MeasurementNode measurementNodeOs = new MeasurementNode("os", id, new HashMap<>());
 
       measurementNodeSend.getMeasurements().add(measurement);
       measurementNodeRecv.getMeasurements().add(measurement);
@@ -238,7 +244,7 @@ public class TestDefaultLogPublisher {
           result = measurementNodeOs;
         }
       };
-      publisher.onPolledEvent(new PolledEvent(Collections.emptyList(), Collections.emptyList()));
+      publisher.onPolledEvent(new PolledEvent(Collections.emptyList()));
       List<LogEvent> events = collector.getEvents().stream()
           .filter(e -> "scb-metrics".equals(e.getLoggerName())).toList();
       LogEvent event = events.get(0);
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
index 6480928f9..535c28700 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
@@ -36,20 +36,18 @@ import org.junit.jupiter.api.Assertions;
 import org.mockito.Mockito;
 import org.springframework.core.env.Environment;
 
-import com.google.common.collect.Lists;
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
 
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import io.vertx.core.json.Json;
 
 public class TestInvocationPublishModelFactory {
   EventBus eventBus = new EventBus();
 
-  GlobalRegistry globalRegistry = new GlobalRegistry();
+  MeterRegistry meterRegistry = new SimpleMeterRegistry();
 
-  Registry registry = new DefaultRegistry(new ManualClock());
+  GlobalRegistry globalRegistry = new GlobalRegistry(meterRegistry);
 
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
 
@@ -71,208 +69,208 @@ public class TestInvocationPublishModelFactory {
             CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
         .thenReturn(7);
     Mockito.when(environment.getProperty(CONFIG_LATENCY_DISTRIBUTION, String.class)).thenReturn("0,1,100");
-    globalRegistry.add(registry);
-    invocationMetersInitializer.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
+
+    invocationMetersInitializer.init(meterRegistry, eventBus, new MetricsBootstrapConfig(environment));
     prepareInvocation();
 
     globalRegistry.poll(1);
-    PublishModelFactory factory = new PublishModelFactory(Lists.newArrayList(registry.iterator()));
+    PublishModelFactory factory = new PublishModelFactory(meterRegistry.getMeters());
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
     String expect = """
         {
-          "operationPerfGroups" : {
-            "groups" : {
-              "rest" : {
-                "200" : {
-                  "transport" : "rest",
-                  "status" : "200",
-                  "operationPerfs" : [ {
-                    "operation" : "m.s.o",
-                    "stages" : {
-                      "consumer-encode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "prepare" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "total" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.4000000000000001E-5,
-                        "msMaxLatency" : 1.4000000000000001E-5
-                      },
-                      "wait" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "consumer-send" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "connection" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "consumer-decode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      }
-                    },
-                    "latencyDistribution" : [ 1, 0, 0 ]
-                  } ],
-                  "summary" : {
-                    "operation" : "",
-                    "stages" : {
-                      "consumer-encode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "prepare" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "wait" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "total" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.4000000000000001E-5,
-                        "msMaxLatency" : 1.4000000000000001E-5
-                      },
-                      "consumer-send" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "connection" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "consumer-decode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      }
-                    },
-                    "latencyDistribution" : [ 1, 0, 0 ]
-                  }
-                }
-              }
-            }
-          }
-        }
+           "operationPerfGroups" : {
+             "groups" : {
+               "rest" : {
+                 "200" : {
+                   "transport" : "rest",
+                   "status" : "200",
+                   "operationPerfs" : [ {
+                     "operation" : "m.s.o",
+                     "stages" : {
+                       "consumer-encode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "prepare" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "wait" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "total" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.4E-5,
+                         "msMaxLatency" : 1.4E-5
+                       },
+                       "consumer-send" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "connection" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "consumer-decode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       }
+                     },
+                     "latencyDistribution" : [ 1, 0, 0 ]
+                   } ],
+                   "summary" : {
+                     "operation" : "",
+                     "stages" : {
+                       "consumer-encode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "prepare" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "total" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.4E-5,
+                         "msMaxLatency" : 1.4E-5
+                       },
+                       "wait" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "consumer-send" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "connection" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "consumer-decode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       }
+                     },
+                     "latencyDistribution" : [ 1, 0, 0 ]
+                   }
+                 }
+               }
+             }
+           }
+         }
         """;
     Assertions.assertEquals(Json.encodePrettily(Json.decodeValue(expect, Object.class)),
         Json.encodePrettily(model.getConsumer()));
 
     expect = """
         {
-          "operationPerfGroups" : {
-            "groups" : {
-              "rest" : {
-                "200" : {
-                  "transport" : "rest",
-                  "status" : "200",
-                  "operationPerfs" : [ {
-                    "operation" : "m.s.o",
-                    "stages" : {
-                      "consumer-encode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "prepare" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "total" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.4000000000000001E-5,
-                        "msMaxLatency" : 1.4000000000000001E-5
-                      },
-                      "wait" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "consumer-send" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "connection" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "consumer-decode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      }
-                    },
-                    "latencyDistribution" : [ 1, 0, 0 ]
-                  } ],
-                  "summary" : {
-                    "operation" : "",
-                    "stages" : {
-                      "consumer-encode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "prepare" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "wait" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "total" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.4000000000000001E-5,
-                        "msMaxLatency" : 1.4000000000000001E-5
-                      },
-                      "consumer-send" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "connection" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      },
-                      "consumer-decode" : {
-                        "tps" : 1.0,
-                        "msTotalTime" : 1.0000000000000002E-6,
-                        "msMaxLatency" : 1.0000000000000002E-6
-                      }
-                    },
-                    "latencyDistribution" : [ 1, 0, 0 ]
-                  }
-                }
-              }
-            }
-          }
-        }
+           "operationPerfGroups" : {
+             "groups" : {
+               "rest" : {
+                 "200" : {
+                   "transport" : "rest",
+                   "status" : "200",
+                   "operationPerfs" : [ {
+                     "operation" : "m.s.o",
+                     "stages" : {
+                       "consumer-encode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "prepare" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "wait" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "total" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.4E-5,
+                         "msMaxLatency" : 1.4E-5
+                       },
+                       "consumer-send" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "connection" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "consumer-decode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       }
+                     },
+                     "latencyDistribution" : [ 1, 0, 0 ]
+                   } ],
+                   "summary" : {
+                     "operation" : "",
+                     "stages" : {
+                       "consumer-encode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "prepare" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "total" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.4E-5,
+                         "msMaxLatency" : 1.4E-5
+                       },
+                       "wait" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "consumer-send" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "connection" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       },
+                       "consumer-decode" : {
+                         "tps" : 1.0,
+                         "msTotalTime" : 1.0000000000000002E-6,
+                         "msMaxLatency" : 1.0000000000000002E-6
+                       }
+                     },
+                     "latencyDistribution" : [ 1, 0, 0 ]
+                   }
+                 }
+               }
+             }
+           }
+         }
         """;
     Assertions.assertEquals(Json.encodePrettily(Json.decodeValue(expect, Object.class)),
         Json.encodePrettily(model.getProducer()));
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
index 66a451aef..a540eb21b 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
@@ -32,7 +32,7 @@ import org.apache.servicecomb.metrics.core.publish.model.invocation.Utils;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 
-import com.netflix.spectator.api.patterns.ThreadPoolMonitorPublishModelFactory;
+import org.apache.servicecomb.metrics.core.meter.ThreadPoolMonitorPublishModelFactory;
 
 import jakarta.ws.rs.core.Response.Status;
 
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
index ef37c4f93..64778d3ee 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
@@ -19,27 +19,26 @@ package org.apache.servicecomb.metrics.core.publish;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ThreadPoolExecutor;
 
+import org.apache.servicecomb.foundation.common.event.EventManager;
 import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
+import org.apache.servicecomb.metrics.core.ThreadPoolMetersInitializer;
 import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 import org.junit.runners.MethodSorters;
+import org.mockito.Mockito;
 
-import com.google.common.collect.Lists;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.patterns.PolledMeter;
-import com.netflix.spectator.api.patterns.ThreadPoolMonitor;
-
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import mockit.Expectations;
 import mockit.Injectable;
 import mockit.Mocked;
 
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 public class TestThreadPoolPublishModelFactory {
-  protected Registry registry = new DefaultRegistry(new ManualClock());
+  MeterRegistry registry = new SimpleMeterRegistry();
 
   @Mocked
   BlockingQueue<Runnable> queue;
@@ -55,10 +54,15 @@ public class TestThreadPoolPublishModelFactory {
       }
     };
 
-    ThreadPoolMonitor.attach(registry, threadPoolExecutor, "test");
-
-    PolledMeter.update(registry);
-    PublishModelFactory factory = new PublishModelFactory(Lists.newArrayList(registry.iterator()));
+    MetricsBootstrapConfig metricsBootstrapConfig = Mockito.mock(MetricsBootstrapConfig.class);
+    ThreadPoolMetersInitializer threadPoolMetersInitializer = new ThreadPoolMetersInitializer() {
+      @Override
+      public void createThreadPoolMeters() {
+        createThreadPoolMeters("test", threadPoolExecutor);
+      }
+    };
+    threadPoolMetersInitializer.init(registry, EventManager.getEventBus(), metricsBootstrapConfig);
+    PublishModelFactory factory = new PublishModelFactory(registry.getMeters());
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
     Assertions.assertEquals(
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
index 9c65ee24a..2a6247870 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
@@ -24,46 +24,47 @@ import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNo
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.PublishUtils;
 
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
-import com.netflix.spectator.api.Registry;
-import com.netflix.spectator.api.Statistic;
-
+import io.micrometer.core.instrument.Measurement;
+import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Meter.Type;
+import io.micrometer.core.instrument.Statistic;
+import io.micrometer.core.instrument.Tags;
 import jakarta.ws.rs.core.Response.Status;
 
 public class Utils {
-  static Registry registry = new DefaultRegistry();
-
   public static MeasurementNode totalStageNode = Utils.createStageNode(InvocationStageTrace.STAGE_TOTAL, 10, 10, 100);
 
   public static MeasurementNode executeStageNode =
       Utils.createStageNode(InvocationStageTrace.STAGE_PROVIDER_BUSINESS, 10, 10, 100);
 
+  public static Id initId = new Id("id", Tags.empty(), null, null, Type.OTHER);
+
   public static MeasurementNode createStageNode(String stage,
       double count,
       double totalTime,
       double max) {
-    Id id = registry.createId("id").withTag(Statistic.count);
-    Measurement countMeasurement = new Measurement(id.withTag(Statistic.count), 0, count);
-    Measurement totalTimeMeasurement = new Measurement(id.withTag(Statistic.totalTime), 0, totalTime);
-    Measurement maxMeasurement = new Measurement(id.withTag(Statistic.max), 0, max);
+    Id id = initId;
+    Measurement countMeasurement = new Measurement(() -> count, Statistic.COUNT);
+    Measurement totalTimeMeasurement = new Measurement(() -> totalTime, Statistic.TOTAL_TIME);
+    Measurement maxMeasurement = new Measurement(() -> max, Statistic.MAX);
 
-    MeasurementNode stageNode = new MeasurementNode(stage, null);
-    stageNode.addChild(Statistic.count.name(), countMeasurement);
-    stageNode.addChild(Statistic.totalTime.name(), totalTimeMeasurement);
-    stageNode.addChild(Statistic.max.name(), maxMeasurement);
+    MeasurementNode stageNode = new MeasurementNode(stage, id, null);
+    stageNode.addChild(Statistic.COUNT.name(), id, countMeasurement);
+    stageNode.addChild(Statistic.TOTAL_TIME.name(), id, totalTimeMeasurement);
+    stageNode.addChild(Statistic.MAX.name(), id, maxMeasurement);
 
     return stageNode;
   }
 
   public static MeasurementNode createStatusNode(String status, MeasurementNode... stageNodes) {
-    MeasurementNode statusNode = new MeasurementNode(status, new HashMap<>());
-    MeasurementNode typeNode = new MeasurementNode(MeterInvocationConst.TAG_STAGE, new HashMap<>());
-    MeasurementNode latencyNode = new MeasurementNode(MeterInvocationConst.TAG_LATENCY_DISTRIBUTION, new HashMap<>());
+    Id id = initId;
+    MeasurementNode statusNode = new MeasurementNode(status, id, new HashMap<>());
+    MeasurementNode typeNode = new MeasurementNode(MeterInvocationConst.TAG_STAGE, id, new HashMap<>());
+    MeasurementNode latencyNode = new MeasurementNode(MeterInvocationConst.TAG_LATENCY_DISTRIBUTION, id,
+        new HashMap<>());
     List<Measurement> measurements = latencyNode.getMeasurements();
-    measurements.add(new Measurement(null, 0L, 1));
-    measurements.add(new Measurement(null, 0L, 2));
+    measurements.add(new Measurement(() -> 1, Statistic.VALUE));
+    measurements.add(new Measurement(() -> 2, Statistic.VALUE));
     for (MeasurementNode stageNode : stageNodes) {
       typeNode.getChildren().put(stageNode.getName(), stageNode);
     }
diff --git a/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java b/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java
index 167a66b40..bd9fdd0bf 100644
--- a/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java
+++ b/metrics/metrics-integration/metrics-prometheus/src/test/java/org/apache/servicecomb/metrics/prometheus/TestPrometheusPublisher.java
@@ -33,7 +33,6 @@ import org.apache.commons.lang3.reflect.FieldUtils;
 import org.apache.servicecomb.config.BootStrapProperties;
 import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -41,16 +40,15 @@ import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 import org.springframework.core.env.Environment;
 
-import com.netflix.spectator.api.Counter;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
 import com.sun.net.httpserver.HttpServer;
 
+import io.micrometer.core.instrument.Counter;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import io.prometheus.client.exporter.HTTPServer;
 
 public class TestPrometheusPublisher {
-  GlobalRegistry globalRegistry = new GlobalRegistry(new ManualClock());
+  MeterRegistry meterRegistry = new SimpleMeterRegistry();
 
   PrometheusPublisher publisher = new PrometheusPublisher();
 
@@ -75,7 +73,7 @@ public class TestPrometheusPublisher {
     Mockito.when(environment.getProperty(METRICS_PROMETHEUS_ADDRESS, String.class, "0.0.0.0:9696"))
         .thenReturn("a:b:c");
     Assertions.assertThrows(ServiceCombException.class, () -> {
-      publisher.init(globalRegistry, null, null);
+      publisher.init(meterRegistry, null, null);
     });
   }
 
@@ -84,7 +82,7 @@ public class TestPrometheusPublisher {
     Mockito.when(environment.getProperty(METRICS_PROMETHEUS_ADDRESS, String.class, "0.0.0.0:9696"))
         .thenReturn("localhost:xxxx");
     Assertions.assertThrows(ServiceCombException.class, () -> {
-      publisher.init(globalRegistry, null, null);
+      publisher.init(meterRegistry, null, null);
     });
   }
 
@@ -93,7 +91,7 @@ public class TestPrometheusPublisher {
     Mockito.when(environment.getProperty(METRICS_PROMETHEUS_ADDRESS, String.class, "0.0.0.0:9696"))
         .thenReturn("localhost:9999999");
     Assertions.assertThrows(ServiceCombException.class, () -> {
-      publisher.init(globalRegistry, null, null);
+      publisher.init(meterRegistry, null, null);
     });
   }
 
@@ -103,12 +101,9 @@ public class TestPrometheusPublisher {
     Mockito.when(environment.getProperty(METRICS_PROMETHEUS_ADDRESS, String.class, "0.0.0.0:9696"))
         .thenReturn("localhost:0");
     publisher.setEnvironment(environment);
-    publisher.init(globalRegistry, null, new MetricsBootstrapConfig(environment));
+    publisher.init(meterRegistry, null, new MetricsBootstrapConfig(environment));
 
-    Registry registry = new DefaultRegistry(new ManualClock());
-    globalRegistry.add(registry);
-
-    Counter counter = registry.counter("count.name", "tag1", "tag1v", "tag2", "tag2v");
+    Counter counter = meterRegistry.counter("count.name", "tag1", "tag1v", "tag2", "tag2v");
     counter.increment();
 
     HTTPServer httpServer = (HTTPServer) FieldUtils.readField(publisher, "httpServer", true);
diff --git a/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java b/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java
index 65103dbb2..e989a5b8a 100644
--- a/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java
+++ b/solutions/solution-basic/src/main/java/org/apache/servicecomb/solution/basic/integration/MetricsEndpointImpl.java
@@ -24,13 +24,16 @@ import java.util.stream.StreamSupport;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.metrics.core.meter.vertx.EndpointMeter;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 
 import com.google.common.eventbus.EventBus;
 
+import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.Meter.Id;
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
 
 @RestSchema(schemaId = MetricsEndpoint.NAME, schemaInterface = MetricsEndpoint.class)
 public class MetricsEndpointImpl implements MetricsInitializer, MetricsEndpoint {
@@ -48,7 +51,7 @@ public class MetricsEndpointImpl implements MetricsInitializer, MetricsEndpoint
 
     for (Meter meter : this.meterRegistry.getMeters()) {
       meter.measure().forEach(measurement -> {
-        String key = idToString(meter.getId(), sb);
+        String key = idToString(meter.getId(), measurement, sb);
         measurements.put(key, measurement.getValue());
       });
     }
@@ -58,18 +61,23 @@ public class MetricsEndpointImpl implements MetricsInitializer, MetricsEndpoint
 
   // format id to string:
   // idName(tag1=value1,tag2=value2)
-  protected String idToString(Id id, StringBuilder sb) {
+  protected String idToString(Id id, Measurement measurement, StringBuilder sb) {
     sb.setLength(0);
-    sb.append(id.getName()).append('(');
+    sb.append(id.getName()).append("(").append(EndpointMeter.STATISTIC).append("=")
+        .append(measurement.getStatistic().name()).append(",");
     sb.append(StreamSupport
         .stream(id
             .getTags()
             .spliterator(), false)
-        .map(Object::toString)
+        .map(this::tagToString)
         .collect(
             Collectors.joining(",")));
     sb.append(')');
 
     return sb.toString();
   }
+
+  private String tagToString(Tag tag) {
+    return tag.getKey() + "=" + tag.getValue();
+  }
 }
diff --git a/solutions/solution-basic/src/test/java/org/apache/servicecomb/solution/basic/integration/TestMetricsEndpointImpl.java b/solutions/solution-basic/src/test/java/org/apache/servicecomb/solution/basic/integration/TestMetricsEndpointImpl.java
index a7698d609..cb175d9b7 100644
--- a/solutions/solution-basic/src/test/java/org/apache/servicecomb/solution/basic/integration/TestMetricsEndpointImpl.java
+++ b/solutions/solution-basic/src/test/java/org/apache/servicecomb/solution/basic/integration/TestMetricsEndpointImpl.java
@@ -23,25 +23,38 @@ import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.M
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
-import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.mockito.Mockito;
 import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.EventBus;
-import com.netflix.spectator.api.Clock;
-import com.netflix.spectator.api.DefaultRegistry;
-import com.netflix.spectator.api.ManualClock;
-import com.netflix.spectator.api.Registry;
+
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 
 public class TestMetricsEndpointImpl {
   MetricsEndpointImpl publisher = new MetricsEndpointImpl();
 
+  EventBus eventBus = new EventBus();
+
   Environment environment = Mockito.mock(Environment.class);
 
+  @BeforeEach
+  public void setUp() {
+    Mockito.when(environment.getProperty(METRICS_WINDOW_TIME, int.class, DEFAULT_METRICS_WINDOW_TIME))
+        .thenReturn(DEFAULT_METRICS_WINDOW_TIME);
+    Mockito.when(environment.getProperty(
+            CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
+        .thenReturn(7);
+  }
+
   @Test
   public void measure_globalRegistryNull() {
+    MeterRegistry registry = new SimpleMeterRegistry();
+    publisher.init(registry, eventBus, new MetricsBootstrapConfig(environment));
+
     Map<String, Double> result = publisher.measure();
 
     Assertions.assertEquals(0, result.size());
@@ -49,25 +62,15 @@ public class TestMetricsEndpointImpl {
 
   @Test
   public void measure_normal() {
-    Mockito.when(environment.getProperty(METRICS_WINDOW_TIME, int.class, DEFAULT_METRICS_WINDOW_TIME))
-        .thenReturn(DEFAULT_METRICS_WINDOW_TIME);
-    Mockito.when(environment.getProperty(
-            CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
-        .thenReturn(7);
-
-    Clock clock = new ManualClock();
-    GlobalRegistry globalRegistry = new GlobalRegistry();
-    Registry registry = new DefaultRegistry(clock);
-    registry.timer(registry.createId("name", "t1", "v1", "t2", "v2"));
-    globalRegistry.add(registry);
-
-    EventBus eventBus = new EventBus();
+    MeterRegistry registry = new SimpleMeterRegistry();
+    registry.timer("name", "t1", "v1", "t2", "v2");
 
-    publisher.init(globalRegistry, eventBus, new MetricsBootstrapConfig(environment));
+    publisher.init(registry, eventBus, new MetricsBootstrapConfig(environment));
     Map<String, Double> result = publisher.measure();
 
-    Assertions.assertEquals(2, result.size());
-    Assertions.assertEquals(0, result.get("name(statistic=count,t1=v1,t2=v2)"), 0);
-    Assertions.assertEquals(0, result.get("name(statistic=totalTime,t1=v1,t2=v2)"), 0);
+    Assertions.assertEquals(3, result.size());
+    Assertions.assertEquals(0, result.get("name(statistic=COUNT,t1=v1,t2=v2)"), 0);
+    Assertions.assertEquals(0, result.get("name(statistic=TOTAL_TIME,t1=v1,t2=v2)"), 0);
+    Assertions.assertEquals(0, result.get("name(statistic=MAX,t1=v1,t2=v2)"), 0);
   }
 }


(servicecomb-java-chassis) 07/11: [SCB-2838]using micrometer to replace spectator part5: configure meter registry

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 3b349b3efa8b692e89c17a12831007980e9465fe
Author: liubao <bi...@qq.com>
AuthorDate: Thu Nov 30 10:06:27 2023 +0800

    [SCB-2838]using micrometer to replace spectator part5: configure meter registry
---
 .../foundation/metrics/MetricsBootstrap.java       | 14 ++++-----
 .../publish/{spectator => }/DefaultTagFinder.java  |  2 +-
 .../{spectator => }/MeasurementGroupConfig.java    |  2 +-
 .../publish/{spectator => }/MeasurementNode.java   |  2 +-
 .../publish/{spectator => }/MeasurementTree.java   |  2 +-
 .../metrics/publish/{spectator => }/TagFinder.java |  2 +-
 .../metrics/registry/GlobalRegistry.java           | 34 ----------------------
 .../foundation/metrics/TestMetricsBootstrap.java   |  8 +++--
 .../publish/spectator/TestDefaultTagFinder.java    |  2 ++
 .../spectator/TestMeasurementGroupConfig.java      |  2 ++
 .../publish/spectator/TestMeasurementNode.java     |  1 +
 .../publish/spectator/TestMeasurementTree.java     |  4 +++
 .../metrics/publish/spectator/TestTagFinder.java   |  2 ++
 .../metrics/core/MetricsCoreConfiguration.java     | 31 ++++++++++++++++++--
 .../ThreadPoolMonitorPublishModelFactory.java      |  4 +--
 .../AbstractMeasurementNodeLogPublisher.java       |  4 +--
 .../core/publish/ClientEndpointsLogPublisher.java  |  4 +--
 .../metrics/core/publish/DefaultLogPublisher.java  |  4 +--
 .../metrics/core/publish/PublishModelFactory.java  |  8 ++---
 .../metrics/core/publish/PublishUtils.java         |  2 +-
 .../core/publish/ServerEndpointsLogPublisher.java  |  4 +--
 .../core/TestInvocationMetersInitializer.java      | 13 ++-------
 .../core/TestThreadPoolMetersInitializer.java      |  4 +--
 .../metrics/core/meter/os/TestNetMeter.java        |  4 +--
 .../metrics/core/meter/os/TestOsMeter.java         |  4 +--
 .../core/publish/TestDefaultLogPublisher.java      |  4 +--
 .../publish/TestInvocationPublishModelFactory.java |  4 ---
 .../metrics/core/publish/TestPublishUtils.java     |  4 +--
 .../core/publish/model/invocation/Utils.java       |  2 +-
 29 files changed, 83 insertions(+), 94 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
index 72be58c9d..86529a36e 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java
@@ -26,7 +26,6 @@ import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.env.Environment;
 
 import com.google.common.eventbus.EventBus;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
@@ -36,22 +35,19 @@ import io.micrometer.core.instrument.MeterRegistry;
 public class MetricsBootstrap {
   private static final Logger LOGGER = LoggerFactory.getLogger(MetricsBootstrap.class);
 
+  private final MetricsBootstrapConfig config;
+
   private MeterRegistry meterRegistry;
 
   private EventBus eventBus;
 
-  private MetricsBootstrapConfig config;
-
   private ScheduledExecutorService executorService;
 
   private List<MetricsInitializer> metricsInitializers;
 
-  private Environment environment;
-
   @Autowired
-  public void setEnvironment(Environment environment) {
-    this.environment = environment;
-    config = new MetricsBootstrapConfig(environment);
+  public MetricsBootstrap(MetricsBootstrapConfig config) {
+    this.config = config;
   }
 
   @Autowired
@@ -68,7 +64,7 @@ public class MetricsBootstrap {
     this.eventBus = eventBus;
     this.executorService = Executors.newScheduledThreadPool(1,
         new ThreadFactoryBuilder()
-            .setNameFormat("spectator-poller-%d")
+            .setNameFormat("metrics-poller-%d")
             .build());
 
     metricsInitializers.forEach(initializer -> initializer.init(this.meterRegistry, eventBus, config));
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/DefaultTagFinder.java
similarity index 95%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/DefaultTagFinder.java
index 31af35c7a..f29227c6a 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/DefaultTagFinder.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics.publish.spectator;
+package org.apache.servicecomb.foundation.metrics.publish;
 
 
 import io.micrometer.core.instrument.Tag;
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementGroupConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementGroupConfig.java
similarity index 95%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementGroupConfig.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementGroupConfig.java
index 0942baf26..cec6db25e 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementGroupConfig.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementGroupConfig.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics.publish.spectator;
+package org.apache.servicecomb.foundation.metrics.publish;
 
 import java.util.Arrays;
 import java.util.HashMap;
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementNode.java
similarity index 97%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementNode.java
index b357f758e..8ff19a153 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementNode.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics.publish.spectator;
+package org.apache.servicecomb.foundation.metrics.publish;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
similarity index 98%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
index c372a3304..440900e4f 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics.publish.spectator;
+package org.apache.servicecomb.foundation.metrics.publish;
 
 import java.util.ArrayList;
 import java.util.Iterator;
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/TagFinder.java
similarity index 95%
rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java
rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/TagFinder.java
index a3c893b4b..e1f3c8b40 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/TagFinder.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.foundation.metrics.publish.spectator;
+package org.apache.servicecomb.foundation.metrics.publish;
 
 import io.micrometer.core.instrument.Tag;
 
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
deleted file mode 100644
index 453c86495..000000000
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java
+++ /dev/null
@@ -1,34 +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.servicecomb.foundation.metrics.registry;
-
-import org.apache.servicecomb.foundation.metrics.PolledEvent;
-
-import io.micrometer.core.instrument.MeterRegistry;
-
-
-public class GlobalRegistry {
-  private final MeterRegistry meterRegistry;
-
-  public GlobalRegistry(MeterRegistry meterRegistry) {
-    this.meterRegistry = meterRegistry;
-  }
-
-  public PolledEvent poll(long secondInterval) {
-    return new PolledEvent(this.meterRegistry.getMeters());
-  }
-}
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
index 02deb078b..231b0099e 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java
@@ -39,7 +39,7 @@ import io.micrometer.core.instrument.MeterRegistry;
 import mockit.Deencapsulation;
 
 public class TestMetricsBootstrap {
-  MetricsBootstrap bootstrap = new MetricsBootstrap();
+  MetricsBootstrap bootstrap;
 
   EventBus eventBus = new EventBus();
 
@@ -47,13 +47,15 @@ public class TestMetricsBootstrap {
 
   @BeforeEach
   public void setUp() {
-    bootstrap.setMetricsInitializers(List.of());
     Mockito.when(environment.getProperty(METRICS_WINDOW_TIME, int.class, DEFAULT_METRICS_WINDOW_TIME))
         .thenReturn(DEFAULT_METRICS_WINDOW_TIME);
     Mockito.when(environment.getProperty(
             CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7))
         .thenReturn(7);
-    bootstrap.setEnvironment(environment);
+
+    MetricsBootstrapConfig config = new MetricsBootstrapConfig(environment);
+    bootstrap = new MetricsBootstrap(config);
+    bootstrap.setMetricsInitializers(List.of());
   }
 
   @Test
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java
index cc9dcadcc..46220069b 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java
@@ -19,6 +19,8 @@ package org.apache.servicecomb.foundation.metrics.publish.spectator;
 import java.util.Arrays;
 import java.util.List;
 
+import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder;
+import org.apache.servicecomb.foundation.metrics.publish.TagFinder;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java
index 033740096..b46373867 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java
@@ -19,6 +19,8 @@ package org.apache.servicecomb.foundation.metrics.publish.spectator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.TagFinder;
 import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java
index a366cee54..be7681ae5 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.foundation.metrics.publish.spectator;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.Test;
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
index 44037f7a3..d21354be5 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
@@ -18,6 +18,10 @@ package org.apache.servicecomb.foundation.metrics.publish.spectator;
 
 import java.util.concurrent.TimeUnit;
 
+import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java
index a4c40320e..2a0d96063 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java
@@ -16,6 +16,8 @@
  */
 package org.apache.servicecomb.foundation.metrics.publish.spectator;
 
+import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder;
+import org.apache.servicecomb.foundation.metrics.publish.TagFinder;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
index 5d1dc7f60..f0e05ae00 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
@@ -16,23 +16,50 @@
  */
 package org.apache.servicecomb.metrics.core;
 
+import java.time.Duration;
+
 import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrap;
+import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.metrics.core.publish.DefaultLogPublisher;
 import org.apache.servicecomb.metrics.core.publish.SlowInvocationLogger;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+import io.micrometer.core.instrument.Clock;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.CountingMode;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 
 @Configuration
 public class MetricsCoreConfiguration {
+  @Bean
+  public MetricsBootstrapConfig metricsBootstrapConfig(Environment environment) {
+    return new MetricsBootstrapConfig(environment);
+  }
+
+  @Bean
+  public MeterRegistry meterRegistry(MetricsBootstrapConfig config) {
+    return new SimpleMeterRegistry(s -> {
+      if ("simple.step".equals(s)) {
+        return Duration.ofMillis(config.getMsPollInterval()).toString();
+      }
+      if ("simple.mode".equals(s)) {
+        return CountingMode.STEP.name();
+      }
+      return null;
+    }, Clock.SYSTEM);
+  }
+
   @Bean
   public MetricsBootListener metricsBootListener(MetricsBootstrap metricsBootstrap) {
     return new MetricsBootListener(metricsBootstrap);
   }
 
   @Bean
-  public MetricsBootstrap metricsBootstrap() {
-    return new MetricsBootstrap();
+  public MetricsBootstrap metricsBootstrap(MetricsBootstrapConfig config) {
+    return new MetricsBootstrap(config);
   }
 
   // Begin MetricsInitializers
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
index d6b7fb7bf..003989087 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
@@ -18,8 +18,8 @@ package org.apache.servicecomb.metrics.core.meter;
 
 import java.util.Map;
 
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.ThreadPoolMetersInitializer;
 import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel;
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java
index d5d478b0b..cba8e334c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/AbstractMeasurementNodeLogPublisher.java
@@ -16,8 +16,8 @@
  */
 package org.apache.servicecomb.metrics.core.publish;
 
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 
 public abstract class AbstractMeasurementNodeLogPublisher {
   protected StringBuilder sb;
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ClientEndpointsLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ClientEndpointsLogPublisher.java
index 57958ef9b..0669283fc 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ClientEndpointsLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ClientEndpointsLogPublisher.java
@@ -22,8 +22,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.servicecomb.foundation.common.net.NetUtils;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import org.apache.servicecomb.metrics.core.meter.vertx.EndpointMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.HttpClientEndpointMeter;
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index 4d7ae9954..ba0679e8d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -29,8 +29,8 @@ import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
 import org.apache.servicecomb.foundation.metrics.meter.LatencyDistributionConfig;
 import org.apache.servicecomb.foundation.metrics.meter.LatencyScopeConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
 import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
index 6554fc936..db5e43404 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
@@ -18,10 +18,10 @@ package org.apache.servicecomb.metrics.core.publish;
 
 import java.util.List;
 
-import org.apache.servicecomb.foundation.metrics.publish.spectator.DefaultTagFinder;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
index 94b9c43ab..8f883b5a8 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
@@ -19,7 +19,7 @@ package org.apache.servicecomb.metrics.core.publish;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup;
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ServerEndpointsLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ServerEndpointsLogPublisher.java
index 0e1ae12f4..115e96600 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ServerEndpointsLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/ServerEndpointsLogPublisher.java
@@ -19,8 +19,8 @@ package org.apache.servicecomb.metrics.core.publish;
 import static org.apache.servicecomb.foundation.common.utils.StringBuilderUtils.appendLine;
 
 import org.apache.servicecomb.foundation.common.net.NetUtils;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
 import org.apache.servicecomb.metrics.core.meter.vertx.EndpointMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.ServerEndpointMeter;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
index 16f9b67ad..8705f89d1 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
@@ -26,9 +26,8 @@ import org.apache.servicecomb.core.CoreConst;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.junit.Assert;
@@ -50,8 +49,6 @@ public class TestInvocationMetersInitializer {
 
   MeterRegistry registry = new SimpleMeterRegistry();
 
-  GlobalRegistry globalRegistry = new GlobalRegistry(registry);
-
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
 
   @Mocked
@@ -104,8 +101,6 @@ public class TestInvocationMetersInitializer {
     eventBus.post(event);
     eventBus.post(event);
 
-    globalRegistry.poll(1);
-
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.getMeters().iterator(),
         new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME, "stage"));
@@ -231,8 +226,6 @@ public class TestInvocationMetersInitializer {
     eventBus.post(event);
     eventBus.post(event);
 
-    globalRegistry.poll(1);
-
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.getMeters().iterator(),
         new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME, "stage"));
@@ -372,8 +365,6 @@ public class TestInvocationMetersInitializer {
     eventBus.post(event);
     eventBus.post(event);
 
-    globalRegistry.poll(1);
-
     MeasurementTree tree = new MeasurementTree();
     tree.from(registry.getMeters().iterator(),
         new MeasurementGroupConfig(MeterInvocationConst.INVOCATION_NAME, "stage"));
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
index dba231e87..73afa85b9 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
@@ -31,8 +31,8 @@ import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.GroupExecutor;
 import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 import org.mockito.Mockito;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
index 60f54e3d7..33856505a 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestNetMeter.java
@@ -23,8 +23,8 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.os.net.InterfaceUsage;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
index 98863c911..ebbf6c399 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/meter/os/TestOsMeter.java
@@ -26,8 +26,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementGroupConfig;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.os.cpu.CpuUtils;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
index e0b1618e8..a18d2207d 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
@@ -30,8 +30,8 @@ import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.common.Holder;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.PolledEvent;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector;
 import org.apache.servicecomb.foundation.vertx.VertxUtils;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
index 535c28700..e96bed878 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
@@ -26,7 +26,6 @@ import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
-import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry;
 import org.apache.servicecomb.metrics.core.InvocationMetersInitializer;
 import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
@@ -47,8 +46,6 @@ public class TestInvocationPublishModelFactory {
 
   MeterRegistry meterRegistry = new SimpleMeterRegistry();
 
-  GlobalRegistry globalRegistry = new GlobalRegistry(meterRegistry);
-
   InvocationMetersInitializer invocationMetersInitializer = new InvocationMetersInitializer();
 
   Invocation invocation = Mockito.mock(Invocation.class);
@@ -73,7 +70,6 @@ public class TestInvocationPublishModelFactory {
     invocationMetersInitializer.init(meterRegistry, eventBus, new MetricsBootstrapConfig(environment));
     prepareInvocation();
 
-    globalRegistry.poll(1);
     PublishModelFactory factory = new PublishModelFactory(meterRegistry.getMeters());
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
index a540eb21b..7d98f7bff 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
@@ -21,8 +21,8 @@ import java.util.Map;
 
 import org.apache.servicecomb.core.CoreConst;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementTree;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup;
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
index 2a6247870..a9f87601d 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
@@ -20,7 +20,7 @@ import java.util.HashMap;
 import java.util.List;
 
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
-import org.apache.servicecomb.foundation.metrics.publish.spectator.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.PublishUtils;
 


(servicecomb-java-chassis) 08/11: [SCB-2838]using micrometer to replace spectator part6: thread pool and endpoint improvement

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 26b990fd5ce9b0a91e65379e892739bdbf7cb87d
Author: liubao <bi...@qq.com>
AuthorDate: Fri Dec 1 09:13:04 2023 +0800

    [SCB-2838]using micrometer to replace spectator part6: thread pool and endpoint improvement
---
 .../metrics/publish/MeasurementTree.java           |  31 +-
 .../publish/spectator/TestMeasurementTree.java     |   4 +-
 .../monitor/MetricsMonitorDataProvider.java        |  26 +-
 .../metrics/core/MetricsCoreConfiguration.java     |   2 +
 .../metrics/core/ThreadPoolMetersInitializer.java  |  54 +--
 .../ThreadPoolMonitorPublishModelFactory.java      |  52 ++-
 .../meter/invocation/AbstractInvocationMeter.java  |   3 +-
 .../meter/invocation/MeterInvocationConst.java     |   6 -
 .../metrics/core/meter/pool/ThreadPoolMeter.java   | 102 ++++++
 .../metrics/core/meter/vertx/EndpointMeter.java    |   2 +-
 .../metrics/core/publish/DefaultLogPublisher.java  |  55 ++-
 .../metrics/core/publish/PublishModelFactory.java  |  12 +-
 .../metrics/core/publish/PublishUtils.java         |  13 +-
 .../core/publish/model/invocation/PerfInfo.java    |  16 +-
 .../core/TestInvocationMetersInitializer.java      | 100 +++---
 .../core/TestThreadPoolMetersInitializer.java      |  30 +-
 .../core/publish/TestDefaultLogPublisher.java      |  17 +-
 .../publish/TestInvocationPublishModelFactory.java | 372 ++++++++++-----------
 .../metrics/core/publish/TestPublishUtils.java     |  27 +-
 .../publish/TestThreadPoolPublishModelFactory.java |   7 +-
 .../model/invocation/TestOperationPerf.java        |  12 +-
 .../model/invocation/TestOperationPerfGroup.java   |  12 +-
 .../publish/model/invocation/TestPerfInfo.java     |  16 +-
 .../core/publish/model/invocation/Utils.java       |   3 +-
 24 files changed, 521 insertions(+), 453 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
index 440900e4f..88e6eda69 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java
@@ -17,8 +17,10 @@
 package org.apache.servicecomb.foundation.metrics.publish;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
+import java.util.concurrent.TimeUnit;
 
 import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.Meter;
@@ -46,28 +48,35 @@ public class MeasurementTree extends MeasurementNode {
   // only id name exists in groupConfig will accept, others will be ignored
   public void from(Iterator<Meter> meters, MeasurementGroupConfig groupConfig) {
     meters.forEachRemaining(meter -> {
-      Iterable<Measurement> measurements = meter.measure();
-      from(meter.getId(), measurements, groupConfig);
-
       // This code snip is not very good design. But timer is quite special.
-      if (meter instanceof Timer) {
-        HistogramSnapshot snapshot = ((Timer) meter).takeSnapshot();
+      if (meter instanceof Timer timer) {
+        HistogramSnapshot snapshot = timer.takeSnapshot();
+        List<Measurement> summary = Arrays.asList(new Measurement(snapshot::count, Statistic.COUNT),
+            new Measurement(() -> snapshot.total(TimeUnit.MILLISECONDS), Statistic.TOTAL_TIME),
+            new Measurement(() -> snapshot.max(TimeUnit.MILLISECONDS), Statistic.MAX));
+        from(meter.getId(), summary, groupConfig);
+
         CountAtBucket[] countAtBuckets = snapshot.histogramCounts();
         if (countAtBuckets.length > 2) {
-          List<Measurement> latency = new ArrayList<>(countAtBuckets.length);
+          List<Measurement> distributions = new ArrayList<>(countAtBuckets.length);
           for (int i = 0; i < countAtBuckets.length; i++) {
             final int index = i;
             if (index == 0) {
-              latency.add(new Measurement(() -> countAtBuckets[index].count(),
-                  Statistic.VALUE));
+              distributions.add(new Measurement(() -> countAtBuckets[index].count(),
+                  Statistic.COUNT));
               continue;
             }
-            latency.add(new Measurement(() -> countAtBuckets[index].count() - countAtBuckets[index - 1].count(),
-                Statistic.VALUE));
+            distributions.add(new Measurement(() -> countAtBuckets[index].count() - countAtBuckets[index - 1].count(),
+                Statistic.COUNT));
           }
-          from(meter.getId().withTag(Tag.of(TAG_TYPE, TAG_LATENCY_DISTRIBUTION)), latency, groupConfig);
+
+          from(meter.getId().withTag(Tag.of(TAG_TYPE, TAG_LATENCY_DISTRIBUTION)), distributions, groupConfig);
         }
+        return;
       }
+
+      Iterable<Measurement> measurements = meter.measure();
+      from(meter.getId(), measurements, groupConfig);
     });
   }
 
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
index d21354be5..234147a1f 100644
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
+++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java
@@ -54,8 +54,8 @@ public class TestMeasurementTree {
 
   @Test
   public void from() {
-    timer.record(10, TimeUnit.SECONDS);
-    timer.record(2, TimeUnit.SECONDS);
+    timer.record(10, TimeUnit.MILLISECONDS);
+    timer.record(2, TimeUnit.MILLISECONDS);
 
     MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2");
     tree.from(registry.getMeters().iterator(), config);
diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java
index 4829fb22a..ed54eef34 100644
--- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java
+++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java
@@ -140,16 +140,16 @@ public class MetricsMonitorDataProvider implements MonitorDataProvider {
               });
           // dashboard calculates the latest 10 seconds, different with metrics cycle.
           interfaceInfo.setTotal(
-              doubleToInt(interfaceInfo.getTotal() + 10 * stageTotal.getTps()));
+              doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests()));
           if (perfGroup.getStatus().matches(CODE_SUCCESS)) {
-            interfaceInfo.setQps(stageTotal.getTps());
+            interfaceInfo.setQps(stageTotal.getTotalRequests() / 10);
             interfaceInfo.setLatency(doubleToInt(stageTotal.calcMsLatency()));
           } else {
             interfaceInfo.setFailure(
-                doubleToInt(interfaceInfo.getTotal() + stageTotal.getMsTotalTime() * stageTotal.getTps()));
+                doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests()));
             if (perfGroup.getStatus().equals(CODE_TIMEOUT)) {
               interfaceInfo.setCountTimeout(
-                  doubleToInt(interfaceInfo.getCountTimeout() + stageTotal.getMsTotalTime() * stageTotal.getTps()));
+                  doubleToInt(interfaceInfo.getCountTimeout() + stageTotal.getTotalRequests()));
             }
           }
         }
@@ -176,16 +176,17 @@ public class MetricsMonitorDataProvider implements MonitorDataProvider {
               });
           // dashboard calculates the latest 10 seconds, different with metrics cycle.
           interfaceInfo.setTotal(
-              doubleToInt(interfaceInfo.getTotal() + 10 * stageTotal.getTps()));
+              doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests()));
           if (perfGroup.getStatus().matches(CODE_SUCCESS)) {
-            interfaceInfo.setQps(stageTotal.getTps());
+            interfaceInfo.setQps(stageTotal.getTotalRequests() / 10);
             interfaceInfo.setLatency(doubleToInt(stageTotal.calcMsLatency()));
           } else {
             interfaceInfo.setFailure(
-                doubleToInt(interfaceInfo.getTotal() + stageTotal.getMsTotalTime() * stageTotal.getTps()));
+                doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests()));
             if (perfGroup.getStatus().equals(CODE_TIMEOUT)) {
               interfaceInfo.setCountTimeout(
-                  doubleToInt(interfaceInfo.getCountTimeout() + stageTotal.getMsTotalTime() * stageTotal.getTps()));
+                  doubleToInt(
+                      interfaceInfo.getCountTimeout() + stageTotal.getTotalRequests()));
             }
           }
         }
@@ -212,16 +213,17 @@ public class MetricsMonitorDataProvider implements MonitorDataProvider {
               });
           // dashboard calculates the latest 10 seconds, different with metrics cycle.
           interfaceInfo.setTotal(
-              doubleToInt(interfaceInfo.getTotal() + 10 * stageTotal.getTps()));
+              doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests()));
           if (perfGroup.getStatus().matches(CODE_SUCCESS)) {
-            interfaceInfo.setQps(stageTotal.getTps());
+            interfaceInfo.setQps(stageTotal.getTotalRequests() / 10);
             interfaceInfo.setLatency(doubleToInt(stageTotal.calcMsLatency()));
           } else {
             interfaceInfo.setFailure(
-                doubleToInt(interfaceInfo.getTotal() + stageTotal.getMsTotalTime() * stageTotal.getTps()));
+                doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests()));
             if (perfGroup.getStatus().equals(CODE_TIMEOUT)) {
               interfaceInfo.setCountTimeout(
-                  doubleToInt(interfaceInfo.getCountTimeout() + stageTotal.getMsTotalTime() * stageTotal.getTps()));
+                  doubleToInt(
+                      interfaceInfo.getCountTimeout() + stageTotal.getTotalRequests()));
             }
           }
         }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
index f0e05ae00..661fc7a1d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/MetricsCoreConfiguration.java
@@ -23,6 +23,7 @@ import org.apache.servicecomb.foundation.metrics.MetricsBootstrap;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.metrics.core.publish.DefaultLogPublisher;
 import org.apache.servicecomb.metrics.core.publish.SlowInvocationLogger;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.core.env.Environment;
@@ -40,6 +41,7 @@ public class MetricsCoreConfiguration {
   }
 
   @Bean
+  @ConditionalOnMissingBean
   public MeterRegistry meterRegistry(MetricsBootstrapConfig config) {
     return new SimpleMeterRegistry(s -> {
       if ("simple.step".equals(s)) {
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
index a2a307b4a..9ada12258 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/ThreadPoolMetersInitializer.java
@@ -16,6 +16,7 @@
  */
 package org.apache.servicecomb.metrics.core;
 
+import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -26,37 +27,21 @@ import org.apache.servicecomb.core.SCBEngine;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.executor.GroupExecutor;
-import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
 import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
+import org.apache.servicecomb.metrics.core.meter.pool.ThreadPoolMeter;
 
 import com.google.common.eventbus.EventBus;
 
-import io.micrometer.core.instrument.Gauge;
 import io.micrometer.core.instrument.MeterRegistry;
 
-public class ThreadPoolMetersInitializer implements MetricsInitializer {
-  public static final String ID = "id";
-
-  public static final String REJECTED_COUNT = "threadpool.rejectedCount";
-
-  public static final String TASK_COUNT = "threadpool.taskCount";
-
-  public static final String COMPLETED_TASK_COUNT = "threadpool.completedTaskCount";
-
-  public static final String CURRENT_THREADS_BUSY = "threadpool.currentThreadsBusy";
-
-  public static final String MAX_THREADS = "threadpool.maxThreads";
-
-  public static final String POOL_SIZE = "threadpool.poolSize";
-
-  public static final String CORE_POOL_SIZE = "threadpool.corePoolSize";
-
-  public static final String QUEUE_SIZE = "threadpool.queueSize";
-
+public class ThreadPoolMetersInitializer implements MetricsInitializer, PeriodMeter {
   private MeterRegistry meterRegistry;
 
+  private Map<String, ThreadPoolMeter> threadPoolMeters = new HashMap<>();
+
   @Override
   public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
     this.meterRegistry = meterRegistry;
@@ -106,25 +91,12 @@ public class ThreadPoolMetersInitializer implements MetricsInitializer {
       return;
     }
 
-    Gauge.builder(TASK_COUNT, threadPoolExecutor::getTaskCount).tags(ID, threadPoolName)
-        .register(meterRegistry);
-    Gauge.builder(COMPLETED_TASK_COUNT, threadPoolExecutor::getCompletedTaskCount).tags(ID, threadPoolName)
-        .register(meterRegistry);
-    Gauge.builder(CURRENT_THREADS_BUSY, threadPoolExecutor::getActiveCount).tags(ID, threadPoolName)
-        .register(meterRegistry);
-    Gauge.builder(MAX_THREADS, threadPoolExecutor::getMaximumPoolSize).tags(ID, threadPoolName)
-        .register(meterRegistry);
-    Gauge.builder(POOL_SIZE, threadPoolExecutor::getPoolSize).tags(ID, threadPoolName)
-        .register(meterRegistry);
-    Gauge.builder(CORE_POOL_SIZE, threadPoolExecutor::getCorePoolSize).tags(ID, threadPoolName)
-        .register(meterRegistry);
-    Gauge.builder(QUEUE_SIZE, () -> threadPoolExecutor.getQueue().size()).tags(ID, threadPoolName)
-        .register(meterRegistry);
-
-    if (executor instanceof ThreadPoolExecutorEx) {
-      Gauge.builder(REJECTED_COUNT, () -> ((ThreadPoolExecutorEx) (executor)).getRejectedCount())
-          .tags(ID, threadPoolName)
-          .register(meterRegistry);
-    }
+    threadPoolMeters.computeIfAbsent(threadPoolName,
+        (key) -> new ThreadPoolMeter(meterRegistry, threadPoolName, threadPoolExecutor));
+  }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    threadPoolMeters.forEach((key, value) -> value.poll(msNow, secondInterval));
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
index 003989087..d0474142c 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/ThreadPoolMonitorPublishModelFactory.java
@@ -16,11 +16,12 @@
  */
 package org.apache.servicecomb.metrics.core.meter;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
-import org.apache.servicecomb.metrics.core.ThreadPoolMetersInitializer;
+import org.apache.servicecomb.metrics.core.meter.pool.ThreadPoolMeter;
 import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel;
 
 import io.micrometer.core.instrument.Measurement;
@@ -30,54 +31,41 @@ public class ThreadPoolMonitorPublishModelFactory {
     void set(ThreadPoolPublishModel model, Measurement measurement);
   }
 
-  private final MeasurementTree tree;
-
-  private final Map<String, ThreadPoolPublishModel> threadPools;
-
-  public ThreadPoolMonitorPublishModelFactory(MeasurementTree tree,
-      Map<String, ThreadPoolPublishModel> threadPools) {
-    this.tree = tree;
-    this.threadPools = threadPools;
-  }
-
-  public static void create(MeasurementTree tree,
-      Map<String, ThreadPoolPublishModel> threadPools) {
-    new ThreadPoolMonitorPublishModelFactory(tree, threadPools).create();
-  }
-
-  public void create() {
-    readMeasurement(ThreadPoolMetersInitializer.TASK_COUNT,
+  public static Map<String, ThreadPoolPublishModel> create(MeasurementTree tree) {
+    Map<String, ThreadPoolPublishModel> result = new HashMap<>(8);
+    readMeasurement(result, tree, ThreadPoolMeter.TASK_COUNT,
         (model, measurement) -> model.setAvgTaskCount(measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.COMPLETED_TASK_COUNT,
+    readMeasurement(result, tree, ThreadPoolMeter.COMPLETED_TASK_COUNT,
         (model, measurement) -> model.setAvgCompletedTaskCount(measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.CURRENT_THREADS_BUSY,
+    readMeasurement(result, tree, ThreadPoolMeter.CURRENT_THREADS_BUSY,
         (model, measurement) -> model.setCurrentThreadsBusy((int) measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.MAX_THREADS,
+    readMeasurement(result, tree, ThreadPoolMeter.MAX_THREADS,
         (model, measurement) -> model.setMaxThreads((int) measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.POOL_SIZE,
+    readMeasurement(result, tree, ThreadPoolMeter.POOL_SIZE,
         (model, measurement) -> model.setPoolSize((int) measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.CORE_POOL_SIZE,
+    readMeasurement(result, tree, ThreadPoolMeter.CORE_POOL_SIZE,
         (model, measurement) -> model.setCorePoolSize((int) measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.QUEUE_SIZE,
+    readMeasurement(result, tree, ThreadPoolMeter.QUEUE_SIZE,
         (model, measurement) -> model.setQueueSize((int) measurement.getValue()));
-    readMeasurement(ThreadPoolMetersInitializer.REJECTED_COUNT,
+    readMeasurement(result, tree, ThreadPoolMeter.REJECTED_COUNT,
         (model, measurement) -> model.setRejected(measurement.getValue()));
+    return result;
   }
 
-  protected void readMeasurement(String name, Setter setter) {
-    MeasurementNode node = tree.findChild(name);
+  protected static void readMeasurement(Map<String, ThreadPoolPublishModel> threadPools, MeasurementTree tree,
+      String name, Setter setter) {
+    MeasurementNode node = tree.findChild(ThreadPoolMeter.THREAD_POOL_METER);
     if (node == null) {
       return;
     }
 
-    for (Measurement measurement : node.getMeasurements()) {
-      String threadPoolName = node.getId().getTag(ThreadPoolMetersInitializer.ID);
-      if (threadPoolName == null) {
+    for (String threadPoolName : node.getChildren().keySet()) {
+      MeasurementNode measure = node.findChild(threadPoolName, name);
+      if (measure == null) {
         continue;
       }
-
       ThreadPoolPublishModel model = threadPools.computeIfAbsent(threadPoolName, tpn -> new ThreadPoolPublishModel());
-      setter.set(model, measurement);
+      setter.set(model, measure.getMeasurements().get(0));
     }
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
index bf7bb0429..1ced47feb 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/AbstractInvocationMeter.java
@@ -46,7 +46,8 @@ public abstract class AbstractInvocationMeter {
         .tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE,
             MeterInvocationConst.TAG_STAGE, InvocationStageTrace.STAGE_TOTAL));
     if (!StringUtils.isEmpty(metricsBootstrapConfig.getLatencyDistribution())) {
-      totalBuilder.sla(toDuration(metricsBootstrapConfig.getLatencyDistribution()));
+      totalBuilder.sla(toDuration(metricsBootstrapConfig.getLatencyDistribution()))
+          .distributionStatisticExpiry(Duration.ofMillis(metricsBootstrapConfig.getMsPollInterval()));
     }
     this.totalTimer = totalBuilder.register(meterRegistry);
     this.prepareTimer = Timer.builder(name).tags(tags.and(MeterInvocationConst.TAG_TYPE, MeterInvocationConst.TAG_STAGE
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
index fd5d53f9e..fac87d55e 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/invocation/MeterInvocationConst.java
@@ -16,8 +16,6 @@
  */
 package org.apache.servicecomb.metrics.core.meter.invocation;
 
-import io.micrometer.core.instrument.Statistic;
-
 public interface MeterInvocationConst {
   String INVOCATION_NAME = "servicecomb.invocation";
 
@@ -32,11 +30,7 @@ public interface MeterInvocationConst {
 
   String TAG_STAGE = "stage";
 
-  String TAG_LATENCY_DISTRIBUTION = "latencyDistribution";
-
   String TAG_STATUS = "status";
 
-  String TAG_STATISTIC = Statistic.COUNT.name();
-
   String EDGE_INVOCATION_NAME = "EDGE";
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/pool/ThreadPoolMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/pool/ThreadPoolMeter.java
new file mode 100644
index 000000000..1267bc53e
--- /dev/null
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/pool/ThreadPoolMeter.java
@@ -0,0 +1,102 @@
+/*
+ * 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.servicecomb.metrics.core.meter.pool;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
+import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter;
+
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
+
+public class ThreadPoolMeter implements PeriodMeter {
+  public static final String THREAD_POOL_METER = "servicecomb.threadpool";
+
+  public static final String ID = "id";
+
+  public static final String STAGE = "stage";
+
+  public static final String REJECTED_COUNT = "rejectedCount";
+
+  public static final String TASK_COUNT = "taskCount";
+
+  public static final String COMPLETED_TASK_COUNT = "completedTaskCount";
+
+  public static final String CURRENT_THREADS_BUSY = "currentThreadsBusy";
+
+  public static final String MAX_THREADS = "maxThreads";
+
+  public static final String POOL_SIZE = "poolSize";
+
+  public static final String CORE_POOL_SIZE = "corePoolSize";
+
+  public static final String QUEUE_SIZE = "queueSize";
+
+  private final ThreadPoolExecutor threadPoolExecutor;
+
+  private long currentTask;
+
+  private long lastTask;
+
+  private long currentCompletedTask;
+
+  private long lastCompletedTask;
+
+  public ThreadPoolMeter(MeterRegistry meterRegistry, String threadPoolName, ThreadPoolExecutor threadPoolExecutor) {
+    this.threadPoolExecutor = threadPoolExecutor;
+
+    Gauge.builder(THREAD_POOL_METER, () -> currentTask)
+        .tags(ID, threadPoolName, STAGE, TASK_COUNT)
+        .register(meterRegistry);
+    Gauge.builder(THREAD_POOL_METER, () -> currentCompletedTask)
+        .tags(ID, threadPoolName, STAGE, COMPLETED_TASK_COUNT)
+        .register(meterRegistry);
+    Gauge.builder(THREAD_POOL_METER, threadPoolExecutor::getActiveCount)
+        .tags(ID, threadPoolName, STAGE, CURRENT_THREADS_BUSY)
+        .register(meterRegistry);
+    Gauge.builder(THREAD_POOL_METER, threadPoolExecutor::getMaximumPoolSize)
+        .tags(ID, threadPoolName, STAGE, MAX_THREADS)
+        .register(meterRegistry);
+    Gauge.builder(THREAD_POOL_METER, threadPoolExecutor::getPoolSize)
+        .tags(ID, threadPoolName, STAGE, POOL_SIZE)
+        .register(meterRegistry);
+    Gauge.builder(THREAD_POOL_METER, threadPoolExecutor::getCorePoolSize)
+        .tags(ID, threadPoolName, STAGE, CORE_POOL_SIZE)
+        .register(meterRegistry);
+    Gauge.builder(THREAD_POOL_METER, () -> threadPoolExecutor.getQueue().size())
+        .tags(ID, threadPoolName, STAGE, QUEUE_SIZE)
+        .register(meterRegistry);
+
+    if (threadPoolExecutor instanceof ThreadPoolExecutorEx) {
+      Gauge.builder(THREAD_POOL_METER, () -> ((ThreadPoolExecutorEx) (threadPoolExecutor)).getRejectedCount())
+          .tags(ID, threadPoolName, STAGE, REJECTED_COUNT)
+          .register(meterRegistry);
+    }
+  }
+
+  @Override
+  public void poll(long msNow, long secondInterval) {
+    long temp = threadPoolExecutor.getTaskCount();
+    currentTask = temp - lastTask;
+    lastTask = temp;
+
+    temp = threadPoolExecutor.getCompletedTaskCount();
+    currentCompletedTask = temp - lastCompletedTask;
+    lastCompletedTask = temp;
+  }
+}
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
index f00cf22e0..b758dbebf 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
@@ -104,7 +104,7 @@ public class EndpointMeter implements PeriodMeter {
     disconnectCount = Gauge.builder(name, () -> currentDisconnectCount)
         .tags(tags.and(Tag.of(STATISTIC, DISCONNECT_COUNT)))
         .register(meterRegistry);
-    connections = Gauge.builder(name, () -> currentConnectCount - currentDisconnectCount)
+    connections = Gauge.builder(name, () -> this.metric.getConnectCount() - this.metric.getDisconnectCount())
         .tags(tags.and(Tag.of(STATISTIC, CONNECTIONS)))
         .register(meterRegistry);
     bytesRead = Gauge.builder(name, () -> currentBytesRead)
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index ba0679e8d..feaee2e22 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -62,7 +62,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
   // for a client, maybe will connect to too many endpoints, so default not print detail, just print summary
   public static final String ENDPOINTS_CLIENT_DETAIL_ENABLED = "servicecomb.metrics.publisher.defaultLog.endpoints.client.detail.enabled";
 
-  private static final String FIRST_LINE_SIMPLE_FORMAT = "  %-11s %-8.1f %-18s %s%s\n";
+  private static final String FIRST_LINE_SIMPLE_FORMAT = "  %-11s\n";
 
   private static final String SIMPLE_FORMAT = "              %-8.1f %-18s %s%s\n";
 
@@ -243,7 +243,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
     sb.append(""
             + "edge:\n"
             + " simple:\n"
-            + "  status      tps      latency            ")
+            + "  status      requests      latency       ")
         .append(latencyDistributionHeader)
         .append("operation\n");
     StringBuilder detailsBuilder = new StringBuilder();
@@ -267,7 +267,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
     sb.append(""
             + "consumer:\n"
             + " simple:\n"
-            + "  status      tps      latency            ")
+            + "  status      requests      latency       ")
         .append(latencyDistributionHeader)
         .append("operation\n");
     StringBuilder detailsBuilder = new StringBuilder();
@@ -291,7 +291,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
     sb.append(""
             + "producer:\n"
             + " simple:\n"
-            + "  status      tps      latency            ")
+            + "  status      requests      latency       ")
         .append(latencyDistributionHeader)
         .append("operation\n");
     // use detailsBuilder, we can traverse the map only once
@@ -311,32 +311,24 @@ public class DefaultLogPublisher implements MetricsInitializer {
 
   private StringBuilder printSamplePerf(OperationPerfGroup perfGroup) {
     StringBuilder sb = new StringBuilder();
-    boolean firstLine = true;
+    String status = perfGroup.getTransport() + "." + perfGroup.getStatus() + ":";
+    sb.append(String.format(FIRST_LINE_SIMPLE_FORMAT, status));
+
     for (int i = 0; i < perfGroup.getOperationPerfs().size(); i++) {
       OperationPerf operationPerf = perfGroup.getOperationPerfs().get(i);
-      PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
-      if (Double.compare(0D, stageTotal.getTps()) == 0) {
+      if (isIngoreEmptyPerf(operationPerf)) {
         continue;
       }
-      if (firstLine) {
-        firstLine = false;
-        String status = perfGroup.getTransport() + "." + perfGroup.getStatus();
-        sb.append(String.format(FIRST_LINE_SIMPLE_FORMAT, status,
-            stageTotal.getTps(),
-            getDetailsFromPerf(stageTotal),
-            formatLatencyDistribution(operationPerf),
-            operationPerf.getOperation()));
-      } else {
-        sb.append(String.format(SIMPLE_FORMAT, stageTotal.getTps(),
-            getDetailsFromPerf(stageTotal),
-            formatLatencyDistribution(operationPerf),
-            operationPerf.getOperation()));
-      }
+      PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
+      sb.append(String.format(SIMPLE_FORMAT, stageTotal.getTotalRequests(),
+          getDetailsFromPerf(stageTotal),
+          formatLatencyDistribution(operationPerf),
+          operationPerf.getOperation()));
     }
     OperationPerf summaryOperation = perfGroup.getSummary();
     PerfInfo stageSummaryTotal = summaryOperation.findStage(InvocationStageTrace.STAGE_TOTAL);
     //print summary
-    sb.append(String.format(SIMPLE_FORMAT, stageSummaryTotal.getTps(),
+    sb.append(String.format(SIMPLE_FORMAT, stageSummaryTotal.getTotalRequests(),
         getDetailsFromPerf(stageSummaryTotal),
         formatLatencyDistribution(summaryOperation),
         "(summary)"));
@@ -357,8 +349,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
         .append(":\n");
     PerfInfo prepare, queue, providerDecode, providerEncode, execute, sendResp;
     for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
-      PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
-      if (Double.compare(0D, stageTotal.getTps()) == 0) {
+      if (isIngoreEmptyPerf(operationPerf)) {
         continue;
       }
       prepare = operationPerf.findStage(InvocationStageTrace.STAGE_PREPARE);
@@ -396,8 +387,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
     PerfInfo prepare, encodeRequest, decodeResponse, sendReq, getConnect,
         waitResp;
     for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
-      PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
-      if (Double.compare(0D, stageTotal.getTps()) == 0) {
+      if (isIngoreEmptyPerf(operationPerf)) {
         continue;
       }
       prepare = operationPerf.findStage(InvocationStageTrace.STAGE_PREPARE);
@@ -436,8 +426,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
         encodeConsumerRequest, decodeConsumerResponse, sendReq, getConnect,
         waitResp, sendResp;
     for (OperationPerf operationPerf : perfGroup.getOperationPerfs()) {
-      PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
-      if (Double.compare(0D, stageTotal.getTps()) == 0) {
+      if (isIngoreEmptyPerf(operationPerf)) {
         continue;
       }
       prepare = operationPerf.findStage(InvocationStageTrace.STAGE_PREPARE);
@@ -469,6 +458,16 @@ public class DefaultLogPublisher implements MetricsInitializer {
     return sb;
   }
 
+  private boolean isIngoreEmptyPerf(OperationPerf operationPerf) {
+    PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
+    // max latency is calculated in ring algorithm, maybe not 0
+    if (Double.compare(0D, stageTotal.getTotalRequests()) == 0
+        && Double.compare(0D, stageTotal.getMsMaxLatency()) == 0) {
+      return true;
+    }
+    return false;
+  }
+
   protected void printVertxMetrics(MeasurementTree tree, StringBuilder sb) {
     appendLine(sb, "vertx:");
 
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
index db5e43404..5baa2917e 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishModelFactory.java
@@ -23,16 +23,16 @@ import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.VertxMetersInitializer;
+import org.apache.servicecomb.metrics.core.meter.ThreadPoolMonitorPublishModelFactory;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.meter.os.NetMeter;
 import org.apache.servicecomb.metrics.core.meter.os.OsMeter;
+import org.apache.servicecomb.metrics.core.meter.pool.ThreadPoolMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.EndpointMeter;
 import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 
-import org.apache.servicecomb.metrics.core.meter.ThreadPoolMonitorPublishModelFactory;
-
 import io.micrometer.core.instrument.Meter;
 
 public class PublishModelFactory {
@@ -64,7 +64,6 @@ public class PublishModelFactory {
         MeterInvocationConst.TAG_TYPE,
         new DefaultTagFinder(MeterInvocationConst.TAG_STAGE, true));
 
-    //os config
     groupConfig.addGroup(OsMeter.OS_NAME,
         OsMeter.OS_TYPE,
         new DefaultTagFinder(NetMeter.INTERFACE, true));
@@ -73,6 +72,9 @@ public class PublishModelFactory {
         VertxMetersInitializer.ENDPOINTS_TYPE,
         EndpointMeter.ADDRESS, EndpointMeter.STATISTIC);
 
+    groupConfig.addGroup(ThreadPoolMeter.THREAD_POOL_METER,
+        ThreadPoolMeter.ID, ThreadPoolMeter.STAGE);
+
     return groupConfig;
   }
 
@@ -106,11 +108,11 @@ public class PublishModelFactory {
 
     model.getProducer()
         .setOperationPerfGroups(generateOperationPerfGroups(tree, InvocationType.PROVIDER.name()));
-    //edge
+
     model.getEdge()
         .setOperationPerfGroups(generateOperationPerfGroups(tree, MeterInvocationConst.EDGE_INVOCATION_NAME));
 
-    ThreadPoolMonitorPublishModelFactory.create(tree, model.getThreadPools());
+    model.setThreadPools(ThreadPoolMonitorPublishModelFactory.create(tree));
 
     return model;
   }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
index 8f883b5a8..9bf2cb6f9 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/PublishUtils.java
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup;
@@ -34,13 +35,9 @@ public final class PublishUtils {
 
   public static PerfInfo createPerfInfo(MeasurementNode stageNode) {
     PerfInfo perfInfo = new PerfInfo();
-    perfInfo.setTps(stageNode.findChild(Statistic.COUNT.name()).summary());
-    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.TOTAL_TIME.name()).summary() * 1000);
-    // when UT with DefaultRegistry, there is no max value
-    MeasurementNode maxNode = stageNode.findChild(Statistic.MAX.name());
-    if (maxNode != null) {
-      perfInfo.setMsMaxLatency(maxNode.summary() * 1000);
-    }
+    perfInfo.setTotalRequests(stageNode.findChild(Statistic.COUNT.name()).summary());
+    perfInfo.setMsTotalTime(stageNode.findChild(Statistic.TOTAL_TIME.name()).summary());
+    perfInfo.setMsMaxLatency(stageNode.findChild(Statistic.MAX.name()).summary());
     return perfInfo;
   }
 
@@ -54,7 +51,7 @@ public final class PublishUtils {
       operationPerf.getStages().put(mNode.getName(), perfInfo);
     });
 
-    MeasurementNode latencyNode = statusNode.findChild(MeterInvocationConst.TAG_LATENCY_DISTRIBUTION);
+    MeasurementNode latencyNode = statusNode.findChild(MeasurementTree.TAG_LATENCY_DISTRIBUTION);
     if (latencyNode != null && latencyNode.getMeasurements() != null) {
       operationPerf.setLatencyDistribution(latencyNode.getMeasurements().stream()
           .map(m -> (int) m.getValue())
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/invocation/PerfInfo.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/invocation/PerfInfo.java
index fef78700c..e9e3afbee 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/invocation/PerfInfo.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/model/invocation/PerfInfo.java
@@ -17,18 +17,18 @@
 package org.apache.servicecomb.metrics.core.publish.model.invocation;
 
 public class PerfInfo {
-  private double tps;
+  private double totalRequests;
 
   private double msTotalTime;
 
   private double msMaxLatency;
 
-  public double getTps() {
-    return tps;
+  public double getTotalRequests() {
+    return totalRequests;
   }
 
-  public void setTps(double tps) {
-    this.tps = tps;
+  public void setTotalRequests(double totalRequests) {
+    this.totalRequests = totalRequests;
   }
 
   public double getMsTotalTime() {
@@ -48,7 +48,7 @@ public class PerfInfo {
   }
 
   public void add(PerfInfo other) {
-    tps += other.tps;
+    totalRequests += other.totalRequests;
     msTotalTime += other.msTotalTime;
     if (msMaxLatency < other.msMaxLatency) {
       msMaxLatency = other.msMaxLatency;
@@ -56,12 +56,12 @@ public class PerfInfo {
   }
 
   public double calcMsLatency() {
-    return (tps != 0) ? msTotalTime / tps : 0;
+    return (totalRequests != 0) ? msTotalTime / totalRequests : 0;
   }
 
   @Override
   public String toString() {
-    return "PerfInfo [tps=" + tps + ", msTotalTime=" + msTotalTime + ", msLatency=" + calcMsLatency()
+    return "PerfInfo [tps=" + totalRequests + ", msTotalTime=" + msTotalTime + ", msLatency=" + calcMsLatency()
         + ", msMaxLatency="
         + msMaxLatency + "]";
   }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
index 8705f89d1..09963b4e4 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestInvocationMetersInitializer.java
@@ -110,9 +110,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
         .getMeasurements();
@@ -120,9 +120,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-send")
         .getMeasurements();
@@ -130,9 +130,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.0E-8");
+        "statistic='TOTAL_TIME', value=1.0E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=5.0E-9");
+        "statistic='MAX', value=5.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
         .getMeasurements();
@@ -140,9 +140,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-encode")
         .getMeasurements();
@@ -151,9 +151,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=8.0E-9");
+        "statistic='TOTAL_TIME', value=8.0E-6");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=4.0E-9");
+        "statistic='MAX', value=4.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
         .getMeasurements();
@@ -161,9 +161,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "wait")
         .getMeasurements();
@@ -171,9 +171,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-decode")
         .getMeasurements();
@@ -181,9 +181,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
   }
 
   @Test
@@ -236,9 +236,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
         .getMeasurements();
@@ -246,9 +246,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-send")
         .getMeasurements();
@@ -256,9 +256,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.0E-8");
+        "statistic='TOTAL_TIME', value=1.0E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=5.0E-9");
+        "statistic='MAX', value=5.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "connection")
         .getMeasurements();
@@ -266,9 +266,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-encode")
         .getMeasurements();
@@ -276,9 +276,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=8.0E-9");
+        "statistic='TOTAL_TIME', value=8.0E-6");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=4.0E-9");
+        "statistic='MAX', value=4.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "wait")
         .getMeasurements();
@@ -286,9 +286,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "consumer-decode")
         .getMeasurements();
@@ -296,9 +296,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.6E-8");
+        "statistic='TOTAL_TIME', value=1.6E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=8.0E-9");
+        "statistic='MAX', value=8.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-decode")
         .getMeasurements();
@@ -306,9 +306,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-encode")
         .getMeasurements();
@@ -316,9 +316,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-send")
         .getMeasurements();
@@ -326,9 +326,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
   }
 
   @Test
@@ -375,9 +375,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "prepare")
         .getMeasurements();
@@ -385,9 +385,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "queue")
         .getMeasurements();
@@ -395,9 +395,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "execute")
         .getMeasurements();
@@ -405,9 +405,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-decode")
         .getMeasurements();
@@ -415,9 +415,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-encode")
         .getMeasurements();
@@ -425,9 +425,9 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
 
     measurements = tree.findChild(MeterInvocationConst.INVOCATION_NAME, "provider-send")
         .getMeasurements();
@@ -435,8 +435,8 @@ public class TestInvocationMetersInitializer {
     AssertUtil.assertMeasure(measurements, 0,
         "statistic='COUNT', value=2.0");
     AssertUtil.assertMeasure(measurements, 1,
-        "statistic='TOTAL_TIME', value=1.8E-8");
+        "statistic='TOTAL_TIME', value=1.8E-5");
     AssertUtil.assertMeasure(measurements, 2,
-        "statistic='MAX', value=9.0E-9");
+        "statistic='MAX', value=9.0E-6");
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
index 73afa85b9..9c9698aed 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestThreadPoolMetersInitializer.java
@@ -32,7 +32,9 @@ import org.apache.servicecomb.core.executor.GroupExecutor;
 import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.utils.BeanUtils;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
+import org.apache.servicecomb.metrics.core.meter.pool.ThreadPoolMeter;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 import org.mockito.Mockito;
@@ -127,22 +129,18 @@ public class TestThreadPoolMetersInitializer {
 
     MeasurementTree tree = new MeasurementTree();
     MeasurementGroupConfig group = new MeasurementGroupConfig();
-    group.addGroup("threadpool.maxThreads", "id");
-    group.addGroup("threadpool.rejectedCount", "id");
-    group.addGroup("threadpool.completedTaskCount", "id");
-    group.addGroup("threadpool.currentThreadsBusy", "id");
-    group.addGroup("threadpool.corePoolSize", "id");
-    group.addGroup("threadpool.poolSize", "id");
-    group.addGroup("threadpool.queueSize", "id");
-    group.addGroup("threadpool.taskCount", "id");
+    group.addGroup(ThreadPoolMeter.THREAD_POOL_METER, ThreadPoolMeter.ID,
+        ThreadPoolMeter.STAGE);
     tree.from(registry.getMeters().iterator(), group);
-    Assertions.assertEquals(tree.findChild("threadpool.maxThreads", "groupExecutor-group0").summary(), 0, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.rejectedCount", "groupExecutor-group0").summary(), 0, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.completedTaskCount", "groupExecutor-group0").summary(), 0, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.currentThreadsBusy", "groupExecutor-group0").summary(), 0, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.corePoolSize", "groupExecutor-group0").summary(), 0, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.poolSize", "groupExecutor-group0").summary(), 0, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.queueSize", "groupExecutor-group0").summary(), 10, 0);
-    Assertions.assertEquals(tree.findChild("threadpool.taskCount", "groupExecutor-group0").summary(), 0, 0);
+
+    MeasurementNode node = tree.findChild(ThreadPoolMeter.THREAD_POOL_METER);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "maxThreads").summary(), 0, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "rejectedCount").summary(), 0, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "completedTaskCount").summary(), 0, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "currentThreadsBusy").summary(), 0, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "corePoolSize").summary(), 0, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "poolSize").summary(), 0, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "queueSize").summary(), 10, 0);
+    Assertions.assertEquals(node.findChild("groupExecutor-group0", "taskCount").summary(), 0, 0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
index a18d2207d..bc1fd4df6 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestDefaultLogPublisher.java
@@ -163,7 +163,7 @@ public class TestDefaultLogPublisher {
       };
       DefaultPublishModel model = new DefaultPublishModel();
       PerfInfo perfTotal = new PerfInfo();
-      perfTotal.setTps(10_0000);
+      perfTotal.setTotalRequests(10_0000);
       perfTotal.setMsTotalTime(30000L * 1_0000);
       perfTotal.setMsMaxLatency(30000);
       OperationPerf operationPerf = new OperationPerf();
@@ -264,8 +264,9 @@ public class TestDefaultLogPublisher {
                 0        0          0        0           NaN      0         0.0       0.0          test
               consumer:
                simple:
-                status      tps      latency            [0,1) [1,100) [100,) operation
-                rest.OK     100000.0 3000.000/30000.000 12    120     1200   op
+                status      requests      latency       [0,1) [1,100) [100,) operation
+                rest.OK:  \s
+                            100000.0 3000.000/30000.000 12    120     1200   op
                             100000.0 3000.000/30000.000 12    120     1200   (summary)
                details:
                   rest.OK:
@@ -274,8 +275,9 @@ public class TestDefaultLogPublisher {
                       wait  : 3000.000/30000.000 decode-response    : 3000.000/30000.000
               producer:
                simple:
-                status      tps      latency            [0,1) [1,100) [100,) operation
-                rest.OK     100000.0 3000.000/30000.000 12    120     1200   op
+                status      requests      latency       [0,1) [1,100) [100,) operation
+                rest.OK:  \s
+                            100000.0 3000.000/30000.000 12    120     1200   op
                             100000.0 3000.000/30000.000 12    120     1200   (summary)
                details:
                   rest.OK:
@@ -284,8 +286,9 @@ public class TestDefaultLogPublisher {
                       encode-response: 3000.000/30000.000 send: 3000.000/30000.000
               edge:
                simple:
-                status      tps      latency            [0,1) [1,100) [100,) operation
-                rest.OK     100000.0 3000.000/30000.000 12    120     1200   op
+                status      requests      latency       [0,1) [1,100) [100,) operation
+                rest.OK:  \s
+                            100000.0 3000.000/30000.000 12    120     1200   op
                             100000.0 3000.000/30000.000 12    120     1200   (summary)
                details:
                   rest.OK:
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
index e96bed878..d0310e48c 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestInvocationPublishModelFactory.java
@@ -75,198 +75,198 @@ public class TestInvocationPublishModelFactory {
 
     String expect = """
         {
-           "operationPerfGroups" : {
-             "groups" : {
-               "rest" : {
-                 "200" : {
-                   "transport" : "rest",
-                   "status" : "200",
-                   "operationPerfs" : [ {
-                     "operation" : "m.s.o",
-                     "stages" : {
-                       "consumer-encode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "prepare" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "wait" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "total" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.4E-5,
-                         "msMaxLatency" : 1.4E-5
-                       },
-                       "consumer-send" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "connection" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "consumer-decode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       }
-                     },
-                     "latencyDistribution" : [ 1, 0, 0 ]
-                   } ],
-                   "summary" : {
-                     "operation" : "",
-                     "stages" : {
-                       "consumer-encode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "prepare" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "total" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.4E-5,
-                         "msMaxLatency" : 1.4E-5
-                       },
-                       "wait" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "consumer-send" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "connection" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "consumer-decode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       }
-                     },
-                     "latencyDistribution" : [ 1, 0, 0 ]
-                   }
-                 }
-               }
-             }
-           }
-         }
+            "operationPerfGroups" : {
+              "groups" : {
+                "rest" : {
+                  "200" : {
+                    "transport" : "rest",
+                    "status" : "200",
+                    "operationPerfs" : [ {
+                      "operation" : "m.s.o",
+                      "stages" : {
+                        "consumer-encode" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "prepare" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "wait" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "total" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.4E-5,
+                          "msMaxLatency" : 1.4E-5
+                        },
+                        "consumer-send" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "connection" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "consumer-decode" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        }
+                      },
+                      "latencyDistribution" : [ 1, 0, 0 ]
+                    } ],
+                    "summary" : {
+                      "operation" : "",
+                      "stages" : {
+                        "consumer-encode" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "prepare" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "total" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.4E-5,
+                          "msMaxLatency" : 1.4E-5
+                        },
+                        "wait" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "consumer-send" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "connection" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        },
+                        "consumer-decode" : {
+                          "totalRequests" : 1.0,
+                          "msTotalTime" : 1.0E-6,
+                          "msMaxLatency" : 1.0E-6
+                        }
+                      },
+                      "latencyDistribution" : [ 1, 0, 0 ]
+                    }
+                  }
+                }
+              }
+            }
+          }
         """;
     Assertions.assertEquals(Json.encodePrettily(Json.decodeValue(expect, Object.class)),
         Json.encodePrettily(model.getConsumer()));
 
     expect = """
         {
-           "operationPerfGroups" : {
-             "groups" : {
-               "rest" : {
-                 "200" : {
-                   "transport" : "rest",
-                   "status" : "200",
-                   "operationPerfs" : [ {
-                     "operation" : "m.s.o",
-                     "stages" : {
-                       "consumer-encode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "prepare" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "wait" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "total" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.4E-5,
-                         "msMaxLatency" : 1.4E-5
-                       },
-                       "consumer-send" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "connection" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "consumer-decode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       }
-                     },
-                     "latencyDistribution" : [ 1, 0, 0 ]
-                   } ],
-                   "summary" : {
-                     "operation" : "",
-                     "stages" : {
-                       "consumer-encode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "prepare" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "total" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.4E-5,
-                         "msMaxLatency" : 1.4E-5
-                       },
-                       "wait" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "consumer-send" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "connection" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       },
-                       "consumer-decode" : {
-                         "tps" : 1.0,
-                         "msTotalTime" : 1.0000000000000002E-6,
-                         "msMaxLatency" : 1.0000000000000002E-6
-                       }
-                     },
-                     "latencyDistribution" : [ 1, 0, 0 ]
-                   }
-                 }
-               }
-             }
-           }
-         }
+          "operationPerfGroups" : {
+            "groups" : {
+              "rest" : {
+                "200" : {
+                  "transport" : "rest",
+                  "status" : "200",
+                  "operationPerfs" : [ {
+                    "operation" : "m.s.o",
+                    "stages" : {
+                      "consumer-encode" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "prepare" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "wait" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "total" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.4E-5,
+                        "msMaxLatency" : 1.4E-5
+                      },
+                      "consumer-send" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "connection" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "consumer-decode" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      }
+                    },
+                    "latencyDistribution" : [ 1, 0, 0 ]
+                  } ],
+                  "summary" : {
+                    "operation" : "",
+                    "stages" : {
+                      "consumer-encode" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "prepare" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "total" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.4E-5,
+                        "msMaxLatency" : 1.4E-5
+                      },
+                      "wait" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "consumer-send" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "connection" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      },
+                      "consumer-decode" : {
+                        "totalRequests" : 1.0,
+                        "msTotalTime" : 1.0E-6,
+                        "msMaxLatency" : 1.0E-6
+                      }
+                    },
+                    "latencyDistribution" : [ 1, 0, 0 ]
+                  }
+                }
+              }
+            }
+          }
+        }
         """;
     Assertions.assertEquals(Json.encodePrettily(Json.decodeValue(expect, Object.class)),
         Json.encodePrettily(model.getProducer()));
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
index 7d98f7bff..66fb62f2f 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestPublishUtils.java
@@ -16,13 +16,13 @@
  */
 package org.apache.servicecomb.metrics.core.publish;
 
-import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.servicecomb.core.CoreConst;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
+import org.apache.servicecomb.metrics.core.meter.ThreadPoolMonitorPublishModelFactory;
 import org.apache.servicecomb.metrics.core.publish.model.ThreadPoolPublishModel;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf;
 import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup;
@@ -32,8 +32,6 @@ import org.apache.servicecomb.metrics.core.publish.model.invocation.Utils;
 import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 
-import org.apache.servicecomb.metrics.core.meter.ThreadPoolMonitorPublishModelFactory;
-
 import jakarta.ws.rs.core.Response.Status;
 
 public class TestPublishUtils {
@@ -45,9 +43,9 @@ public class TestPublishUtils {
 
     PerfInfo perf = PublishUtils.createPerfInfo(stageNode);
 
-    Assertions.assertEquals(10, perf.getTps(), 0);
-    Assertions.assertEquals(1000, perf.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perf.getMsMaxLatency(), 0);
+    Assertions.assertEquals(10, perf.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perf.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perf.getMsMaxLatency(), 0);
   }
 
   @Test
@@ -56,9 +54,9 @@ public class TestPublishUtils {
 
     PerfInfo perfInfo = opPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
     Integer[] latencyDistribution = opPerf.getLatencyDistribution();
-    Assertions.assertEquals(10, perfInfo.getTps(), 0);
-    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
     Assertions.assertEquals(2, latencyDistribution.length);
     Assertions.assertEquals(1, latencyDistribution[0].intValue());
     Assertions.assertEquals(2, latencyDistribution[1].intValue());
@@ -77,9 +75,9 @@ public class TestPublishUtils {
 
     PerfInfo perfInfo = group.getSummary().findStage(InvocationStageTrace.STAGE_TOTAL);
     Integer[] latencyDistribution = group.getSummary().getLatencyDistribution();
-    Assertions.assertEquals(10, perfInfo.getTps(), 0);
-    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
     Assertions.assertEquals(2, latencyDistribution.length);
     Assertions.assertEquals(1, latencyDistribution[0].intValue());
     Assertions.assertEquals(2, latencyDistribution[1].intValue());
@@ -87,9 +85,8 @@ public class TestPublishUtils {
 
   @Test
   public void createThreadPoolPublishModels_empty() {
-    Map<String, ThreadPoolPublishModel> threadPools = new HashMap<>();
-
-    ThreadPoolMonitorPublishModelFactory.create(new MeasurementTree(), threadPools);
+    Map<String, ThreadPoolPublishModel> threadPools =
+        ThreadPoolMonitorPublishModelFactory.create(new MeasurementTree());
 
     Assertions.assertTrue(threadPools.isEmpty());
   }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
index 64778d3ee..7a20f852c 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/TestThreadPoolPublishModelFactory.java
@@ -17,8 +17,8 @@
 package org.apache.servicecomb.metrics.core.publish;
 
 import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
 
+import org.apache.servicecomb.core.executor.ThreadPoolExecutorEx;
 import org.apache.servicecomb.foundation.common.event.EventManager;
 import org.apache.servicecomb.foundation.common.utils.JsonUtils;
 import org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig;
@@ -44,7 +44,7 @@ public class TestThreadPoolPublishModelFactory {
   BlockingQueue<Runnable> queue;
 
   @Test
-  public void createDefaultPublishModel(@Injectable ThreadPoolExecutor threadPoolExecutor) throws Exception {
+  public void createDefaultPublishModel(@Injectable ThreadPoolExecutorEx threadPoolExecutor) throws Exception {
     new Expectations() {
       {
         threadPoolExecutor.getQueue();
@@ -66,7 +66,8 @@ public class TestThreadPoolPublishModelFactory {
     DefaultPublishModel model = factory.createDefaultPublishModel();
 
     Assertions.assertEquals(
-        "{\"test\":{\"avgTaskCount\":0.0,\"avgCompletedTaskCount\":0.0,\"currentThreadsBusy\":0,\"maxThreads\":0,\"poolSize\":0,\"corePoolSize\":0,\"queueSize\":10,\"rejected\":\"NaN\"}}",
+        """
+            {"test":{"avgTaskCount":0.0,"avgCompletedTaskCount":0.0,"currentThreadsBusy":0,"maxThreads":0,"poolSize":0,"corePoolSize":0,"queueSize":10,"rejected":0.0}}""",
         JsonUtils.writeValueAsString(model.getThreadPools()));
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java
index bc4016165..2090f21a8 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerf.java
@@ -35,13 +35,13 @@ public class TestOperationPerf {
     Assertions.assertEquals(op, otherOpPerf.getOperation());
 
     PerfInfo perfInfo = opPerf.findStage(InvocationStageTrace.STAGE_TOTAL);
-    Assertions.assertEquals(10, perfInfo.getTps(), 0);
-    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
 
     perfInfo = opPerf.findStage(InvocationStageTrace.STAGE_PROVIDER_BUSINESS);
-    Assertions.assertEquals(10, perfInfo.getTps(), 0);
-    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(10, perfInfo.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java
index ae3ed7a29..9f4fa492f 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestOperationPerfGroup.java
@@ -47,13 +47,13 @@ public class TestOperationPerfGroup {
     OperationPerf summary = group.getSummary();
 
     PerfInfo perfInfo = summary.findStage(InvocationStageTrace.STAGE_TOTAL);
-    Assertions.assertEquals(20, perfInfo.getTps(), 0);
-    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(20, perfInfo.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
 
     perfInfo = summary.findStage(InvocationStageTrace.STAGE_PROVIDER_BUSINESS);
-    Assertions.assertEquals(20, perfInfo.getTps(), 0);
-    Assertions.assertEquals(1000, perfInfo.calcMsLatency(), 0);
-    Assertions.assertEquals(100000, perfInfo.getMsMaxLatency(), 0);
+    Assertions.assertEquals(20, perfInfo.getTotalRequests(), 0);
+    Assertions.assertEquals(1, perfInfo.calcMsLatency(), 0);
+    Assertions.assertEquals(100, perfInfo.getMsMaxLatency(), 0);
   }
 }
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestPerfInfo.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestPerfInfo.java
index 3fec1908b..35c6d83e7 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestPerfInfo.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/TestPerfInfo.java
@@ -24,7 +24,7 @@ public class TestPerfInfo {
   public void construct() {
     PerfInfo perf = new PerfInfo();
 
-    Assertions.assertEquals(0, perf.getTps(), 0);
+    Assertions.assertEquals(0, perf.getTotalRequests(), 0);
     Assertions.assertEquals(0, perf.getMsTotalTime(), 0);
     Assertions.assertEquals(0, perf.getMsMaxLatency(), 0);
     Assertions.assertEquals(0, perf.calcMsLatency(), 0);
@@ -35,18 +35,18 @@ public class TestPerfInfo {
     PerfInfo sum = new PerfInfo();
 
     PerfInfo other = new PerfInfo();
-    other.setTps(10);
+    other.setTotalRequests(10);
     other.setMsTotalTime(10);
     other.setMsMaxLatency(100);
     sum.add(other);
 
     other = new PerfInfo();
-    other.setTps(20);
+    other.setTotalRequests(20);
     other.setMsTotalTime(20);
     other.setMsMaxLatency(200);
     sum.add(other);
 
-    Assertions.assertEquals(30, sum.getTps(), 0);
+    Assertions.assertEquals(30, sum.getTotalRequests(), 0);
     Assertions.assertEquals(30, sum.getMsTotalTime(), 0);
     Assertions.assertEquals(200, sum.getMsMaxLatency(), 0);
     Assertions.assertEquals(1.0, sum.calcMsLatency(), 0);
@@ -57,18 +57,18 @@ public class TestPerfInfo {
     PerfInfo sum = new PerfInfo();
 
     PerfInfo other = new PerfInfo();
-    other.setTps(10);
+    other.setTotalRequests(10);
     other.setMsTotalTime(10);
     other.setMsMaxLatency(100);
     sum.add(other);
 
     other = new PerfInfo();
-    other.setTps(20);
+    other.setTotalRequests(20);
     other.setMsTotalTime(20);
     other.setMsMaxLatency(50);
     sum.add(other);
 
-    Assertions.assertEquals(30, sum.getTps(), 0);
+    Assertions.assertEquals(30, sum.getTotalRequests(), 0);
     Assertions.assertEquals(1.0, sum.calcMsLatency(), 0);
     Assertions.assertEquals(100, sum.getMsMaxLatency(), 0);
   }
@@ -76,7 +76,7 @@ public class TestPerfInfo {
   @Test
   public void testToString() {
     PerfInfo perf = new PerfInfo();
-    perf.setTps(10);
+    perf.setTotalRequests(10);
     perf.setMsTotalTime(10);
     perf.setMsMaxLatency(100);
 
diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
index a9f87601d..c48a1b5b6 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/publish/model/invocation/Utils.java
@@ -21,6 +21,7 @@ import java.util.List;
 
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode;
+import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree;
 import org.apache.servicecomb.metrics.core.meter.invocation.MeterInvocationConst;
 import org.apache.servicecomb.metrics.core.publish.PublishUtils;
 
@@ -60,7 +61,7 @@ public class Utils {
     Id id = initId;
     MeasurementNode statusNode = new MeasurementNode(status, id, new HashMap<>());
     MeasurementNode typeNode = new MeasurementNode(MeterInvocationConst.TAG_STAGE, id, new HashMap<>());
-    MeasurementNode latencyNode = new MeasurementNode(MeterInvocationConst.TAG_LATENCY_DISTRIBUTION, id,
+    MeasurementNode latencyNode = new MeasurementNode(MeasurementTree.TAG_LATENCY_DISTRIBUTION, id,
         new HashMap<>());
     List<Measurement> measurements = latencyNode.getMeasurements();
     measurements.add(new Measurement(() -> 1, Statistic.VALUE));


(servicecomb-java-chassis) 03/11: [SCB-2838]using micrometer to replace spectator part3: EndpointMeter

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 611517baf6388bd5c54c96d41b92d76be6e87329
Author: liubao <bi...@qq.com>
AuthorDate: Mon Nov 27 09:50:50 2023 +0800

    [SCB-2838]using micrometer to replace spectator part3: EndpointMeter
---
 .../com/netflix/spectator/api/SpectatorUtils.java  |  33 ------
 .../foundation/metrics/meter/PeriodMeter.java      |  10 +-
 .../foundation/metrics/meter/SimpleTimer.java      |  91 ---------------
 .../foundation/metrics/meter/TestSimpleTimer.java  |  43 -------
 .../metric/DefaultClientEndpointMetricManager.java |  27 ++++-
 .../metrics/core/VertxMetersInitializer.java       |  18 ++-
 .../metrics/core/meter/vertx/EndpointMeter.java    | 126 ++++++++++++---------
 .../core/meter/vertx/HttpClientEndpointMeter.java  |  26 ++---
 .../core/meter/vertx/HttpClientEndpointsMeter.java |  15 +--
 .../core/meter/vertx/ServerEndpointMeter.java      |  33 +++---
 .../core/meter/vertx/ServerEndpointsMeter.java     |  12 +-
 .../core/meter/vertx/VertxEndpointsMeter.java      |  52 +++------
 .../metrics/core/publish/DefaultLogPublisher.java  |   2 +-
 13 files changed, 165 insertions(+), 323 deletions(-)

diff --git a/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
deleted file mode 100644
index 400b8cb4b..000000000
--- a/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java
+++ /dev/null
@@ -1,33 +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 com.netflix.spectator.api;
-
-import io.micrometer.core.instrument.Meter;
-import io.micrometer.core.instrument.MeterRegistry;
-
-public final class SpectatorUtils {
-  private SpectatorUtils() {
-  }
-
-  public static void registerMeter(MeterRegistry registry, Meter meter) {
-    registry.counter()
-    if (!(registry instanceof AbstractRegistry)) {
-      throw new IllegalStateException("registry must be a AbstractRegistry, class=" + registry.getClass().getName());
-    }
-    ((AbstractRegistry) registry).getOrCreate(meter.id(), Meter.class, null, _id -> meter);
-  }
-}
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
index 4fa57f13e..3fcbf41bd 100644
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
+++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java
@@ -16,14 +16,6 @@
  */
 package org.apache.servicecomb.foundation.metrics.meter;
 
-import java.util.List;
-
-import io.micrometer.core.instrument.Measurement;
-import io.micrometer.core.instrument.Meter;
-
-
-public interface PeriodMeter extends Meter {
+public interface PeriodMeter {
   void calcMeasurements(long msNow, long secondInterval);
-
-  void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval);
 }
diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
deleted file mode 100644
index f1860a783..000000000
--- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java
+++ /dev/null
@@ -1,91 +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.servicecomb.foundation.metrics.meter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.LongAdder;
-
-
-import io.micrometer.core.instrument.Measurement;
-
-/**
- * ServoTimer is too slow
- * this is a faster timer
- */
-public class SimpleTimer extends AbstractPeriodMeter {
-  private static final double CNV_SECONDS = 1.0 / TimeUnit.SECONDS.toNanos(1L);
-
-  private final Id idCount;
-
-  private final Id idTotalTime;
-
-  private final Id idMax;
-
-  private final LongAdder count = new LongAdder();
-
-  private final LongAdder totalTime = new LongAdder();
-
-  private final AtomicDouble max = new AtomicDouble();
-
-  private long lastCount = 0;
-
-  private long lastTotalTime = 0;
-
-  public SimpleTimer(Id id) {
-    this.id = id;
-    this.idCount = id.withTag(Statistic.count);
-    this.idTotalTime = id.withTag(Statistic.totalTime);
-    this.idMax = id.withTag(Statistic.max);
-  }
-
-  public void record(long nanoAmount) {
-    if (nanoAmount >= 0) {
-      totalTime.add(nanoAmount);
-      count.increment();
-      max.max(nanoAmount);
-    }
-  }
-
-  private Measurement newMeasurement(Id id, long msNow, Number n) {
-    return new Measurement(id, msNow, n.doubleValue());
-  }
-
-  @Override
-  public void calcMeasurements(long msNow, long secondInterval) {
-    List<Measurement> measurements = new ArrayList<>(3);
-    calcMeasurements(measurements, msNow, secondInterval);
-    allMeasurements = measurements;
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
-    long currentCount = count.longValue();
-    long currentTotalTime = totalTime.longValue();
-
-    measurements.add(newMeasurement(idCount, msNow, (double) (currentCount - lastCount) / secondInterval));
-    measurements
-        .add(newMeasurement(idTotalTime, msNow, (currentTotalTime - lastTotalTime) / secondInterval * CNV_SECONDS));
-    measurements.add(newMeasurement(idMax, msNow, max.get() * CNV_SECONDS));
-
-    lastCount = currentCount;
-    lastTotalTime = currentTotalTime;
-    // maybe lost some max value, but not so important?
-    max.set(0);
-  }
-}
diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
deleted file mode 100644
index adc08f1bb..000000000
--- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java
+++ /dev/null
@@ -1,43 +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.servicecomb.foundation.metrics.meter;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import io.micrometer.core.instrument.Meter.Id;
-import io.micrometer.core.instrument.Meter.Type;
-import io.micrometer.core.instrument.Tags;
-
-public class TestSimpleTimer {
-  SimpleTimer timer = new SimpleTimer(new Id("test", Tags.empty(), null, null, Type.TIMER));
-
-  @Test
-  public void measure() {
-    timer.record(2);
-    timer.record(4);
-
-    Assertions.assertFalse(timer.measure().iterator().hasNext());
-
-    timer.calcMeasurements(1, 2);
-    Assertions.assertEquals(
-        "[Measurement(name:statistic=count,1,1.0), Measurement(name:statistic=totalTime,1,3.0000000000000004E-9), Measurement(name:statistic=max,1,4.0E-9)]",
-        timer.measure().toString());
-    Assertions.assertFalse(timer.hasExpired());
-    Assertions.assertEquals("name", timer.id().getName());
-  }
-}
diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java
index bdd5a1e52..a6ece5cac 100644
--- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java
+++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java
@@ -16,6 +16,8 @@
  */
 package org.apache.servicecomb.foundation.vertx.metrics.metric;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -28,6 +30,10 @@ import com.google.common.annotations.VisibleForTesting;
 import io.vertx.core.Vertx;
 
 public class DefaultClientEndpointMetricManager {
+  public interface ChangeListener {
+    void endpointsChanged();
+  }
+
   private final MetricsOptionsEx metricsOptionsEx;
 
   // to avoid save too many endpoint that not exist any more
@@ -43,14 +49,24 @@ public class DefaultClientEndpointMetricManager {
   // so must lock the logic
   private final ReadWriteLock rwlock = new ReentrantReadWriteLock();
 
+  private final List<ChangeListener> changeListeners = new ArrayList<>();
+
   public DefaultClientEndpointMetricManager(MetricsOptionsEx metricsOptionsEx) {
     this.metricsOptionsEx = metricsOptionsEx;
   }
 
+  public void addChangeListener(ChangeListener listener) {
+    this.changeListeners.add(listener);
+  }
+
   public DefaultClientEndpointMetric getOrCreateEndpointMetric(String address) {
     rwlock.readLock().lock();
     try {
-      return clientEndpointMetricMap.computeIfAbsent(address, DefaultClientEndpointMetric::new);
+      if (clientEndpointMetricMap.get(address) == null) {
+        clientEndpointMetricMap.put(address, new DefaultClientEndpointMetric(address));
+        onChanged();
+      }
+      return clientEndpointMetricMap.get(address);
     } finally {
       rwlock.readLock().unlock();
     }
@@ -67,22 +83,31 @@ public class DefaultClientEndpointMetricManager {
 
   @VisibleForTesting
   public void onCheckClientEndpointMetricExpired(long periodic) {
+    boolean changed = false;
     for (DefaultClientEndpointMetric metric : clientEndpointMetricMap.values()) {
       if (metric.isExpired(metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano())) {
         rwlock.writeLock().lock();
         try {
           if (metric.isExpired(metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano())) {
             clientEndpointMetricMap.remove(metric.getAddress());
+            changed = true;
           }
         } finally {
           rwlock.writeLock().unlock();
         }
       }
     }
+    if (changed) {
+      onChanged();
+    }
   }
 
   public void setVertx(Vertx vertx) {
     vertx.setPeriodic(metricsOptionsEx.getCheckClientEndpointMetricIntervalInMilliseconds(),
         this::onCheckClientEndpointMetricExpired);
   }
+
+  private void onChanged() {
+    this.changeListeners.forEach(ChangeListener::endpointsChanged);
+  }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
index 51cee1400..dbc093ab1 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/VertxMetersInitializer.java
@@ -21,35 +21,31 @@ import org.apache.servicecomb.foundation.metrics.MetricsInitializer;
 import org.apache.servicecomb.foundation.vertx.SharedVertxFactory;
 import org.apache.servicecomb.metrics.core.meter.vertx.HttpClientEndpointsMeter;
 import org.apache.servicecomb.metrics.core.meter.vertx.ServerEndpointsMeter;
-import org.apache.servicecomb.metrics.core.meter.vertx.VertxEndpointsMeter;
 
 import com.google.common.eventbus.EventBus;
 
-import io.micrometer.core.instrument.Meter.Id;
 import io.micrometer.core.instrument.MeterRegistry;
-import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Tags;
 
 public class VertxMetersInitializer implements MetricsInitializer {
   public static final String VERTX_ENDPOINTS = "servicecomb.vertx.endpoints";
 
   public static final String ENDPOINTS_TYPE = "type";
 
-  public static final String ENDPOINTS_CLINET = "client";
+  public static final String ENDPOINTS_CLIENT = "client";
 
   public static final String ENDPOINTS_SERVER = "server";
 
   @Override
   public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) {
-    Id endpointsId = new Id(VERTX_ENDPOINTS, null, null, null, null);
-    VertxEndpointsMeter clientMeter = new HttpClientEndpointsMeter(
-        endpointsId.withTag(Tag.of(ENDPOINTS_TYPE, ENDPOINTS_CLINET)),
+    new HttpClientEndpointsMeter(meterRegistry, VERTX_ENDPOINTS,
+        Tags.of(ENDPOINTS_TYPE, ENDPOINTS_CLIENT),
         SharedVertxFactory.getMetricsFactory(config.getEnvironment())
             .getVertxMetrics()
-            .getClientEndpointMetricManager()
-            .getClientEndpointMetricMap());
+            .getClientEndpointMetricManager());
 
-    VertxEndpointsMeter serverMeter = new ServerEndpointsMeter(
-        endpointsId.withTag(Tag.of(ENDPOINTS_TYPE, ENDPOINTS_SERVER)),
+    new ServerEndpointsMeter(meterRegistry, VERTX_ENDPOINTS,
+        Tags.of(ENDPOINTS_TYPE, ENDPOINTS_SERVER),
         SharedVertxFactory.getMetricsFactory(config.getEnvironment())
             .getVertxMetrics()
             .getServerEndpointMetricMap());
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
index 2217c8204..3624ef441 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/EndpointMeter.java
@@ -16,15 +16,14 @@
  */
 package org.apache.servicecomb.metrics.core.meter.vertx;
 
-import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import io.micrometer.core.instrument.Measurement;
-import io.micrometer.core.instrument.Meter.Id;
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
-
+import io.micrometer.core.instrument.Tags;
 
 public class EndpointMeter {
   private static final double SNV_MILLI_SECONDS = 1.0 / TimeUnit.MILLISECONDS.toNanos(1L);
@@ -47,23 +46,23 @@ public class EndpointMeter {
 
   public static final String LATENCY = "latency";
 
-  protected Id id;
+  protected DefaultEndpointMetric metric;
 
-  private final Id idConnect;
+  private final MeterRegistry meterRegistry;
 
-  private final Id idDisconnect;
+  private final Gauge connectCount;
 
-  private final Id idConnections;
+  private final Gauge disconnectCount;
 
-  private final Id idBytesRead;
+  private final Gauge connections;
 
-  private final Id idBytesWritten;
+  private final Gauge bytesRead;
 
-  private final Id idRequests;
+  private final Gauge bytesWritten;
 
-  private final Id idLatency;
+  private final Gauge requests;
 
-  protected DefaultEndpointMetric metric;
+  private final Gauge latency;
 
   private long lastConnectCount;
 
@@ -75,51 +74,76 @@ public class EndpointMeter {
 
   private long lastRequests;
 
+  private long lastRequestsForLatency;
+
   private long lastLatency;
 
-  public EndpointMeter(Id id, DefaultEndpointMetric metric) {
-    id = id.withTag(Tag.of(ADDRESS, metric.getAddress()));
-    this.id = id;
-    idConnect = id.withTag(Tag.of(STATISTIC, CONNECT_COUNT);
-    idDisconnect = id.withTag(Tag.of(STATISTIC, DISCONNECT_COUNT));
-    idConnections = id.withTag(Tag.of(STATISTIC, CONNECTIONS));
-    idBytesRead = id.withTag(Tag.of(STATISTIC, BYTES_READ));
-    idBytesWritten = id.withTag(Tag.of(STATISTIC, BYTES_WRITTEN));
-    idRequests = id.withTag(Tag.of(STATISTIC, REQUESTS));
-    idLatency = id.withTag(Tag.of(STATISTIC, LATENCY));
-    this.metric = metric;
+  public EndpointMeter(MeterRegistry meterRegistry, String name, Tags tags, DefaultEndpointMetric metric) {
+    this.meterRegistry = meterRegistry;
+
+    tags = tags.and(Tag.of(ADDRESS, metric.getAddress()));
+    connectCount = Gauge.builder(name, () -> {
+          long current = metric.getConnectCount();
+          long result = current - lastConnectCount;
+          lastConnectCount = current;
+          return result;
+        })
+        .tags(tags.and(Tag.of(STATISTIC, CONNECT_COUNT)))
+        .register(meterRegistry);
+    disconnectCount = Gauge.builder(name, () -> {
+          long current = metric.getDisconnectCount();
+          long result = current - lastDisconnectCount;
+          lastDisconnectCount = current;
+          return result;
+        }).tags(tags.and(Tag.of(STATISTIC, DISCONNECT_COUNT)))
+        .register(meterRegistry);
+    connections = Gauge.builder(name, () -> metric.getConnectCount() - metric.getDisconnectCount())
+        .tags(tags.and(Tag.of(STATISTIC, CONNECTIONS)))
+        .register(meterRegistry);
+    bytesRead = Gauge.builder(name, () -> {
+          long current = metric.getBytesRead();
+          long result = current - lastBytesRead;
+          lastBytesRead = current;
+          return result;
+        }).tags(tags.and(Tag.of(STATISTIC, BYTES_READ)))
+        .register(meterRegistry);
+    bytesWritten = Gauge.builder(name, () -> {
+          long current = metric.getBytesWritten();
+          long result = current - lastBytesWritten;
+          lastBytesWritten = current;
+          return result;
+        }).tags(tags.and(Tag.of(STATISTIC, BYTES_WRITTEN)))
+        .register(meterRegistry);
+    requests = Gauge.builder(name, () -> {
+          long current = metric.getRequests();
+          long result = current - lastRequests;
+          lastRequests = current;
+          return result;
+        }).tags(tags.and(Tag.of(STATISTIC, REQUESTS)))
+        .register(meterRegistry);
+    latency = Gauge.builder(name, () -> {
+          long currentLatency = metric.getLatency();
+          long currentRequests = metric.getRequests();
+          double result = currentRequests - lastRequestsForLatency == 0 ? 0 :
+              (currentLatency - lastLatency) / ((double) (currentRequests - lastRequestsForLatency)) * SNV_MILLI_SECONDS;
+          lastRequestsForLatency = currentRequests;
+          lastLatency = currentLatency;
+          return result;
+        }).tags(tags.and(Tag.of(STATISTIC, LATENCY)))
+        .register(meterRegistry);
   }
 
   public DefaultEndpointMetric getMetric() {
     return metric;
   }
 
-  protected Measurement newMeasurement(Id id, long timestamp, Number n) {
-    return new Measurement(id, timestamp, n.doubleValue());
-  }
-
-  public void calcMeasurements(List<Measurement> measurements, long msNow, double secondInterval) {
-    long connectCount = metric.getConnectCount();
-    long disconnectCount = metric.getDisconnectCount();
-    long bytesRead = metric.getBytesRead();
-    long bytesWritten = metric.getBytesWritten();
-    long requests = metric.getRequests();
-    long latency = metric.getLatency();
-
-    measurements.add(newMeasurement(idConnect, msNow, connectCount - lastConnectCount));
-    measurements.add(newMeasurement(idDisconnect, msNow, disconnectCount - lastDisconnectCount));
-    measurements.add(newMeasurement(idConnections, msNow, connectCount - disconnectCount));
-    measurements.add(newMeasurement(idBytesRead, msNow, (bytesRead - lastBytesRead) / secondInterval));
-    measurements.add(newMeasurement(idBytesWritten, msNow, (bytesWritten - lastBytesWritten) / secondInterval));
-    measurements.add(newMeasurement(idRequests, msNow, requests - lastRequests));
-    measurements.add(newMeasurement(idLatency, msNow,
-        requests - lastRequests == 0 ? 0 : (latency - lastLatency) / (requests - lastRequests) * SNV_MILLI_SECONDS));
-
-    this.lastConnectCount = connectCount;
-    this.lastDisconnectCount = disconnectCount;
-    this.lastBytesRead = bytesRead;
-    this.lastBytesWritten = bytesWritten;
-    this.lastRequests = requests;
-    this.lastLatency = latency;
+  public void destroy() {
+    this.meterRegistry.remove(connectCount);
+    this.meterRegistry.remove(disconnectCount);
+    this.meterRegistry.remove(connections);
+    this.meterRegistry.remove(bytesRead);
+    this.meterRegistry.remove(bytesWritten);
+    this.meterRegistry.remove(requests);
+    this.meterRegistry.remove(latency);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java
index a960bf680..a80f4643e 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointMeter.java
@@ -16,29 +16,21 @@
  */
 package org.apache.servicecomb.metrics.core.meter.vertx;
 
-import java.util.List;
-
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetric;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Tags;
 
 public class HttpClientEndpointMeter extends EndpointMeter {
   public static final String QUEUE_COUNT = "queueCount";
 
-  private final Id idQueueCount;
-
-  public HttpClientEndpointMeter(Id id, DefaultEndpointMetric metric) {
-    super(id, metric);
-    idQueueCount = this.id.withTag(STATISTIC, QUEUE_COUNT);
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, double secondInterval) {
-    super.calcMeasurements(measurements, msNow, secondInterval);
-
-    long queueCount = ((DefaultClientEndpointMetric) metric).getQueueCount();
-    measurements.add(newMeasurement(idQueueCount, msNow, queueCount));
+  public HttpClientEndpointMeter(MeterRegistry meterRegistry, String name, Tags tags, DefaultEndpointMetric metric) {
+    super(meterRegistry, name, tags, metric);
+    Gauge.builder(name, () -> ((DefaultClientEndpointMetric) metric).getQueueCount())
+        .tags(tags.and(Tag.of(STATISTIC, QUEUE_COUNT)))
+        .register(meterRegistry);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
index a8c3c4db9..78169f6af 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/HttpClientEndpointsMeter.java
@@ -16,20 +16,21 @@
  */
 package org.apache.servicecomb.metrics.core.meter.vertx;
 
-import java.util.Map;
-
+import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetricManager;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
 public class HttpClientEndpointsMeter extends VertxEndpointsMeter {
-  public <T extends DefaultEndpointMetric> HttpClientEndpointsMeter(MeterRegistry meterRegistry, Id id,
-      Map<String, T> endpointMetricMap) {
-    super(meterRegistry, id, endpointMetricMap);
+  public <T extends DefaultEndpointMetric> HttpClientEndpointsMeter(MeterRegistry meterRegistry, String name, Tags tags,
+      DefaultClientEndpointMetricManager clientEndpointMetricManager) {
+    super(meterRegistry, name, tags, clientEndpointMetricManager.getClientEndpointMetricMap());
+    clientEndpointMetricManager.addChangeListener(this::onChanged);
   }
 
   @Override
-  protected EndpointMeter createEndpointMeter(Id id, DefaultEndpointMetric metric) {
-    return new HttpClientEndpointMeter(id, metric);
+  protected EndpointMeter createEndpointMeter(DefaultEndpointMetric metric) {
+    return new HttpClientEndpointMeter(meterRegistry, name, tags, metric);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java
index b2e8b6f40..2e8c6d2fb 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointMeter.java
@@ -16,33 +16,28 @@
  */
 package org.apache.servicecomb.metrics.core.meter.vertx;
 
-import java.util.List;
-
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric;
 
-import com.netflix.spectator.api.Id;
-import com.netflix.spectator.api.Measurement;
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tag;
+import io.micrometer.core.instrument.Tags;
 
 public class ServerEndpointMeter extends EndpointMeter {
   public static final String REJECT_BY_CONNECTION_LIMIT = "rejectByConnectionLimit";
 
-  private final Id idRejectByConnectionLimit;
-
   private long lastRejectByConnectionLimit;
 
-  public ServerEndpointMeter(Id id, DefaultEndpointMetric metric) {
-    super(id, metric);
-    idRejectByConnectionLimit = this.id.withTag(STATISTIC, REJECT_BY_CONNECTION_LIMIT);
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, double secondInterval) {
-    super.calcMeasurements(measurements, msNow, secondInterval);
-
-    long rejectByConnectionLimit = ((DefaultServerEndpointMetric) metric).getRejectByConnectionLimitCount();
-    measurements
-        .add(newMeasurement(idRejectByConnectionLimit, msNow, rejectByConnectionLimit - lastRejectByConnectionLimit));
-    this.lastRejectByConnectionLimit = rejectByConnectionLimit;
+  public ServerEndpointMeter(MeterRegistry meterRegistry, String name, Tags tags, DefaultEndpointMetric metric) {
+    super(meterRegistry, name, tags, metric);
+    Gauge.builder(name, () -> {
+          long current = ((DefaultServerEndpointMetric) metric).getRejectByConnectionLimitCount();
+          long result = current - lastRejectByConnectionLimit;
+          lastRejectByConnectionLimit = current;
+          return result;
+        })
+        .tags(tags.and(Tag.of(STATISTIC, REJECT_BY_CONNECTION_LIMIT)))
+        .register(meterRegistry);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointsMeter.java
index 14c3f2cdc..11f5a7065 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/ServerEndpointsMeter.java
@@ -20,15 +20,17 @@ import java.util.Map;
 
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import com.netflix.spectator.api.Id;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
 public class ServerEndpointsMeter extends VertxEndpointsMeter {
-  public <T extends DefaultEndpointMetric> ServerEndpointsMeter(Id id, Map<String, T> endpointMetricMap) {
-    super(id, endpointMetricMap);
+  public <T extends DefaultEndpointMetric> ServerEndpointsMeter(MeterRegistry meterRegistry, String name, Tags tags,
+      Map<String, T> endpointMetricMap) {
+    super(meterRegistry, name, tags, endpointMetricMap);
   }
 
   @Override
-  protected EndpointMeter createEndpointMeter(Id id, DefaultEndpointMetric metric) {
-    return new ServerEndpointMeter(id, metric);
+  protected EndpointMeter createEndpointMeter(DefaultEndpointMetric metric) {
+    return new ServerEndpointMeter(meterRegistry, name, tags, metric);
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
index 7bed21427..829f17746 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/meter/vertx/VertxEndpointsMeter.java
@@ -16,70 +16,52 @@
  */
 package org.apache.servicecomb.metrics.core.meter.vertx;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
-import org.apache.servicecomb.foundation.metrics.meter.AbstractPeriodMeter;
 import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric;
 
-import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
 
-public class VertxEndpointsMeter extends AbstractPeriodMeter {
+public class VertxEndpointsMeter {
   private final Map<String, DefaultEndpointMetric> endpointMetricMap;
 
-  private final MeterRegistry meterRegistry;
+  protected final MeterRegistry meterRegistry;
+
+  protected final String name;
+
+  protected final Tags tags;
 
   private final Map<String, EndpointMeter> endpointMeterMap = new ConcurrentHashMapEx<>();
 
   @SuppressWarnings("unchecked")
-  public <T extends DefaultEndpointMetric> VertxEndpointsMeter(MeterRegistry meterRegistry, Id id,
+  public <T extends DefaultEndpointMetric> VertxEndpointsMeter(MeterRegistry meterRegistry, String name, Tags tags,
       Map<String, T> endpointMetricMap) {
-    this.id = id;
     this.meterRegistry = meterRegistry;
+    this.name = name;
+    this.tags = tags;
     this.endpointMetricMap = (Map<String, DefaultEndpointMetric>) endpointMetricMap;
-  }
-
-  @Override
-  public void calcMeasurements(long msNow, long secondInterval) {
-    List<Measurement> measurements = new ArrayList<>();
-    calcMeasurements(measurements, msNow, secondInterval);
-    allMeasurements = measurements;
-  }
-
-  @Override
-  public void calcMeasurements(List<Measurement> measurements, long msNow, long secondInterval) {
     syncMeters();
-
-    for (EndpointMeter meter : endpointMeterMap.values()) {
-      meter.calcMeasurements(measurements, msNow, secondInterval);
-    }
   }
 
   private void syncMeters() {
     for (EndpointMeter meter : endpointMeterMap.values()) {
       if (!endpointMetricMap.containsKey(meter.getMetric().getAddress())) {
-        endpointMeterMap.remove(meter.getMetric().getAddress());
+        EndpointMeter removed = endpointMeterMap.remove(meter.getMetric().getAddress());
+        removed.destroy();
       }
     }
     for (DefaultEndpointMetric metric : endpointMetricMap.values()) {
-      endpointMeterMap.computeIfAbsent(metric.getAddress(), addr -> createEndpointMeter(id, metric));
+      endpointMeterMap.computeIfAbsent(metric.getAddress(), address -> createEndpointMeter(metric));
     }
   }
 
-  protected EndpointMeter createEndpointMeter(Id id, DefaultEndpointMetric metric) {
-    return new EndpointMeter(id, metric);
+  protected EndpointMeter createEndpointMeter(DefaultEndpointMetric metric) {
+    return new EndpointMeter(meterRegistry, name, tags, metric);
   }
 
-  @Override
-  public Iterable<Measurement> measure() {
-    return allMeasurements;
-  }
-
-  @Override
-  public boolean hasExpired() {
-    return false;
+  protected void onChanged() {
+    syncMeters();
   }
 }
diff --git a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
index 2f45238d9..48e0d047d 100644
--- a/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
+++ b/metrics/metrics-core/src/main/java/org/apache/servicecomb/metrics/core/publish/DefaultLogPublisher.java
@@ -482,7 +482,7 @@ public class DefaultLogPublisher implements MetricsInitializer {
     }
 
     ClientEndpointsLogPublisher client = new ClientEndpointsLogPublisher(tree, sb,
-        VertxMetersInitializer.ENDPOINTS_CLINET);
+        VertxMetersInitializer.ENDPOINTS_CLIENT);
     ServerEndpointsLogPublisher server = new ServerEndpointsLogPublisher(tree, sb,
         VertxMetersInitializer.ENDPOINTS_SERVER);
     if (client.isExists() || server.isExists()) {


(servicecomb-java-chassis) 10/11: [SCB-2838]fix test case in linux not mock

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit f9b3c9f16675de08b146c1dab3d58ae0426bdb20
Author: liubao <bi...@qq.com>
AuthorDate: Fri Dec 1 15:45:58 2023 +0800

    [SCB-2838]fix test case in linux not mock
---
 .../org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java  | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
index a373e21ba..28865a3fd 100644
--- a/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
+++ b/metrics/metrics-core/src/test/java/org/apache/servicecomb/metrics/core/TestOsMeterInitializer.java
@@ -34,6 +34,7 @@ import org.junit.Test;
 import org.junit.jupiter.api.Assertions;
 
 import com.google.common.eventbus.EventBus;
+import com.google.common.io.CharSource;
 import com.google.common.io.Files;
 
 import io.micrometer.core.instrument.MeterRegistry;
@@ -55,10 +56,10 @@ public class TestOsMeterInitializer {
     list.add("13  1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1");
     list.add("useless");
     list.add("eth0: 0 0    0    0    0     0          0          0         0 0    0      0     0     0    0    0");
-    new MockUp<Files>() {
+    new MockUp<CharSource>() {
       //Files.readFirstLine
       @Mock
-      public String readFirstLine(File file, Charset encoding) {
+      public String readFirstLine() {
         return list.get(0);
       }
     };