You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2020/09/26 13:30:56 UTC

[skywalking] branch master updated: Provide metrics APIs for agent plugin (#5523)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new a68be42  Provide metrics APIs for agent plugin (#5523)
a68be42 is described below

commit a68be426a0c22d9ff0f10860417ef405edc1797d
Author: mrproliu <74...@qq.com>
AuthorDate: Sat Sep 26 21:30:37 2020 +0800

    Provide metrics APIs for agent plugin (#5523)
---
 .../skywalking/apm/toolkit/meter/BaseBuilder.java  |  53 +++++-
 .../skywalking/apm/toolkit/meter/BaseMeter.java    |  16 +-
 .../skywalking/apm/toolkit/meter/Counter.java      |  48 ++++-
 .../apache/skywalking/apm/toolkit/meter/Gauge.java |  37 +++-
 .../skywalking/apm/toolkit/meter/Histogram.java    |  74 +++++---
 .../meter/{BaseMeter.java => MeterCenter.java}     |  23 +--
 .../skywalking/apm/toolkit/meter/MeterFactory.java |  16 +-
 .../apm/toolkit/meter/impl/AbstractBuilder.java    |  98 -----------
 .../apm/toolkit/meter/impl/AbstractMeter.java      |  72 --------
 .../apm/toolkit/meter/impl/GaugeImpl.java          |  79 ---------
 .../apm/toolkit/meter/impl/MeterCenter.java        |  65 -------
 .../apm/toolkit/meter/AbstractMeterTest.java       | 194 ---------------------
 .../skywalking/apm/toolkit/meter/CounterTest.java  |  89 +---------
 .../skywalking/apm/toolkit/meter/GaugeTest.java    |  44 +----
 .../apm/toolkit/meter/HistogramTest.java           |  99 +----------
 .../apm/toolkit/meter/MeterCenterTest.java         |  76 --------
 .../apm/meter/micrometer/SkywalkingCounter.java    |   3 +-
 .../meter/micrometer/SkywalkingCustomCounter.java  |  15 +-
 .../meter/micrometer/SkywalkingMeterRegistry.java  |   2 +-
 .../apm/meter/micrometer/MeterBuilderTest.java     |  13 +-
 .../meter/micrometer/SkywalkingCounterTest.java    |  26 +--
 .../micrometer/SkywalkingCustomCounterTest.java    |   7 +-
 .../SkywalkingDistributionSummaryTest.java         |  25 +--
 .../micrometer/SkywalkingLongTaskTimerTest.java    |  26 +--
 .../meter/micrometer/SkywalkingMeterBaseTest.java  |  91 ----------
 .../micrometer/SkywalkingMeterRegistryTest.java    | 129 +-------------
 .../apm/meter/micrometer/SkywalkingTimerTest.java  |  25 +--
 .../apm/agent/core/meter/AbstractBuilder.java      |  77 ++++++++
 .../MeterTransformer.java => BaseMeter.java}       |  58 +++---
 .../skywalking/apm/agent/core/meter/Counter.java   |  80 ++++-----
 .../HistogramAdapter.java => CounterMode.java}     |  17 +-
 .../GaugeTransformer.java => Gauge.java}           |  58 ++++--
 .../skywalking/apm/agent/core/meter/Histogram.java | 103 +++++------
 .../apm/agent/core}/meter/MeterFactory.java        |  38 +---
 .../apm/agent/core/meter/MeterSender.java          |   9 +-
 .../apm/agent/core/meter/MeterService.java         |  18 +-
 .../skywalking/apm/agent/core/meter/MeterTag.java  |   7 +-
 .../agent/core/meter/adapter/CounterAdapter.java   |  23 ---
 .../apm/agent/core/meter/adapter/GaugeAdapter.java |  23 ---
 .../apm/agent/core/meter/adapter/MeterAdapter.java |  31 ----
 .../core/meter/transform/CounterTransformer.java   |  49 ------
 .../core/meter/transform/HistogramTransformer.java |  92 ----------
 ...ounterTransformerTest.java => CounterTest.java} |  77 ++++----
 .../GaugeTransformerTest.java => GaugeTest.java}   |  65 +++----
 ...gramTransformerTest.java => HistogramTest.java} |  86 ++++-----
 .../apm/agent/core/meter/MeterDataBaseTest.java    |  81 +++++++++
 .../apm/agent/core/meter/MeterFactoryTest.java     |  79 +++++++++
 .../apm/agent/core/meter/MeterServiceTest.java     |  69 +-------
 .../activation/meter/CounterActivation.java        |  40 ++++-
 ...eptor.java => CounterConstructInterceptor.java} |  20 ++-
 ...Interceptor.java => CounterGetInterceptor.java} |  30 ++--
 ...eptor.java => CounterIncrementInterceptor.java} |  32 ++--
 .../toolkit/activation/meter/GaugeActivation.java  |  24 ++-
 ...rceptor.java => GaugeConstructInterceptor.java} |  18 +-
 ...geInterceptor.java => GaugeGetInterceptor.java} |  31 ++--
 .../activation/meter/HistogramActivation.java      |  24 ++-
 ...ptor.java => HistogramAddValueInterceptor.java} |  32 ++--
 ...tor.java => HistogramConstructInterceptor.java} |  19 +-
 .../meter/adapter/ToolkitCounterAdapter.java       |  46 -----
 .../meter/adapter/ToolkitGaugeAdapter.java         |  46 -----
 .../meter/adapter/ToolkitHistogramAdapter.java     |  61 -------
 ...t.java => CounterConstructInterceptorTest.java} |  41 +++--
 ...est.java => GaugeConstructInterceptorTest.java} |  40 ++---
 ...java => HistogramConstructInterceptorTest.java} |  33 ++--
 .../toolkit/meter/ToolkitCounterAdapterTest.java   |  71 --------
 .../apm/toolkit/meter/ToolkitGaugeAdapterTest.java |  49 ------
 .../toolkit/meter/ToolkitHistogramAdapterTest.java |  64 -------
 .../apm/agent/core/kafka/KafkaMeterSender.java     |   5 +-
 docs/en/guides/Java-Plugin-Development-Guide.md    |  55 +++++-
 .../java-agent/Application-toolkit-meter.md        |   2 +-
 test/e2e/e2e-service-provider/pom.xml              |  10 +-
 71 files changed, 1064 insertions(+), 2314 deletions(-)

diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseBuilder.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseBuilder.java
index d73ddff..29a146d 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseBuilder.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseBuilder.java
@@ -18,16 +18,63 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-public interface BaseBuilder<Builder extends BaseBuilder, Meter extends BaseMeter> {
+import java.util.Objects;
+
+/**
+ * Help to build the meter
+ */
+public abstract class BaseBuilder<BUILDER extends BaseBuilder, METER extends BaseMeter> {
+    protected final MeterId meterId;
+
+    /**
+     * Build a new meter build, meter name is required
+     */
+    public BaseBuilder(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Meter name cannot be null");
+        }
+        this.meterId = new MeterId(name, getType());
+    }
+
+    /**
+     * Build a new meter build from exists meter id
+     */
+    public BaseBuilder(MeterId meterId) {
+        if (meterId == null) {
+            throw new IllegalArgumentException("Meter id cannot be null");
+        }
+        if (!Objects.equals(meterId.getType(), getType())) {
+            throw new IllegalArgumentException("Meter id type is not matches");
+        }
+        this.meterId = meterId;
+    }
+
+    /**
+     * Get supported build meter type
+     */
+    protected abstract MeterId.MeterType getType();
+
+    /**
+     * Create a meter
+     */
+    protected abstract METER create();
 
     /**
      * append new tags to this meter
      */
-    Builder tag(String name, String value);
+    public BUILDER tag(String name, String value) {
+        meterId.getTags().add(new MeterId.Tag(name, value));
+        return (BUILDER) this;
+    }
 
     /**
      * Build a new meter object
      */
-    Meter build();
+    public METER build() {
+        // sort the tags
+        this.meterId.getTags().sort(MeterId.Tag::compareTo);
+        // create or get the meter
+        return create();
+    }
 
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java
index de7a2a0..4998015 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java
@@ -18,21 +18,29 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-public interface BaseMeter {
+public abstract class BaseMeter {
+    public BaseMeter(MeterId meterId) {
+    }
 
     /**
      * Get meter name
      */
-    String getName();
+    public String getName() {
+        return "";
+    }
 
     /**
      * Get tag value
      */
-    String getTag(String tagKey);
+    public String getTag(String tagKey) {
+        return "";
+    }
 
     /**
      * Get meter Id
      */
-    MeterId getMeterId();
+    public MeterId getMeterId() {
+        return null;
+    }
 
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Counter.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Counter.java
index fb7cd73..d3f947c 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Counter.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Counter.java
@@ -21,16 +21,29 @@ package org.apache.skywalking.apm.toolkit.meter;
 /**
  * A counter is a cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.
  */
-public interface Counter extends BaseMeter {
+public class Counter extends BaseMeter {
 
-    void increment(double count);
+    protected Counter(MeterId meterId, Mode mode) {
+        super(meterId);
+    }
 
-    double get();
+    /**
+     * Increase count
+     */
+    public void increment(double count) {
+    }
+
+    /**
+     * Get current value
+     */
+    public double get() {
+        return 0;
+    }
 
     /**
      * Counter mode
      */
-    enum Mode {
+    public enum Mode {
         /**
          * Increase single value, report the real value
          */
@@ -42,10 +55,33 @@ public interface Counter extends BaseMeter {
         RATE
     }
 
-    interface Builder extends BaseBuilder<Builder, Counter> {
+    public static class Builder extends BaseBuilder<Builder, Counter> {
+        private Counter.Mode mode = Counter.Mode.INCREMENT;
+
+        public Builder(String name) {
+            super(name);
+        }
+
+        public Builder(MeterId meterId) {
+            super(meterId);
+        }
+
         /**
          * Setting counter mode
          */
-        Builder mode(Mode mode);
+        public Builder mode(Mode mode) {
+            this.mode = mode;
+            return this;
+        }
+
+        @Override
+        protected MeterId.MeterType getType() {
+            return MeterId.MeterType.COUNTER;
+        }
+
+        @Override
+        protected Counter create() {
+            return new Counter(meterId, mode);
+        }
     }
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Gauge.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Gauge.java
index fd2d2ae..60cdaef 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Gauge.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Gauge.java
@@ -18,17 +18,46 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
+import java.util.function.Supplier;
+
 /**
  * A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
  */
-public interface Gauge extends BaseMeter {
+public class Gauge extends BaseMeter {
+
+    protected Gauge(MeterId meterId, Supplier<Double> getter) {
+        super(meterId);
+    }
 
     /**
-     * Get count
+     * Get current value
      */
-    double get();
+    public double get() {
+        return 0;
+    }
+
+    public static class Builder extends BaseBuilder<Builder, Gauge> {
+        protected Supplier<Double> getter;
+
+        public Builder(String name, Supplier<Double> getter) {
+            super(name);
+            this.getter = getter;
+        }
+
+        public Builder(MeterId meterId, Supplier<Double> getter) {
+            super(meterId);
+            this.getter = getter;
+        }
+
+        @Override
+        protected MeterId.MeterType getType() {
+            return MeterId.MeterType.GAUGE;
+        }
 
-    interface Builder extends BaseBuilder<Builder, Gauge> {
+        @Override
+        protected Gauge create() {
+            return new Gauge(meterId, getter);
+        }
     }
 
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Histogram.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Histogram.java
index 5869052..caf12da 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Histogram.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/Histogram.java
@@ -18,52 +18,80 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
- * Similar to a histogram, a summary sample observations (usual things like request durations and response sizes).
+ * A summary sample observations (usual things like request durations and response sizes).
  * While it also provides a total count of observations and a sum of all observed values, it calculates configurable quartiles over a sliding time window.
  * The histogram provides detailed data in each data group.
  */
-public interface Histogram extends BaseMeter {
+public class Histogram extends BaseMeter {
+
+    protected Histogram(MeterId meterId, List<Double> steps) {
+        super(meterId);
+    }
 
     /**
      * Add value into the histogram, automatic analyze what bucket count need to be increment
      * [step1, step2)
      */
-    void addValue(double value);
+    public void addValue(double value) {
+    }
 
-    /**
-     * Get all buckets
-     */
-    Bucket[] getBuckets();
+    public static class Builder extends BaseBuilder<Builder, Histogram> {
+        private double minValue = 0;
+        private List<Double> steps;
+
+        public Builder(String name) {
+            super(name);
+        }
 
-    interface Builder extends BaseBuilder<Builder, Histogram> {
+        public Builder(MeterId meterId) {
+            super(meterId);
+        }
 
         /**
          * Setting bucket steps
          */
-        Builder steps(List<Double> steps);
+        public Builder steps(List<Double> steps) {
+            this.steps = new ArrayList<>(steps);
+            return this;
+        }
 
         /**
          * Setting min value, default is zero
          */
-        Builder minValue(double minValue);
-    }
+        public Builder minValue(double minValue) {
+            this.minValue = minValue;
+            return this;
+        }
 
-    /**
-     * Histogram bucket
-     */
-    interface Bucket {
+        @Override
+        protected MeterId.MeterType getType() {
+            return MeterId.MeterType.HISTOGRAM;
+        }
 
-        /**
-         * Get bucket key
-         */
-        double getBucket();
+        @Override
+        protected Histogram create() {
+            if (steps == null || steps.isEmpty()) {
+                throw new IllegalArgumentException("Missing steps setting");
+            }
 
-        /**
-         * Get bucket count
-         */
-        long getCount();
+            // sort and distinct the steps
+            steps = steps.stream().distinct().sorted().collect(Collectors.toList());
+
+            // verify steps with except min value
+            if (steps.get(0) < minValue) {
+                throw new IllegalArgumentException("First step must bigger than min value");
+            } else if (steps.get(0) != minValue) {
+                // add the min value to the steps
+                steps.add(0, minValue);
+            }
+
+            return new Histogram(meterId, steps);
+        }
     }
+
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterCenter.java
similarity index 80%
copy from apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java
copy to apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterCenter.java
index de7a2a0..e449272 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/BaseMeter.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterCenter.java
@@ -18,21 +18,16 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-public interface BaseMeter {
-
-    /**
-     * Get meter name
-     */
-    String getName();
-
-    /**
-     * Get tag value
-     */
-    String getTag(String tagKey);
+/**
+ * Management the meter.
+ */
+public class MeterCenter {
 
     /**
-     * Get meter Id
+     * Remove meter
+     * @return Meter reference if exists
      */
-    MeterId getMeterId();
-
+    public static BaseMeter removeMeter(MeterId id) {
+        return null;
+    }
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java
index 60d2611..ae55ef9 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java
@@ -18,10 +18,6 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
-
 import java.util.function.Supplier;
 
 public class MeterFactory {
@@ -30,42 +26,42 @@ public class MeterFactory {
      * Create a counter builder by name
      */
     public static Counter.Builder counter(String name) {
-        return new CounterImpl.Builder(name);
+        return new Counter.Builder(name);
     }
 
     /**
      * Create a counter builder by meter id
      */
     public static Counter.Builder counter(MeterId meterId) {
-        return new CounterImpl.Builder(meterId);
+        return new Counter.Builder(meterId);
     }
 
     /**
      * Create a gauge builder by name and getter
      */
     public static Gauge.Builder gauge(String name, Supplier<Double> getter) {
-        return new GaugeImpl.Builder(name, getter);
+        return new Gauge.Builder(name, getter);
     }
 
     /**
      * Create a gauge builder by meter id and getter
      */
     public static Gauge.Builder gauge(MeterId meterId, Supplier<Double> getter) {
-        return new GaugeImpl.Builder(meterId, getter);
+        return new Gauge.Builder(meterId, getter);
     }
 
     /**
      * Create a histogram builder by name
      */
     public static Histogram.Builder histogram(String name) {
-        return new HistogramImpl.Builder(name);
+        return new Histogram.Builder(name);
     }
 
     /**
      * Create a histogram builder by meterId
      */
     public static Histogram.Builder histogram(MeterId meterId) {
-        return new HistogramImpl.Builder(meterId);
+        return new Histogram.Builder(meterId);
     }
 
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/AbstractBuilder.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/AbstractBuilder.java
deleted file mode 100644
index 3c92aa2..0000000
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/AbstractBuilder.java
+++ /dev/null
@@ -1,98 +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.skywalking.apm.toolkit.meter.impl;
-
-import org.apache.skywalking.apm.toolkit.meter.BaseBuilder;
-import org.apache.skywalking.apm.toolkit.meter.BaseMeter;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-
-import java.util.Objects;
-
-/**
- * Help to build the meter
- */
-public abstract class AbstractBuilder<BUILDER extends BaseBuilder, BASE extends BaseMeter, IMPL extends AbstractMeter> implements BaseBuilder<BUILDER, BASE> {
-    protected final MeterId meterId;
-
-    /**
-     * Build a new meter build, meter name is required
-     */
-    public AbstractBuilder(String name) {
-        if (name == null) {
-            throw new IllegalArgumentException("Meter name cannot be null");
-        }
-        this.meterId = new MeterId(name, getType());
-    }
-
-    /**
-     * Build a new meter build from exists meter id
-     */
-    public AbstractBuilder(MeterId meterId) {
-        if (meterId == null) {
-            throw new IllegalArgumentException("Meter id cannot be null");
-        }
-        if (!Objects.equals(meterId.getType(), getType())) {
-            throw new IllegalArgumentException("Meter id type is not matches");
-        }
-        this.meterId = meterId;
-    }
-
-    /**
-     * append new tag to this meter
-     */
-    public BUILDER tag(String name, String value) {
-        meterId.getTags().add(new MeterId.Tag(name, value));
-        return (BUILDER) this;
-    }
-
-    /**
-     * Create a meter
-     */
-    protected abstract BASE create(MeterId meterId);
-
-    /**
-     * Accept the new meter when register, could use it to judge histogram buckets is correct.
-     * It's working on the same meter id only.
-     * @throws IllegalArgumentException if cannot be accept, throws information
-     */
-    protected void accept(IMPL meter) throws IllegalArgumentException {
-    }
-
-    /**
-     * Get supported build meter type
-     */
-    protected abstract MeterId.MeterType getType();
-
-    /**
-     * Get current meter id
-     */
-    public MeterId getMeterId() {
-        return meterId;
-    }
-
-    /**
-     * Build a new meter object
-     */
-    public BASE build() {
-        // sort the tags
-        this.meterId.getTags().sort(MeterId.Tag::compareTo);
-        // create or get the meter
-        return MeterCenter.getOrCreateMeter(this);
-    }
-}
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/AbstractMeter.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/AbstractMeter.java
deleted file mode 100644
index b3746b7..0000000
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/AbstractMeter.java
+++ /dev/null
@@ -1,72 +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.skywalking.apm.toolkit.meter.impl;
-
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-
-import java.util.Objects;
-
-/**
- * Base meter implementation bean
- */
-public abstract class AbstractMeter {
-
-    protected final MeterId meterId;
-
-    public AbstractMeter(MeterId meterId) {
-        this.meterId = meterId;
-    }
-
-    /**
-     * Get meter name
-     */
-    public String getName() {
-        return meterId.getName();
-    }
-
-    /**
-     * Get tag value
-     */
-    public String getTag(String tagKey) {
-        for (MeterId.Tag tag : meterId.getTags()) {
-            if (tag.getName().equals(tagKey)) {
-                return tag.getValue();
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-        AbstractMeter abstractMeter = (AbstractMeter) o;
-        return Objects.equals(meterId, abstractMeter.meterId);
-    }
-
-    public MeterId getMeterId() {
-        return meterId;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(meterId);
-    }
-
-}
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/GaugeImpl.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/GaugeImpl.java
deleted file mode 100644
index 0474398..0000000
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/GaugeImpl.java
+++ /dev/null
@@ -1,79 +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.skywalking.apm.toolkit.meter.impl;
-
-import org.apache.skywalking.apm.toolkit.meter.Gauge;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-
-import java.util.function.Supplier;
-
-/**
- * Using {@link Supplier} as the value.
- */
-public class GaugeImpl extends AbstractMeter implements Gauge {
-
-    protected Supplier<Double> getter;
-
-    public GaugeImpl(MeterId meterId, Supplier<Double> getter) {
-        super(meterId);
-        this.getter = getter;
-    }
-
-    /**
-     * Get count
-     */
-    public double get() {
-        return getter.get();
-    }
-
-    public static class Builder extends AbstractBuilder<Gauge.Builder, Gauge, GaugeImpl> implements Gauge.Builder {
-        private final Supplier<Double> getter;
-
-        public Builder(String name, Supplier<Double> getter) {
-            super(name);
-            this.getter = getter;
-        }
-
-        public Builder(MeterId meterId, Supplier<Double> getter) {
-            super(meterId);
-            this.getter = getter;
-        }
-
-        @Override
-        public void accept(GaugeImpl meter) {
-            if (this.getter != meter.getter) {
-                throw new IllegalArgumentException("Getter is not same");
-            }
-        }
-
-        @Override
-        public GaugeImpl create(MeterId meterId) {
-            if (getter == null) {
-                throw new IllegalArgumentException("getter cannot be null");
-            }
-            return new GaugeImpl(meterId, getter);
-        }
-
-        @Override
-        public MeterId.MeterType getType() {
-            return MeterId.MeterType.GAUGE;
-        }
-    }
-
-}
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/MeterCenter.java b/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/MeterCenter.java
deleted file mode 100644
index e9d538b..0000000
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/MeterCenter.java
+++ /dev/null
@@ -1,65 +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.skywalking.apm.toolkit.meter.impl;
-
-import org.apache.skywalking.apm.toolkit.meter.BaseBuilder;
-import org.apache.skywalking.apm.toolkit.meter.BaseMeter;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Management all the meter.
- */
-public class MeterCenter {
-
-    private static final Map<MeterId, BaseMeter> METER_MAP = new ConcurrentHashMap<>();
-
-    /**
-     * Get or create a new meter
-     * @return If already exists, it will return existed meter, otherwise it will register it.
-     */
-    public static <BUILDER extends BaseBuilder, BASE extends BaseMeter, IMPL extends AbstractMeter> BASE getOrCreateMeter(AbstractBuilder<BUILDER, BASE, IMPL> builder) {
-        if (builder == null) {
-            return null;
-        }
-        return (BASE) METER_MAP.compute(builder.getMeterId(), (meterId, previous) -> {
-            if (previous == null) {
-                return builder.create(meterId);
-            }
-
-            // Check previous meter is accept the new meter
-            builder.accept((IMPL) previous);
-
-            return previous;
-        });
-    }
-
-    /**
-     * Remove meter
-     * @return Meter reference if exists
-     */
-    public static BaseMeter removeMeter(MeterId id) {
-        if (id == null) {
-            return null;
-        }
-        return METER_MAP.remove(id);
-    }
-}
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/AbstractMeterTest.java b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/AbstractMeterTest.java
deleted file mode 100644
index 511af95..0000000
--- a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/AbstractMeterTest.java
+++ /dev/null
@@ -1,194 +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.skywalking.apm.toolkit.meter;
-
-import org.apache.skywalking.apm.toolkit.meter.impl.AbstractBuilder;
-import org.apache.skywalking.apm.toolkit.meter.impl.AbstractMeter;
-import org.junit.Assert;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.mockito.internal.util.reflection.Whitebox;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class AbstractMeterTest {
-
-    @Test
-    public void testBuild() {
-        // simple name and tags
-        TestCounter.Builder meterBuilder1 = Mockito.spy(TestCounter.create("test_meter"));
-        meterBuilder1.tag("k1", "v1");
-        final Counter testCounter1 = meterBuilder1.build();
-        Assert.assertNotNull(testCounter1);
-
-        verify(meterBuilder1, times(1)).create(any());
-        verify(meterBuilder1, times(0)).accept(any());
-
-        final MeterId meterId = (MeterId) Whitebox.getInternalState(testCounter1, "meterId");
-        Assert.assertNotNull(meterId);
-        Assert.assertEquals(meterId.getName(), "test_meter");
-        Assert.assertEquals(meterId.getType(), MeterId.MeterType.COUNTER);
-        Assert.assertEquals(meterId.getTags(), Arrays.asList(new MeterId.Tag("k1", "v1")));
-
-        // same name and tags
-        TestCounter.Builder meterBuilder2 = Mockito.spy(TestCounter.create("test_meter"));
-        meterBuilder2.tag("k1", "v1");
-        final Counter testCounter2 = meterBuilder2.build();
-        Assert.assertNotNull(testCounter2);
-        verify(meterBuilder2, times(0)).create(any());
-        verify(meterBuilder2, times(1)).accept(any());
-
-        // empty name
-        try {
-            TestCounter.create(null).build();
-            throw new RuntimeException();
-        } catch (IllegalArgumentException e) {
-        } catch (Exception e) {
-            throw e;
-        }
-
-        // correct meter id
-        final MeterId tmpMeterId = new MeterId("test_meter_builder", MeterId.MeterType.COUNTER, Collections.emptyList());
-        new TestCounter.Builder(tmpMeterId).build();
-
-        final MeterId copiedMeterId = tmpMeterId.copyTo("test_meter_builder", MeterId.MeterType.GAUGE);
-        // not matched type
-        try {
-            new TestCounter.Builder(copiedMeterId).build();
-            throw new RuntimeException();
-        } catch (IllegalArgumentException e) {
-        } catch (Exception e) {
-            throw e;
-        }
-
-        // empty meterId
-        try {
-            MeterId emptyId = null;
-            new TestCounter.Builder(emptyId).build();
-            throw new RuntimeException();
-        } catch (IllegalArgumentException e) {
-        } catch (Exception e) {
-            throw e;
-        }
-    }
-
-    @Test
-    public void testEquals() {
-        // same name
-        Assert.assertEquals(
-            TestCounter.create("test").build(),
-            TestCounter.create("test").build()
-        );
-
-        // same name and tag
-        Assert.assertEquals(
-            TestCounter.create("test").tag("k1", "v1").build(),
-            TestCounter.create("test").tag("k1", "v1").build()
-        );
-
-        // not orders tags
-        Assert.assertEquals(
-            TestCounter.create("test").tag("k2", "v2").tag("k3", "v3").build(),
-            TestCounter.create("test").tag("k3", "v3").tag("k2", "v2").build()
-        );
-
-        // not same name
-        Assert.assertNotEquals(
-            TestCounter.create("test1").build(),
-            TestCounter.create("test2").build()
-        );
-
-        // same name, not same tag
-        Assert.assertNotEquals(
-            TestCounter.create("test3").tag("k1", "v1").build(),
-            TestCounter.create("test4").tag("k1", "v2").build()
-        );
-    }
-
-    @Test
-    public void testGetName() {
-        final Counter meter = TestCounter.create("test").build();
-        Assert.assertEquals(meter.getName(), "test");
-    }
-
-    @Test
-    public void testGetTag() {
-        final Counter meter = TestCounter.create("test").tag("k1", "v1").build();
-        Assert.assertEquals(meter.getTag("k1"), "v1");
-        Assert.assertNull(meter.getTag("k2"));
-    }
-
-    @Test
-    public void testGetMeterId() {
-        final Counter meter = TestCounter.create("test").tag("k1", "v1").build();
-        final MeterId tmpMeterId = new MeterId("test", MeterId.MeterType.COUNTER,
-            Arrays.asList(new MeterId.Tag("k1", "v1")));
-        final TestCounter counter = (TestCounter) meter;
-        Assert.assertEquals(tmpMeterId, counter.getMeterId());
-    }
-
-    private static class TestCounter extends AbstractMeter implements Counter {
-        private TestCounter(MeterId meterId) {
-            super(meterId);
-        }
-
-        public static TestCounter.Builder create(String name) {
-            return new Builder(name);
-        }
-
-        @Override
-        public void increment(double count) {
-        }
-
-        @Override
-        public double get() {
-            return 0;
-        }
-
-        public static class Builder extends AbstractBuilder<Builder, Counter, TestCounter> {
-
-            public Builder(String name) {
-                super(name);
-            }
-
-            public Builder(MeterId meterId) {
-                super(meterId);
-            }
-
-            @Override
-            public TestCounter create(MeterId meterId) {
-                return new TestCounter(meterId);
-            }
-
-            @Override
-            protected void accept(TestCounter meter) throws IllegalArgumentException {
-            }
-
-            @Override
-            public MeterId.MeterType getType() {
-                return MeterId.MeterType.COUNTER;
-            }
-        }
-    }
-}
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/CounterTest.java b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/CounterTest.java
index 572c478..5e911e3 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/CounterTest.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/CounterTest.java
@@ -18,100 +18,13 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
-import org.junit.Assert;
 import org.junit.Test;
 
-import java.util.Arrays;
-
 public class CounterTest {
 
     @Test
     public void testBuild() {
-        Counter counter1 = MeterFactory.counter("test_counter").tag("k1", "v1").build();
-        Assert.assertNotNull(counter1);
-
-        final Counter counter2 = MeterFactory.counter(new MeterId("test_counter", MeterId.MeterType.COUNTER, Arrays.asList(new MeterId.Tag("k1", "v1")))).build();
-        Assert.assertNotNull(counter2);
-        Assert.assertEquals(counter1, counter2);
-    }
-
-    @Test
-    public void testIncrement() {
-        Counter counter = MeterFactory.counter("test_counter1").tag("k1", "v1").build();
-        counter.increment(1);
-        Assert.assertEquals(counter.get(), 1d, 0.0);
-
-        counter.increment(1.5);
-        Assert.assertEquals(counter.get(), 2.5d, 0.0);
-
-        counter.increment(-1d);
-        Assert.assertEquals(counter.get(), 1.5d, 0.0);
-    }
-
-    @Test
-    public void testAccept() {
-        Counter counter = MeterFactory.counter("test_counter_accept")
-            .tag("k1", "v1")
-            .mode(Counter.Mode.INCREMENT)
-            .build();
-
-        // Check the same mode
-        try {
-            MeterFactory.counter("test_counter_accept")
-                .tag("k1", "v1")
-                .mode(Counter.Mode.INCREMENT)
-                .build();
-        } catch (IllegalArgumentException e) {
-            throw e;
-        } catch (Exception e) {
-        }
-
-        // Check the different mode
-        try {
-            MeterFactory.counter("test_counter_accept")
-                .tag("k1", "v1")
-                .mode(Counter.Mode.RATE)
-                .build();
-            throw new IllegalStateException();
-        } catch (IllegalStateException e) {
-            throw e;
-        } catch (Exception e) {
-        }
-    }
-
-    @Test
-    public void testAgentGetWithoutRate() {
-        final Counter counter = MeterFactory.counter("test_counter_without_rate")
-            .tag("k1", "v1")
-            .build();
-
-        final CounterImpl counterImpl = (CounterImpl) counter;
-        counter.increment(1);
-        Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
-        Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
-
-        counter.increment(1.5);
-        counter.increment(-0.5);
-        Assert.assertEquals(counterImpl.agentGet(), 2d, 0.0);
-        Assert.assertEquals(counterImpl.agentGet(), 2d, 0.0);
-    }
-
-    @Test
-    public void testAgentGetWithRate() {
-        final Counter counter = MeterFactory.counter("test_counter_with_rate")
-            .tag("k1", "v1")
-            .mode(Counter.Mode.RATE).build();
-
-        final CounterImpl counterImpl = (CounterImpl) counter;
-        counter.increment(1);
-        Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
-        Assert.assertEquals(counterImpl.agentGet(), 0d, 0.0);
-
-        counter.increment(1.5);
-        counter.increment(-0.5);
-        Assert.assertEquals(counterImpl.agentGet(), 1d, 0.0);
-        Assert.assertEquals(counterImpl.agentGet(), 0d, 0.0);
+        MeterFactory.counter("test_counter").tag("k1", "v1").build();
     }
 
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/GaugeTest.java b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/GaugeTest.java
index bc707d3..1e0e4e6 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/GaugeTest.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/GaugeTest.java
@@ -18,55 +18,13 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-import org.junit.Assert;
 import org.junit.Test;
 
-import java.util.Collections;
-
 public class GaugeTest {
 
     @Test
     public void testBuild() {
-        Gauge gauge = MeterFactory.gauge("test_gauge1", () -> 1d).tag("k1", "v1").build();
-        Assert.assertNotNull(gauge);
-
-        // Same meter name and new getter
-        try {
-            MeterFactory.gauge("test_gauge1", () -> 1d).tag("k1", "v1").build();
-            throw new IllegalStateException();
-        } catch (IllegalStateException e) {
-            throw e;
-        } catch (Exception e) {
-        }
-
-        // Missing getter reference
-        try {
-            MeterFactory.gauge("test_gauge2", null).build();
-            throw new IllegalStateException();
-        } catch (IllegalStateException e) {
-            throw e;
-        } catch (Exception e) {
-        }
-
-        // Build by meterId
-        final Gauge gauge1 = MeterFactory.gauge(new MeterId("test_gauge3", MeterId.MeterType.GAUGE, Collections.emptyList()), () -> 1d).build();
-        Assert.assertNotNull(gauge1);
-    }
-
-    @Test
-    public void testGet() {
-        Gauge gauge = MeterFactory.gauge("test_gauge3", () -> 1d).tag("k1", "v1").build();
-        Assert.assertEquals(gauge.get(), 1d, 0.0);
-
-        // Need throw exception
-        gauge = MeterFactory.gauge("test_gauge4", () -> Double.valueOf(1 / 0)).build();
-        try {
-            gauge.get();
-            throw new IllegalStateException();
-        } catch (IllegalStateException e) {
-            throw e;
-        } catch (Exception e) {
-        }
+        MeterFactory.gauge("test_gauge1", () -> 1d).tag("k1", "v1").build();
     }
 
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/HistogramTest.java b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/HistogramTest.java
index 89d0980..46c2c1e 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/HistogramTest.java
+++ b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/HistogramTest.java
@@ -18,114 +18,17 @@
 
 package org.apache.skywalking.apm.toolkit.meter;
 
-import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
-import org.junit.Assert;
 import org.junit.Test;
 
 import java.util.Arrays;
-import java.util.Collections;
 
 public class HistogramTest {
 
     @Test
     public void testBuild() {
         // normal
-        Histogram histogram = MeterFactory.histogram("test_histogram1").steps(Arrays.asList(1d, 5d, 10d)).minValue(-10)
+        MeterFactory.histogram("test_histogram1").steps(Arrays.asList(1d, 5d, 10d)).minValue(-10)
             .tag("k1", "v1").build();
-        verifyHistogram(histogram, -10d, 0, 1d, 0, 5d, 0, 10d, 0);
-
-        // except value bigger than first bucket
-        try {
-            histogram = HistogramImpl.create("test_histogram2").steps(Arrays.asList(1d, 5d, 10d)).minValue(2).build();
-            throw new IllegalStateException("valid failed");
-        } catch (IllegalStateException e) {
-            throw e;
-        } catch (Exception e) {
-            Assert.assertTrue(e instanceof IllegalArgumentException);
-        }
-
-        // except min value is equals first step
-        histogram = HistogramImpl.create("test_histogram3").steps(Arrays.asList(1d, 5d, 10d)).minValue(1d)
-            .tag("k1", "v1").build();
-        verifyHistogram(histogram, 1d, 0, 5d, 0, 10d, 0);
-
-        // empty step
-        try {
-            HistogramImpl.create("test").build();
-            throw new IllegalStateException();
-        } catch (IllegalStateException e) {
-            throw e;
-        } catch (Exception e) {
-            Assert.assertTrue(e instanceof IllegalArgumentException);
-        }
-
-        // Build by meterId
-        histogram = MeterFactory.histogram(new MeterId("test_histogram4", MeterId.MeterType.HISTOGRAM, Collections.emptyList()))
-            .steps(Arrays.asList(1d, 5d, 10d)).minValue(0d).build();
-        Assert.assertNotNull(histogram);
-    }
-
-    @Test
-    public void testAccept() {
-        MeterFactory.histogram("test_histogram_accept").steps(Arrays.asList(1d, 3d, 5d)).minValue(0).build();
-
-        // same histogram
-        HistogramImpl.create("test_histogram_accept").steps(Arrays.asList(1d, 3d, 5d)).minValue(0).build();
-
-        // not same steps size
-        try {
-            HistogramImpl.create("test_histogram_accept").steps(Arrays.asList(1d, 3d, 5d, 7d)).minValue(-1).build();
-        } catch (IllegalArgumentException e) {
-        } catch (Exception e) {
-            throw e;
-        }
-
-        // not same steps value
-        try {
-            HistogramImpl.create("test_histogram_accept").steps(Arrays.asList(1d, 3d, 6d)).minValue(-1).build();
-        } catch (IllegalArgumentException e) {
-        } catch (Exception e) {
-            throw e;
-        }
-    }
-
-    @Test
-    public void testAddValue() {
-        Histogram histogram = MeterFactory.histogram("test_histogram5").steps(Arrays.asList(1d, 5d, 10d)).minValue(-10)
-            .tag("k1", "v1").build();
-
-        // single value
-        histogram.addValue(2);
-        verifyHistogram(histogram, -10d, 0L, 1d, 1L, 5d, 0L, 10d, 0L);
-
-        // multiple values
-        histogram.addValue(2);
-        histogram.addValue(2);
-        histogram.addValue(9);
-        verifyHistogram(histogram, -10d, 0L, 1d, 3L, 5d, 1L, 10d, 0L);
-
-        // un-support value
-        histogram.addValue(-11);
-        verifyHistogram(histogram, -10d, 0L, 1d, 3L, 5d, 1L, 10d, 0L);
-
-        // max value
-        histogram.addValue(Integer.MAX_VALUE);
-        histogram.addValue(9);
-        histogram.addValue(10);
-        verifyHistogram(histogram, -10d, 0L, 1d, 3L, 5d, 2L, 10d, 2L);
     }
 
-    /**
-     * Verify histogram bucket counts
-     */
-    public static void verifyHistogram(Histogram histogram, double... buckets) {
-        Assert.assertNotNull(histogram);
-        final Histogram.Bucket[] histogramBuckets = histogram.getBuckets();
-        Assert.assertEquals(histogramBuckets.length, buckets.length / 2);
-        for (int i = 0; i < histogramBuckets.length; i++) {
-            Assert.assertNotNull(buckets[i]);
-            Assert.assertEquals(buckets[i * 2], histogramBuckets[i].getBucket(), 0.0);
-            Assert.assertEquals(buckets[i * 2 + 1], histogramBuckets[i].getCount(), 0.0);
-        }
-    }
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/MeterCenterTest.java b/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/MeterCenterTest.java
deleted file mode 100644
index 58f19ad..0000000
--- a/apm-application-toolkit/apm-toolkit-meter/src/test/java/org/apache/skywalking/apm/toolkit/meter/MeterCenterTest.java
+++ /dev/null
@@ -1,76 +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.skywalking.apm.toolkit.meter;
-
-import org.apache.skywalking.apm.toolkit.meter.impl.AbstractMeter;
-import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.powermock.reflect.Whitebox;
-
-import java.util.Collections;
-import java.util.Map;
-
-public class MeterCenterTest {
-
-    private Map<MeterId, AbstractMeter> meterMap;
-
-    @Before
-    public void setup() {
-        meterMap = Whitebox.getInternalState(MeterCenter.class, "METER_MAP");
-        meterMap.clear();
-    }
-
-    @Test
-    public void testCreateOrGet() {
-        // null
-        Assert.assertNull(MeterCenter.getOrCreateMeter(null));
-
-        // simple counter
-        final Counter counter = MeterFactory.counter("test").build();
-        final MeterId counterMeterId = Whitebox.getInternalState(counter, "meterId");
-        Assert.assertNotNull(counterMeterId);
-        Assert.assertNotNull(meterMap.get(counterMeterId));
-        Assert.assertEquals(meterMap.get(counterMeterId), counter);
-
-        // same counter
-        Assert.assertEquals(counter, MeterFactory.counter("test").build());
-        Assert.assertEquals(meterMap.size(), 1);
-        Assert.assertNotNull(meterMap.get(counterMeterId));
-        Assert.assertEquals(meterMap.get(counterMeterId), counter);
-    }
-
-    @Test
-    public void testRemoveMeter() {
-        final Counter counter = MeterFactory.counter("test").build();
-        Assert.assertEquals(meterMap.size(), 1);
-        final MeterId counterMeterId = Whitebox.getInternalState(counter, "meterId");
-        MeterCenter.removeMeter(counterMeterId);
-        Assert.assertEquals(meterMap.size(), 0);
-
-        // not registered meter id
-        final MeterId newMeterId = new MeterId("test1", MeterId.MeterType.COUNTER, Collections.emptyList());
-        MeterCenter.removeMeter(newMeterId);
-        Assert.assertEquals(meterMap.size(), 0);
-
-        // remove null
-        MeterCenter.removeMeter(null);
-    }
-}
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounter.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounter.java
index a887006..45563ab 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounter.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounter.java
@@ -20,10 +20,9 @@ package org.apache.skywalking.apm.meter.micrometer;
 
 import io.micrometer.core.instrument.AbstractMeter;
 import org.apache.skywalking.apm.toolkit.meter.Counter;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
 
 /**
- * Wrapper the {@link CounterImpl} to {@link io.micrometer.core.instrument.Counter}
+ * Wrapper the {@link Counter} to {@link io.micrometer.core.instrument.Counter}
  */
 public class SkywalkingCounter extends AbstractMeter implements io.micrometer.core.instrument.Counter {
     private final Counter counter;
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounter.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounter.java
index 0efde2f..5a2baf6 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounter.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounter.java
@@ -19,15 +19,14 @@
 package org.apache.skywalking.apm.meter.micrometer;
 
 import io.micrometer.core.instrument.Measurement;
+import org.apache.skywalking.apm.toolkit.meter.BaseBuilder;
 import org.apache.skywalking.apm.toolkit.meter.Counter;
-import org.apache.skywalking.apm.toolkit.meter.impl.AbstractBuilder;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 
 /**
  * Work for custom {@link Measurement}, support the skywalking rate mode
  */
-public class SkywalkingCustomCounter extends CounterImpl {
+public class SkywalkingCustomCounter extends Counter {
 
     private final Measurement measurement;
 
@@ -44,7 +43,7 @@ public class SkywalkingCustomCounter extends CounterImpl {
     /**
      * Custom counter builder
      */
-    public static class Builder extends AbstractBuilder<Builder, Counter, SkywalkingCustomCounter> {
+    public static class Builder extends BaseBuilder<Builder, Counter> {
         private final Measurement measurement;
         private final SkywalkingConfig config;
 
@@ -55,13 +54,13 @@ public class SkywalkingCustomCounter extends CounterImpl {
         }
 
         @Override
-        protected SkywalkingCustomCounter create(MeterId meterId) {
-            return new SkywalkingCustomCounter(meterId, measurement, config);
+        protected MeterId.MeterType getType() {
+            return MeterId.MeterType.COUNTER;
         }
 
         @Override
-        protected MeterId.MeterType getType() {
-            return MeterId.MeterType.COUNTER;
+        protected Counter create() {
+            return new SkywalkingCustomCounter(meterId, measurement, config);
         }
     }
 }
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistry.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistry.java
index 9b2d323..5ece4f8 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistry.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/main/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistry.java
@@ -36,7 +36,7 @@ import io.micrometer.core.instrument.distribution.pause.PauseDetector;
 import io.micrometer.core.instrument.internal.DefaultGauge;
 import io.micrometer.core.instrument.internal.DefaultMeter;
 import org.apache.skywalking.apm.toolkit.meter.MeterFactory;
-import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
+import org.apache.skywalking.apm.toolkit.meter.MeterCenter;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 
 import java.util.concurrent.TimeUnit;
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/MeterBuilderTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/MeterBuilderTest.java
index 144685d..d32481e 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/MeterBuilderTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/MeterBuilderTest.java
@@ -43,21 +43,10 @@ public class MeterBuilderTest {
             .serviceLevelObjectives(Duration.ofMillis(1).toNanos(), Duration.ofMillis(5).toNanos(), Duration.ofMillis(10).toNanos())
             .minimumExpectedValue(0d).build();
 
-        // Check buckets
+        // Check histogram
         final Optional<Histogram> histogramOptional = MeterBuilder.buildHistogram(meterId, true, statisticConfig, true);
         final Histogram histogram = histogramOptional.orElse(null);
         Assert.assertNotNull(histogram);
-        final Histogram.Bucket[] buckets = histogram.getBuckets();
-        Assert.assertEquals(4, buckets.length);
-        Assert.assertEquals(0d, buckets[0].getBucket(), 0.0);
-        Assert.assertEquals(1d, buckets[1].getBucket(), 0.0);
-        Assert.assertEquals(5d, buckets[2].getBucket(), 0.0);
-        Assert.assertEquals(10d, buckets[3].getBucket(), 0.0);
-
-        // Check meter id
-        Assert.assertEquals("test_histogram", histogram.getMeterId().getName());
-        Assert.assertEquals(MeterId.MeterType.HISTOGRAM, histogram.getMeterId().getType());
-        Assert.assertEquals(Arrays.asList(new MeterId.Tag("k1", "v1")), histogram.getMeterId().getTags());
 
         // Don't need the histogram
         Assert.assertNull(MeterBuilder.buildHistogram(meterId, true, DistributionStatisticConfig.DEFAULT, true).orElse(null));
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounterTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounterTest.java
index 536bd2a..e1cdaed 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounterTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCounterTest.java
@@ -19,16 +19,13 @@
 package org.apache.skywalking.apm.meter.micrometer;
 
 import io.micrometer.core.instrument.Counter;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
 import org.junit.Assert;
 import org.junit.Test;
 import org.powermock.reflect.Whitebox;
 
 import java.util.Arrays;
-import java.util.List;
 
-public class SkywalkingCounterTest extends SkywalkingMeterBaseTest {
+public class SkywalkingCounterTest {
 
     @Test
     public void testCounter() {
@@ -41,19 +38,7 @@ public class SkywalkingCounterTest extends SkywalkingMeterBaseTest {
         final SkywalkingCounter skywalkingCounter = (SkywalkingCounter) counter;
         final org.apache.skywalking.apm.toolkit.meter.Counter realCounter =
             Whitebox.getInternalState(skywalkingCounter, "counter");
-
-        final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
-
-        // Simplify increment
-        skywalkingCounter.increment(1d);
-        assertCounter(realCounter, "test_counter", tags, 1);
-        Assert.assertEquals(1d, skywalkingCounter.count(), 0.0);
-
-        // Multiple increment
-        skywalkingCounter.increment(2d);
-        skywalkingCounter.increment(3d);
-        assertCounter(realCounter, "test_counter", tags, 6);
-        Assert.assertEquals(6d, skywalkingCounter.count(), 0.0);
+        Assert.assertNotNull(realCounter);
     }
 
     @Test
@@ -64,11 +49,8 @@ public class SkywalkingCounterTest extends SkywalkingMeterBaseTest {
         // Check Skywalking counter type
         Assert.assertTrue(counter instanceof SkywalkingCounter);
         final SkywalkingCounter skywalkingCounter = (SkywalkingCounter) counter;
-        final CounterImpl realCounter =
+        final org.apache.skywalking.apm.toolkit.meter.Counter realCounter =
             Whitebox.getInternalState(skywalkingCounter, "counter");
-
-        // check mode
-        final org.apache.skywalking.apm.toolkit.meter.Counter.Mode counterMode = Whitebox.getInternalState(realCounter, "mode");
-        Assert.assertEquals(org.apache.skywalking.apm.toolkit.meter.Counter.Mode.RATE, counterMode);
+        Assert.assertNotNull(realCounter);
     }
 }
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounterTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounterTest.java
index ff88024..5912f15 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounterTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingCustomCounterTest.java
@@ -22,12 +22,13 @@ import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.Statistic;
 import org.apache.skywalking.apm.toolkit.meter.Counter;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
+import org.junit.Assert;
 import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.List;
 
-public class SkywalkingCustomCounterTest extends SkywalkingMeterBaseTest {
+public class SkywalkingCustomCounterTest {
 
     @Test
     public void testBuild() {
@@ -36,8 +37,6 @@ public class SkywalkingCustomCounterTest extends SkywalkingMeterBaseTest {
         final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "custom_counter"));
         final MeterId meterId = new MeterId("test_custom_conter", MeterId.MeterType.COUNTER, tags);
         final Counter counter = new SkywalkingCustomCounter.Builder(meterId, measurement, SkywalkingConfig.DEFAULT).build();
-
-        // Check is counter meter id and value
-        assertCounter(counter, "test_custom_conter", tags, 1d);
+        Assert.assertNotNull(counter);
     }
 }
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingDistributionSummaryTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingDistributionSummaryTest.java
index 693dacb..e87d7fe 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingDistributionSummaryTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingDistributionSummaryTest.java
@@ -22,12 +22,11 @@ import io.micrometer.core.instrument.DistributionSummary;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 import org.junit.Assert;
 import org.junit.Test;
-import org.powermock.reflect.Whitebox;
 
 import java.util.Arrays;
 import java.util.List;
 
-public class SkywalkingDistributionSummaryTest extends SkywalkingMeterBaseTest {
+public class SkywalkingDistributionSummaryTest {
 
     @Test
     public void testSimple() {
@@ -43,17 +42,6 @@ public class SkywalkingDistributionSummaryTest extends SkywalkingMeterBaseTest {
         summary.record(10d);
         summary.record(13d);
         summary.record(2d);
-
-        // Check micrometer data
-        Assert.assertEquals(3, summary.count());
-        Assert.assertEquals(25d, summary.totalAmount(), 0.0);
-        Assert.assertEquals(13d, summary.max(), 0.0);
-
-        // Check Skywalking data
-        assertCounter(Whitebox.getInternalState(summary, "counter"), "test_simple_distribution_summary_count", tags, 3d);
-        assertCounter(Whitebox.getInternalState(summary, "sum"), "test_simple_distribution_summary_sum", tags, 25d);
-        assertGauge(Whitebox.getInternalState(summary, "max"), "test_simple_distribution_summary_max", tags, 13d);
-        assertHistogramNull(Whitebox.getInternalState(summary, "histogram"));
     }
 
     @Test
@@ -73,16 +61,5 @@ public class SkywalkingDistributionSummaryTest extends SkywalkingMeterBaseTest {
         summary.record(10d);
         summary.record(13d);
         summary.record(2d);
-
-        // Check micrometer data
-        Assert.assertEquals(3, summary.count());
-        Assert.assertEquals(25d, summary.totalAmount(), 0.0);
-        Assert.assertEquals(13d, summary.max(), 0.0);
-
-        // Check Skywalking data
-        assertCounter(Whitebox.getInternalState(summary, "counter"), "test_complex_distribution_summary_count", tags, 3d);
-        assertCounter(Whitebox.getInternalState(summary, "sum"), "test_complex_distribution_summary_sum", tags, 25d);
-        assertGauge(Whitebox.getInternalState(summary, "max"), "test_complex_distribution_summary_max", tags, 13d);
-        assertHistogram(Whitebox.getInternalState(summary, "histogram"), "test_complex_distribution_summary_histogram", tags, 1, 1, 10, 2, 20, 0);
     }
 }
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingLongTaskTimerTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingLongTaskTimerTest.java
index 35148a5..5b16332 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingLongTaskTimerTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingLongTaskTimerTest.java
@@ -19,29 +19,12 @@
 package org.apache.skywalking.apm.meter.micrometer;
 
 import io.micrometer.core.instrument.LongTaskTimer;
-import org.apache.skywalking.apm.toolkit.meter.Gauge;
-import org.apache.skywalking.apm.toolkit.meter.impl.AbstractMeter;
-import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
 import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
-import org.powermock.reflect.Whitebox;
 
-import java.util.Arrays;
-import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
-public class SkywalkingLongTaskTimerTest extends SkywalkingMeterBaseTest {
-
-    private Map<MeterId, AbstractMeter> meterMap;
-
-    @Before
-    public void setup() {
-        // Need to clear all of the meter, long task timer has some meter not field field reference
-        meterMap = Whitebox.getInternalState(MeterCenter.class, "METER_MAP");
-        meterMap.clear();
-    }
+public class SkywalkingLongTaskTimerTest {
 
     @Test
     public void testSimple() throws InterruptedException {
@@ -65,13 +48,6 @@ public class SkywalkingLongTaskTimerTest extends SkywalkingMeterBaseTest {
         Assert.assertTrue(timer.duration(TimeUnit.MILLISECONDS) > 0);
         Assert.assertTrue(timer.max(TimeUnit.MILLISECONDS) > 0);
 
-        // Check Skywalking data
-        assertGauge((Gauge) meterMap.values().stream().filter(m -> m.getName().endsWith("_active_count")).findFirst().orElse(null),
-            "test_simple_long_task_timer_active_count", Arrays.asList(new MeterId.Tag("skywalking", "test")), 1);
-        assertGauge((Gauge) meterMap.values().stream().filter(m -> m.getName().endsWith("_duration_sum")).findFirst().orElse(null),
-            "test_simple_long_task_timer_duration_sum", Arrays.asList(new MeterId.Tag("skywalking", "test")), 0, true);
-        assertGauge((Gauge) meterMap.values().stream().filter(m -> m.getName().endsWith("_max")).findFirst().orElse(null),
-            "test_simple_long_task_timer_max", Arrays.asList(new MeterId.Tag("skywalking", "test")), 0, true);
     }
 
     // Add long time task
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterBaseTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterBaseTest.java
deleted file mode 100644
index 454b923..0000000
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterBaseTest.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.skywalking.apm.meter.micrometer;
-
-import org.apache.skywalking.apm.toolkit.meter.Counter;
-import org.apache.skywalking.apm.toolkit.meter.Gauge;
-import org.apache.skywalking.apm.toolkit.meter.Histogram;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-import org.junit.Assert;
-
-import java.util.List;
-import java.util.Optional;
-
-public class SkywalkingMeterBaseTest {
-
-    /**
-     * Check counter data
-     */
-    public void assertCounter(Counter counter, String name, List<MeterId.Tag> tags, double count) {
-        Assert.assertEquals(name, counter.getMeterId().getName());
-        Assert.assertEquals(tags, counter.getMeterId().getTags());
-        Assert.assertEquals(MeterId.MeterType.COUNTER, counter.getMeterId().getType());
-
-        Assert.assertEquals(count, counter.get(), 0.0);
-    }
-
-    /**
-     * Check gauge data, and value must be same
-     */
-    public void assertGauge(Gauge gauge, String name, List<MeterId.Tag> tags, double value) {
-        assertGauge(gauge, name, tags, value, false);
-    }
-
-    /**
-     * Check gauge data, and value could greater than provide value
-     */
-    public void assertGauge(Gauge gauge, String name, List<MeterId.Tag> tags, double value, boolean greaterThanValueMode) {
-        Assert.assertEquals(name, gauge.getMeterId().getName());
-        Assert.assertEquals(tags, gauge.getMeterId().getTags());
-        Assert.assertEquals(MeterId.MeterType.GAUGE, gauge.getMeterId().getType());
-
-        if (greaterThanValueMode) {
-            Assert.assertTrue(gauge.get() > value);
-        } else {
-            Assert.assertEquals(value, gauge.get(), 0.0);
-        }
-    }
-
-    /**
-     * Check not have histogram
-     */
-    public void assertHistogramNull(Optional<Histogram> histogramOptional) {
-        Assert.assertNull(histogramOptional.orElse(null));
-    }
-
-    /**
-     * Check histogram cannot be null and data correct
-     * @param bucketsAndCount bucket and value array
-     */
-    public void assertHistogram(Optional<Histogram> histogramOptional, String name, List<MeterId.Tag> tags, double... bucketsAndCount) {
-        final Histogram histogram = histogramOptional.orElse(null);
-        Assert.assertNotNull(histogram);
-        Assert.assertEquals(name, histogram.getMeterId().getName());
-        Assert.assertEquals(tags, histogram.getMeterId().getTags());
-        Assert.assertEquals(MeterId.MeterType.HISTOGRAM, histogram.getMeterId().getType());
-
-        final Histogram.Bucket[] buckets = histogram.getBuckets();
-        Assert.assertEquals(bucketsAndCount.length / 2, buckets.length);
-        for (int i = 0; i < buckets.length; i++) {
-            Assert.assertEquals(bucketsAndCount[i * 2], buckets[i].getBucket(), 0.0);
-            Assert.assertEquals((long) bucketsAndCount[i * 2 + 1], buckets[i].getCount());
-        }
-    }
-
-}
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistryTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistryTest.java
index 8604b31..3d23780 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistryTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingMeterRegistryTest.java
@@ -22,56 +22,21 @@ import io.micrometer.core.instrument.Measurement;
 import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.Statistic;
 import io.micrometer.core.instrument.Tags;
-import org.apache.skywalking.apm.toolkit.meter.BaseMeter;
-import org.apache.skywalking.apm.toolkit.meter.Counter;
-import org.apache.skywalking.apm.toolkit.meter.Gauge;
-import org.apache.skywalking.apm.toolkit.meter.impl.MeterCenter;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Before;
 import org.junit.Test;
-import org.powermock.reflect.Whitebox;
 
 import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
 import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
 
 /**
  * Only test in build-in meters
  */
-public class SkywalkingMeterRegistryTest extends SkywalkingMeterBaseTest {
-
-    private Map<MeterId, BaseMeter> meterMap;
-
-    @Before
-    public void setup() {
-        // Make sure meters are clear
-        meterMap = Whitebox.getInternalState(MeterCenter.class, "METER_MAP");
-        meterMap.clear();
-    }
-
-    @After
-    public void cleanup() {
-        // Clear meters after finish each test case
-        meterMap.clear();
-    }
+public class SkywalkingMeterRegistryTest {
 
     @Test
     public void testGauge() {
         final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
         final GaugeTestBean gaugeTestBean = new GaugeTestBean(1d);
         registry.gauge("test_counter", gaugeTestBean, GaugeTestBean::getCount);
-
-        // Check meter and count
-        Assert.assertEquals(1, meterMap.size());
-        final BaseMeter meter = meterMap.values().iterator().next();
-        Assert.assertTrue(meter instanceof Gauge);
-        final Gauge gauge = (Gauge) meter;
-
-        Assert.assertEquals(1d, gauge.get(), 0.0);
     }
 
     @Test
@@ -80,23 +45,6 @@ public class SkywalkingMeterRegistryTest extends SkywalkingMeterBaseTest {
         final FunctionTimerBean task = new FunctionTimerBean(1, 200);
         registry.more().timer("test_function_timer", Tags.of("skywalking", "test"), task,
             FunctionTimerBean::getCount, FunctionTimerBean::getTotalTime, TimeUnit.MILLISECONDS);
-        final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
-
-        // Check is has appoint meter
-        Assert.assertEquals(2, meterMap.size());
-        Gauge countGauge = null;
-        Gauge sumGauge = null;
-        for (BaseMeter meter : meterMap.values()) {
-            if (meter.getName().endsWith("count")) {
-                countGauge = (Gauge) meter;
-            } else if (meter.getName().endsWith("sum")) {
-                sumGauge = (Gauge) meter;
-            }
-        }
-
-        // Check data
-        assertGauge(countGauge, "test_function_timer_count", tags, 1);
-        assertGauge(sumGauge, "test_function_timer_sum", tags, 200);
     }
 
     @Test
@@ -105,82 +53,41 @@ public class SkywalkingMeterRegistryTest extends SkywalkingMeterBaseTest {
         final FunctionTimerBean task = new FunctionTimerBean(1, 200);
         registry.more().counter("test_function_counter", Tags.of("skywalking", "test"), task,
             FunctionTimerBean::getCount);
-        final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
-
-        // Check meter and count
-        Assert.assertEquals(1, meterMap.size());
-        Counter countGauge = (Counter) meterMap.values().iterator().next();
-
-        // Check data
-        assertCounter(countGauge, "test_function_counter", tags, 1);
     }
 
     @Test
     public void testNewMeterSum() {
         // sum
-        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.TOTAL, data -> {
-            assertCounter((Counter) data.getMeter(),
-                "test_meter_sum", data.getTags(), 1d);
-        });
+        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.TOTAL);
 
         // count
-        testNewMeter("test_meter", Meter.Type.COUNTER, Statistic.COUNT, data -> {
-            assertCounter((Counter) data.getMeter(),
-                "test_meter", data.getTags(), 1d);
-        });
+        testNewMeter("test_meter", Meter.Type.COUNTER, Statistic.COUNT);
 
         // max
-        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.MAX, data -> {
-            assertGauge((Gauge) data.getMeter(),
-                "test_meter_max", data.getTags(), 1d);
-        });
+        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.MAX);
 
         // activeCount
-        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.ACTIVE_TASKS, data -> {
-            assertGauge((Gauge) data.getMeter(),
-                "test_meter_active_count", data.getTags(), 1d);
-        });
+        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.ACTIVE_TASKS);
 
         // durationSum
-        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.DURATION, data -> {
-            assertGauge((Gauge) data.getMeter(),
-                "test_meter_duration_sum", data.getTags(), 1d);
-        });
+        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.DURATION);
 
         // others
-        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.VALUE, data -> {
-            assertGauge((Gauge) data.getMeter(),
-                "test_meter", data.getTags(), 1d);
-        });
+        testNewMeter("test_meter", Meter.Type.GAUGE, Statistic.VALUE);
     }
 
     /**
      * Check custom measurement
      */
-    private void testNewMeter(String meterName, Meter.Type type, Statistic statistic, Consumer<MeterData> meterChecker) {
+    private void testNewMeter(String meterName, Meter.Type type, Statistic statistic) {
         final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
 
         // Create measurement
         Meter.builder(meterName, type, Arrays.asList(new Measurement(() -> 1d, statistic)))
             .tag("skywalking", "test")
             .register(registry);
-        final List<MeterId.Tag> tags = Arrays.asList(new MeterId.Tag("skywalking", "test"));
-        Assert.assertEquals(1, meterMap.size());
-        meterChecker.accept(new MeterData(meterMap.values().iterator().next(), tags));
-
-        // clear all data
-        cleanup();
     }
 
-    @Test
-    public void testRemove() {
-        final SkywalkingMeterRegistry registry = new SkywalkingMeterRegistry();
-        final io.micrometer.core.instrument.Counter counter = registry.counter("test_remove_counter");
-        Assert.assertEquals(1, meterMap.size());
-
-        registry.remove(counter.getId());
-        Assert.assertEquals(0, meterMap.size());
-    }
 
     /**
      * Working on {@link io.micrometer.core.instrument.Gauge} check
@@ -218,24 +125,4 @@ public class SkywalkingMeterRegistryTest extends SkywalkingMeterBaseTest {
         }
     }
 
-    /**
-     * Working on custom {@link Measurement} check
-     */
-    private static class MeterData {
-        private final BaseMeter meter;
-        private final List<MeterId.Tag> tags;
-
-        public MeterData(BaseMeter meter, List<MeterId.Tag> tags) {
-            this.meter = meter;
-            this.tags = tags;
-        }
-
-        public BaseMeter getMeter() {
-            return meter;
-        }
-
-        public List<MeterId.Tag> getTags() {
-            return tags;
-        }
-    }
 }
diff --git a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingTimerTest.java b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingTimerTest.java
index e4dedd2..a971dec 100644
--- a/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingTimerTest.java
+++ b/apm-application-toolkit/apm-toolkit-micrometer-registry/src/test/java/org/apache/skywalking/apm/meter/micrometer/SkywalkingTimerTest.java
@@ -22,14 +22,13 @@ import io.micrometer.core.instrument.Timer;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 import org.junit.Assert;
 import org.junit.Test;
-import org.powermock.reflect.Whitebox;
 
 import java.time.Duration;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-public class SkywalkingTimerTest extends SkywalkingMeterBaseTest {
+public class SkywalkingTimerTest {
 
     @Test
     public void testSimpleTimer() {
@@ -45,17 +44,6 @@ public class SkywalkingTimerTest extends SkywalkingMeterBaseTest {
         timer.record(10, TimeUnit.MILLISECONDS);
         timer.record(20, TimeUnit.MILLISECONDS);
         timer.record(3, TimeUnit.MILLISECONDS);
-
-        // Check micrometer data
-        Assert.assertEquals(3, timer.count());
-        Assert.assertEquals(33d, timer.totalTime(TimeUnit.MILLISECONDS), 0.0);
-        Assert.assertEquals(20d, timer.max(TimeUnit.MILLISECONDS), 0.0);
-
-        // Check Skywalking data
-        assertCounter(Whitebox.getInternalState(timer, "counter"), "test_simple_timer_count", tags, 3d);
-        assertCounter(Whitebox.getInternalState(timer, "sum"), "test_simple_timer_sum", tags, 33d);
-        assertGauge(Whitebox.getInternalState(timer, "max"), "test_simple_timer_max", tags, 20d);
-        assertHistogramNull(Whitebox.getInternalState(timer, "histogram"));
     }
 
     @Test
@@ -77,16 +65,5 @@ public class SkywalkingTimerTest extends SkywalkingMeterBaseTest {
         timer.record(10, TimeUnit.MILLISECONDS);
         timer.record(22, TimeUnit.MILLISECONDS);
         timer.record(13, TimeUnit.MILLISECONDS);
-
-        // Check micrometer data
-        Assert.assertEquals(3, timer.count());
-        Assert.assertEquals(45d, timer.totalTime(TimeUnit.MILLISECONDS), 0.0);
-        Assert.assertEquals(22d, timer.max(TimeUnit.MILLISECONDS), 0.0);
-
-        // Check Skywalking data
-        assertCounter(Whitebox.getInternalState(timer, "counter"), "test_complex_timer_count", tags, 3d);
-        assertCounter(Whitebox.getInternalState(timer, "sum"), "test_complex_timer_sum", tags, 45d);
-        assertGauge(Whitebox.getInternalState(timer, "max"), "test_complex_timer_max", tags, 22d);
-        assertHistogram(Whitebox.getInternalState(timer, "histogram"), "test_complex_timer_histogram", tags, 1, 0, 10, 2, 20, 1);
     }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/AbstractBuilder.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/AbstractBuilder.java
new file mode 100644
index 0000000..f9e6155
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/AbstractBuilder.java
@@ -0,0 +1,77 @@
+/*
+ * 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.skywalking.apm.agent.core.meter;
+
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+
+import java.util.ArrayList;
+
+/**
+ * Help to build the meter
+ */
+public abstract class AbstractBuilder<BUILDER extends AbstractBuilder, METER extends BaseMeter> {
+
+    private static MeterService METER_SERVICE;
+    protected final MeterId meterId;
+
+    /**
+     * Build a new meter build, meter name is required
+     */
+    public AbstractBuilder(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("Meter name cannot be null");
+        }
+        this.meterId = new MeterId(name, getType(), new ArrayList<>());
+    }
+
+    /**
+     * append new tag to this meter
+     */
+    public BUILDER tag(String name, String value) {
+        meterId.getTags().add(new MeterTag(name, value));
+        return (BUILDER) this;
+    }
+
+    /**
+     * Get supported build meter type
+     */
+    protected abstract MeterType getType();
+
+    /**
+     * Create a meter adapter
+     */
+    protected abstract METER create(MeterId meterId);
+
+    /**
+     * Build a new meter object
+     */
+    public METER build() {
+        // sort the tags
+        this.meterId.getTags().sort(MeterTag::compareTo);
+        // create or get the meter
+        if (METER_SERVICE == null) {
+            METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
+        }
+        final METER adapter = this.create(meterId);
+
+        METER_SERVICE.register(adapter);
+
+        return (METER) adapter;
+    }
+}
\ No newline at end of file
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/MeterTransformer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/BaseMeter.java
similarity index 73%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/MeterTransformer.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/BaseMeter.java
index 700651b..6b9cd24 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/MeterTransformer.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/BaseMeter.java
@@ -16,10 +16,8 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.meter.transform;
+package org.apache.skywalking.apm.agent.core.meter;
 
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.adapter.MeterAdapter;
 import org.apache.skywalking.apm.network.language.agent.v3.Label;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
 
@@ -27,39 +25,42 @@ import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
 
-/**
- * Meter transformer base data
- *
- * @see CounterTransformer
- * @see GaugeTransformer
- * @see HistogramTransformer
- */
-public abstract class MeterTransformer<T extends MeterAdapter> {
-
-    protected T adapter;
+public abstract class BaseMeter {
+    protected final MeterId meterId;
 
     // cache the gRPC label message
     private List<Label> labels;
 
-    public MeterTransformer(T adapter) {
-        this.adapter = adapter;
+    public BaseMeter(MeterId meterId) {
+        this.meterId = meterId;
     }
 
     /**
-     * Identity the meter
+     * Get meter name
      */
-    public MeterId getId() {
-        return adapter.getId();
+    public String getName() {
+        return meterId.getName();
     }
 
     /**
-     * Get meter name
+     * Get tag value
      */
-    public String getName() {
-        return getId().getName();
+    public String getTag(String tagKey) {
+        for (MeterTag tag : meterId.getTags()) {
+            if (tag.getKey().equals(tagKey)) {
+                return tag.getValue();
+            }
+        }
+        return null;
     }
 
     /**
+     * Transform the meter to gRPC message bean
+     * @return if dont need to transform or no changed, return null to ignore
+     */
+    public abstract MeterData.Builder transform();
+
+    /**
      * Transform all tags to gRPC message
      */
     public List<Label> transformTags() {
@@ -72,22 +73,21 @@ public abstract class MeterTransformer<T extends MeterAdapter> {
             .collect(Collectors.toList());
     }
 
-    /**
-     * Transform the meter to gRPC message bean
-     * @return if dont need to transform or no changed, return null to ignore
-     */
-    public abstract MeterData.Builder transform();
+    public MeterId getId() {
+        return meterId;
+    }
 
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
-        MeterTransformer meterTransformer = (MeterTransformer) o;
-        return Objects.equals(getId(), meterTransformer.getId());
+        BaseMeter baseMeter = (BaseMeter) o;
+        return Objects.equals(meterId, baseMeter.meterId);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(getId());
+        return Objects.hash(meterId);
     }
+
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/CounterImpl.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Counter.java
similarity index 57%
rename from apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/CounterImpl.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Counter.java
index 3a7ee41..2075475 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/CounterImpl.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Counter.java
@@ -16,52 +16,44 @@
  *
  */
 
-package org.apache.skywalking.apm.toolkit.meter.impl;
+package org.apache.skywalking.apm.agent.core.meter;
 
-import org.apache.skywalking.apm.toolkit.meter.Counter;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
 
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.atomic.DoubleAdder;
 
 /**
- * Using {@link DoubleAdder} to add count
+ * A counter is a cumulative metric that represents a single monotonically increasing counter whose value can only increase or be reset to zero on restart.
  */
-public class CounterImpl extends AbstractMeter implements Counter {
+public class Counter extends BaseMeter {
 
     protected final DoubleAdder count;
-    protected final Mode mode;
-
+    protected final CounterMode mode;
     private final AtomicReference<Double> previous = new AtomicReference();
 
-    protected CounterImpl(MeterId meterId, Mode mode) {
+    public Counter(MeterId meterId, CounterMode mode) {
         super(meterId);
         this.count = new DoubleAdder();
         this.mode = mode;
     }
 
-    /**
-     * Increment count
-     */
     public void increment(double count) {
         this.count.add(count);
     }
 
-    /**
-     * Get count value
-     */
     public double get() {
-        return this.count.doubleValue();
+        return count.doubleValue();
     }
 
-    /**
-     * Using at the Skywalking agent get, make is support {@link Mode#RATE}
-     */
-    public double agentGet() {
+    @Override
+    public MeterData.Builder transform() {
+        // using rate mode or increase
         final double currentValue = get();
         double count;
-        if (Objects.equals(Mode.RATE, this.mode)) {
+        if (Objects.equals(mode, CounterMode.RATE)) {
             final Double previousValue = previous.getAndSet(currentValue);
 
             // calculate the add count
@@ -74,44 +66,54 @@ public class CounterImpl extends AbstractMeter implements Counter {
             count = currentValue;
         }
 
-        return count;
+        final MeterData.Builder builder = MeterData.newBuilder();
+        builder.setSingleValue(MeterSingleValue.newBuilder()
+            .setName(getName())
+            .addAllLabels(transformTags())
+            .setValue(count).build());
+
+        return builder;
+    }
+
+    /**
+     * Counter mode
+     */
+    public enum Mode {
+        /**
+         * Increase single value, report the real value
+         */
+        INCREMENT,
+
+        /**
+         * Rate with previous value when report
+         */
+        RATE
     }
 
-    public static class Builder extends AbstractBuilder<Counter.Builder, Counter, CounterImpl> implements Counter.Builder {
-        private Counter.Mode mode = Counter.Mode.INCREMENT;
+    public static class Builder extends AbstractBuilder<Builder, Counter> {
+        private CounterMode mode = CounterMode.INCREMENT;
 
         public Builder(String name) {
             super(name);
         }
 
-        public Builder(MeterId meterId) {
-            super(meterId);
-        }
-
         /**
          * Setting counter mode
          */
-        public Builder mode(Counter.Mode mode) {
+        public Builder mode(CounterMode mode) {
             this.mode = mode;
             return this;
         }
 
         @Override
-        protected void accept(CounterImpl meter) throws IllegalArgumentException {
-            // Rate mode must be same
-            if (!Objects.equals(meter.mode, this.mode)) {
-                throw new IllegalArgumentException("Mode is not same");
-            }
-        }
-
-        @Override
         protected Counter create(MeterId meterId) {
-            return new CounterImpl(meterId, mode);
+            return new Counter(meterId, mode);
         }
 
         @Override
-        protected MeterId.MeterType getType() {
-            return MeterId.MeterType.COUNTER;
+        protected MeterType getType() {
+            return MeterType.COUNTER;
         }
+
     }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/HistogramAdapter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/CounterMode.java
similarity index 78%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/HistogramAdapter.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/CounterMode.java
index ab9c46c..1c00457 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/HistogramAdapter.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/CounterMode.java
@@ -16,18 +16,19 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.meter.adapter;
-
-public interface HistogramAdapter extends MeterAdapter {
+package org.apache.skywalking.apm.agent.core.meter;
 
+/**
+ * Counter mode
+ */
+public enum CounterMode {
     /**
-     * Get all buckets
+     * Increase single value, report the real value
      */
-    double[] getAllBuckets();
+    INCREMENT,
 
     /**
-     * Get currently bucket values
+     * Rate with previous value when report
      */
-    long[] getBucketValues();
-
+    RATE
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/GaugeTransformer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Gauge.java
similarity index 55%
rename from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/GaugeTransformer.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Gauge.java
index 6e8e09c..6d8b6a6 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/GaugeTransformer.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Gauge.java
@@ -16,33 +16,43 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.meter.transform;
+package org.apache.skywalking.apm.agent.core.meter;
 
 import org.apache.skywalking.apm.agent.core.logging.api.ILog;
 import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
-import org.apache.skywalking.apm.agent.core.meter.adapter.GaugeAdapter;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
 
-public class GaugeTransformer extends MeterTransformer<GaugeAdapter> {
-    private static final ILog LOGGER = LogManager.getLogger(GaugeTransformer.class);
+import java.util.function.Supplier;
 
-    public GaugeTransformer(GaugeAdapter adapter) {
-        super(adapter);
+/**
+ * A gauge is a metric that represents a single numerical value that can arbitrarily go up and down.
+ */
+public class Gauge extends BaseMeter {
+    private static final ILog LOGGER = LogManager.getLogger(Gauge.class);
+    protected Supplier<Double> getter;
+
+    public Gauge(MeterId meterId, Supplier<Double> getter) {
+        super(meterId);
+        this.getter = getter;
+    }
+
+    /**
+     * Get value
+     */
+    public double get() {
+        final Double data = getter.get();
+        return data == null ? 0 : data;
     }
 
     @Override
     public MeterData.Builder transform() {
         // get count
-        Double count;
+        double count;
         try {
-            count = adapter.getCount();
+            count = get();
         } catch (Exception e) {
-            LOGGER.warn(e, "Cannot get the count in meter:{}", adapter.getId().getName());
-            return null;
-        }
-
-        if (count == null) {
+            LOGGER.warn(e, "Cannot get the count in meter:{}", meterId.getName());
             return null;
         }
 
@@ -54,4 +64,26 @@ public class GaugeTransformer extends MeterTransformer<GaugeAdapter> {
 
         return builder;
     }
+
+    public static class Builder extends AbstractBuilder<Builder, Gauge> {
+        private final Supplier<Double> getter;
+
+        public Builder(String name, Supplier<Double> getter) {
+            super(name);
+            this.getter = getter;
+        }
+
+        @Override
+        protected MeterType getType() {
+            return MeterType.GAUGE;
+        }
+
+        @Override
+        protected Gauge create(MeterId meterId) {
+            if (getter == null) {
+                throw new IllegalArgumentException("getter cannot be null");
+            }
+            return new Gauge(meterId, getter);
+        }
+    }
 }
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/HistogramImpl.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Histogram.java
similarity index 64%
rename from apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/HistogramImpl.java
rename to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Histogram.java
index baa5d1f..d687711 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/impl/HistogramImpl.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/Histogram.java
@@ -16,32 +16,29 @@
  *
  */
 
-package org.apache.skywalking.apm.toolkit.meter.impl;
+package org.apache.skywalking.apm.agent.core.meter;
 
-import org.apache.skywalking.apm.toolkit.meter.Histogram;
-import org.apache.skywalking.apm.toolkit.meter.MeterId;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterBucketValue;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
+import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
 
 /**
- * Custom bucket as the steps.
+ * A summary sample observations (usual things like request durations and response sizes).
+ * While it also provides a total count of observations and a sum of all observed values, it calculates configurable quartiles over a sliding time window.
+ * The histogram provides detailed data in each data group.
  */
-public class HistogramImpl extends AbstractMeter implements Histogram {
-
+public class Histogram extends BaseMeter {
     protected final Bucket[] buckets;
-    protected final List<Double> steps;
-
-    public static HistogramImpl.Builder create(String name) {
-        return new Builder(name);
-    }
 
-    protected HistogramImpl(MeterId meterId, List<Double> steps) {
+    public Histogram(MeterId meterId, List<Double> steps) {
         super(meterId);
-        this.steps = steps;
         this.buckets = initBuckets(steps);
     }
 
@@ -59,13 +56,6 @@ public class HistogramImpl extends AbstractMeter implements Histogram {
     }
 
     /**
-     * Getting all buckets
-     */
-    public Bucket[] getBuckets() {
-        return buckets;
-    }
-
-    /**
      * Using binary search the bucket
      */
     private Bucket findBucket(double value) {
@@ -88,29 +78,36 @@ public class HistogramImpl extends AbstractMeter implements Histogram {
         return low < buckets.length && low >= 0 ? buckets[low] : null;
     }
 
-    private Bucket[] initBuckets(List<Double> buckets) {
-        final Bucket[] list = new Bucket[buckets.size()];
-        for (int i = 0; i < buckets.size(); i++) {
-            list[i] = new Bucket(buckets.get(i));
-        }
-        return list;
+    private Bucket[] initBuckets(List<Double> steps) {
+        return steps.stream().map(Bucket::new).toArray(Bucket[]::new);
     }
 
-    /**
-     * Histogram builder
-     */
-    public static class Builder extends AbstractBuilder<Histogram.Builder, Histogram, HistogramImpl> implements Histogram.Builder {
+    @Override
+    public MeterData.Builder transform() {
+        final MeterData.Builder builder = MeterData.newBuilder();
+
+        // get all values
+        List<MeterBucketValue> values = Arrays.stream(buckets)
+            .map(Histogram.Bucket::transform).collect(Collectors.toList());
+
+        return builder.setHistogram(MeterHistogram.newBuilder()
+            .setName(getName())
+            .addAllLabels(transformTags())
+            .addAllValues(values)
+            .build());
+    }
+
+    public static class Builder extends AbstractBuilder<Builder, Histogram> {
         private double minValue = 0;
         private List<Double> steps;
 
+        /**
+         * Build a new meter build, meter name is required
+         */
         public Builder(String name) {
             super(name);
         }
 
-        public Builder(MeterId meterId) {
-            super(meterId);
-        }
-
         /**
          * Setting bucket steps
          */
@@ -128,24 +125,12 @@ public class HistogramImpl extends AbstractMeter implements Histogram {
         }
 
         @Override
-        public void accept(HistogramImpl meter) {
-            if (this.steps.get(0) != minValue) {
-                this.steps.add(0, minValue);
-            }
-            if (meter.buckets.length != this.steps.size()) {
-                throw new IllegalArgumentException("Steps are not has the same size");
-            }
-            List<Double> meterSteps = new ArrayList<>(meter.buckets.length);
-            for (Bucket bucket : meter.buckets) {
-                meterSteps.add(bucket.bucket);
-            }
-            if (!Objects.equals(meterSteps, this.steps)) {
-                throw new IllegalArgumentException("Steps are not the same");
-            }
+        protected MeterType getType() {
+            return MeterType.HISTOGRAM;
         }
 
         @Override
-        public HistogramImpl create(MeterId meterId) {
+        protected Histogram create(MeterId meterId) {
             if (steps == null || steps.isEmpty()) {
                 throw new IllegalArgumentException("Missing steps setting");
             }
@@ -161,19 +146,14 @@ public class HistogramImpl extends AbstractMeter implements Histogram {
                 steps.add(0, minValue);
             }
 
-            return new HistogramImpl(meterId, steps);
-        }
-
-        @Override
-        public MeterId.MeterType getType() {
-            return MeterId.MeterType.HISTOGRAM;
+            return new Histogram(meterId, steps);
         }
     }
 
     /**
      * Histogram bucket
      */
-    private static class Bucket implements Histogram.Bucket {
+    protected static class Bucket {
         protected double bucket;
         protected AtomicLong count = new AtomicLong();
 
@@ -185,12 +165,11 @@ public class HistogramImpl extends AbstractMeter implements Histogram {
             this.count.addAndGet(count);
         }
 
-        public double getBucket() {
-            return bucket;
-        }
-
-        public long getCount() {
-            return count.get();
+        public MeterBucketValue transform() {
+            return MeterBucketValue.newBuilder()
+                .setBucket(bucket)
+                .setCount(count.get())
+                .build();
         }
 
         @Override
diff --git a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterFactory.java
similarity index 56%
copy from apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java
copy to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterFactory.java
index 60d2611..7d9236b 100644
--- a/apm-application-toolkit/apm-toolkit-meter/src/main/java/org/apache/skywalking/apm/toolkit/meter/MeterFactory.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterFactory.java
@@ -16,56 +16,34 @@
  *
  */
 
-package org.apache.skywalking.apm.toolkit.meter;
-
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
+package org.apache.skywalking.apm.agent.core.meter;
 
 import java.util.function.Supplier;
 
+/**
+ * Help to create meter build, and use {@link AbstractBuilder#build()} to build the meter
+ */
 public class MeterFactory {
 
     /**
      * Create a counter builder by name
      */
     public static Counter.Builder counter(String name) {
-        return new CounterImpl.Builder(name);
-    }
-
-    /**
-     * Create a counter builder by meter id
-     */
-    public static Counter.Builder counter(MeterId meterId) {
-        return new CounterImpl.Builder(meterId);
+        return new Counter.Builder(name);
     }
 
     /**
      * Create a gauge builder by name and getter
      */
-    public static Gauge.Builder gauge(String name, Supplier<Double> getter) {
-        return new GaugeImpl.Builder(name, getter);
-    }
-
-    /**
-     * Create a gauge builder by meter id and getter
-     */
-    public static Gauge.Builder gauge(MeterId meterId, Supplier<Double> getter) {
-        return new GaugeImpl.Builder(meterId, getter);
+    public static Gauge.Builder gauge(String name, Supplier<Double> supplier) {
+        return new Gauge.Builder(name, supplier);
     }
 
     /**
      * Create a histogram builder by name
      */
     public static Histogram.Builder histogram(String name) {
-        return new HistogramImpl.Builder(name);
-    }
-
-    /**
-     * Create a histogram builder by meterId
-     */
-    public static Histogram.Builder histogram(MeterId meterId) {
-        return new HistogramImpl.Builder(meterId);
+        return new Histogram.Builder(name);
     }
 
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterSender.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterSender.java
index d974d31..71a4d67 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterSender.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterSender.java
@@ -31,7 +31,6 @@ import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
 import org.apache.skywalking.apm.agent.core.conf.Config;
 import org.apache.skywalking.apm.agent.core.logging.api.ILog;
 import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.agent.core.remote.GRPCChannelListener;
 import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager;
 import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus;
@@ -62,7 +61,7 @@ public class MeterSender implements BootService, GRPCChannelListener {
 
     }
 
-    public void send(Map<MeterId, MeterTransformer> meterMap, MeterService meterService) {
+    public void send(Map<MeterId, BaseMeter> meterMap, MeterService meterService) {
         if (status == GRPCChannelStatus.CONNECTED) {
             StreamObserver<MeterData> reportStreamObserver = null;
             final GRPCStreamServiceStatus status = new GRPCStreamServiceStatus(false);
@@ -111,12 +110,12 @@ public class MeterSender implements BootService, GRPCChannelListener {
         }
     }
 
-    protected void transform(final Map<MeterId, MeterTransformer> meterMap,
+    protected void transform(final Map<MeterId, BaseMeter> meterMap,
                              final Consumer<MeterData> consumer) {
         // build and report meters
         boolean hasSendMachineInfo = false;
-        for (MeterTransformer meterTransformer : meterMap.values()) {
-            final MeterData.Builder dataBuilder = meterTransformer.transform();
+        for (BaseMeter meter : meterMap.values()) {
+            final MeterData.Builder dataBuilder = meter.transform();
             if (dataBuilder == null) {
                 continue;
             }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterService.java
index e5fb4e6..14887a2 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterService.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterService.java
@@ -29,7 +29,6 @@ import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
 import org.apache.skywalking.apm.agent.core.conf.Config;
 import org.apache.skywalking.apm.agent.core.logging.api.ILog;
 import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.util.RunnableWithExceptionProtection;
 
 /**
@@ -40,7 +39,7 @@ public class MeterService implements BootService, Runnable {
     private static final ILog LOGGER = LogManager.getLogger(MeterService.class);
 
     // all meters
-    private final ConcurrentHashMap<MeterId, MeterTransformer> meterMap = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<MeterId, BaseMeter> meterMap = new ConcurrentHashMap<>();
 
     // report meters
     private volatile ScheduledFuture<?> reportMeterFuture;
@@ -48,19 +47,20 @@ public class MeterService implements BootService, Runnable {
     private MeterSender sender;
 
     /**
-     * Register the meterTransformer
+     * Register the meter
      */
-    public <T extends MeterTransformer> void register(T meterTransformer) {
-        if (meterTransformer == null) {
-            return;
+    public <T extends BaseMeter> T register(T meter) {
+        if (meter == null) {
+            return null;
         }
         if (meterMap.size() >= Config.Meter.MAX_METER_SIZE) {
             LOGGER.warn(
-                "Already out of the meter system max size, will not report. meter name:{}", meterTransformer.getName());
-            return;
+                "Already out of the meter system max size, will not report. meter name:{}", meter.getName());
+            return meter;
         }
 
-        meterMap.putIfAbsent(meterTransformer.getId(), meterTransformer);
+        final BaseMeter data = meterMap.putIfAbsent(meter.getId(), meter);
+        return data == null ? meter : (T) data;
     }
 
     @Override
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterTag.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterTag.java
index b4512a2..a5f0bd7 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterTag.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/MeterTag.java
@@ -20,7 +20,7 @@ package org.apache.skywalking.apm.agent.core.meter;
 
 import java.util.Objects;
 
-public class MeterTag {
+public class MeterTag implements Comparable<MeterTag> {
 
     private String key;
     private String value;
@@ -59,4 +59,9 @@ public class MeterTag {
     public int hashCode() {
         return Objects.hash(key, value);
     }
+
+    @Override
+    public int compareTo(MeterTag o) {
+        return this.key.compareTo(o.key);
+    }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/CounterAdapter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/CounterAdapter.java
deleted file mode 100644
index a7db8df..0000000
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/CounterAdapter.java
+++ /dev/null
@@ -1,23 +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.skywalking.apm.agent.core.meter.adapter;
-
-public interface CounterAdapter extends MeterAdapter {
-    Double getCount();
-}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/GaugeAdapter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/GaugeAdapter.java
deleted file mode 100644
index 178ac9c..0000000
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/GaugeAdapter.java
+++ /dev/null
@@ -1,23 +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.skywalking.apm.agent.core.meter.adapter;
-
-public interface GaugeAdapter extends MeterAdapter {
-    Double getCount();
-}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/MeterAdapter.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/MeterAdapter.java
deleted file mode 100644
index c3eedfe..0000000
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/adapter/MeterAdapter.java
+++ /dev/null
@@ -1,31 +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.skywalking.apm.agent.core.meter.adapter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-
-/**
- * Working on adapt the tool-kit side with agent core
- */
-public interface MeterAdapter {
-    /**
-     * @return {@link MeterId}
-     */
-    MeterId getId();
-}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/CounterTransformer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/CounterTransformer.java
deleted file mode 100644
index 008d796..0000000
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/CounterTransformer.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.skywalking.apm.agent.core.meter.transform;
-
-import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.MeterService;
-import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
-import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
-import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
-
-public class CounterTransformer extends MeterTransformer<CounterAdapter> {
-    private static MeterService METER_SERVICE;
-
-    public CounterTransformer(CounterAdapter adapter) {
-        super(adapter);
-    }
-
-    @Override
-    public MeterData.Builder transform() {
-        if (METER_SERVICE == null) {
-            METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
-        }
-
-        final MeterData.Builder builder = MeterData.newBuilder();
-        builder.setSingleValue(MeterSingleValue.newBuilder()
-            .setName(getName())
-            .addAllLabels(transformTags())
-            .setValue(adapter.getCount()).build());
-
-        return builder;
-    }
-
-}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/HistogramTransformer.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/HistogramTransformer.java
deleted file mode 100644
index 58c50c5..0000000
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/meter/transform/HistogramTransformer.java
+++ /dev/null
@@ -1,92 +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.skywalking.apm.agent.core.meter.transform;
-
-import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
-import org.apache.skywalking.apm.network.language.agent.v3.MeterBucketValue;
-import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
-import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-public class HistogramTransformer extends MeterTransformer<HistogramAdapter> {
-
-    private final Bucket[] buckets;
-
-    public HistogramTransformer(HistogramAdapter adapter) {
-        super(adapter);
-        this.buckets = initBuckets(adapter.getAllBuckets());
-    }
-
-    @Override
-    public MeterData.Builder transform() {
-        final MeterData.Builder builder = MeterData.newBuilder();
-
-        // get all values
-        List<MeterBucketValue> values = new ArrayList<>(this.buckets.length);
-        final long[] bucketValues = adapter.getBucketValues();
-        for (int i = 0; i < bucketValues.length; i++) {
-            values.add(buckets[i].transform(bucketValues[i]));
-        }
-
-        return builder.setHistogram(MeterHistogram.newBuilder()
-            .setName(getName())
-            .addAllLabels(transformTags())
-            .addAllValues(values)
-            .build());
-    }
-
-    private Bucket[] initBuckets(double[] buckets) {
-        final Bucket[] list = new Bucket[buckets.length];
-        for (int i = 0; i < buckets.length; i++) {
-            list[i] = new Bucket(buckets[i]);
-        }
-        return list;
-    }
-
-    public static class Bucket {
-        private double bucket;
-
-        public Bucket(double bucket) {
-            this.bucket = bucket;
-        }
-
-        public MeterBucketValue transform(long currentCount) {
-            return MeterBucketValue.newBuilder()
-                .setBucket(bucket)
-                .setCount(currentCount)
-                .build();
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (o == null || getClass() != o.getClass()) return false;
-            Bucket bucket1 = (Bucket) o;
-            return Double.compare(bucket1.bucket, bucket) == 0;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(bucket);
-        }
-    }
-}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/CounterTransformerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/CounterTest.java
similarity index 53%
rename from apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/CounterTransformerTest.java
rename to apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/CounterTest.java
index be4ccee..2df98aa 100644
--- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/CounterTransformerTest.java
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/CounterTest.java
@@ -16,28 +16,25 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.meter.transform;
+package org.apache.skywalking.apm.agent.core.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.MeterTag;
-import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
 import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
 import org.apache.skywalking.apm.network.language.agent.v3.Label;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
+import org.junit.After;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
+import org.mockito.internal.util.reflection.Whitebox;
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.concurrent.atomic.DoubleAdder;
-
-public class CounterTransformerTest {
+import java.util.concurrent.ConcurrentHashMap;
 
+public class CounterTest {
     @Rule
     public AgentServiceRule agentServiceRule = new AgentServiceRule();
 
@@ -46,15 +43,47 @@ public class CounterTransformerTest {
         ServiceManager.INSTANCE.shutdown();
     }
 
+    @After
+    public void after() {
+        final MeterService meterService = ServiceManager.INSTANCE.findService(MeterService.class);
+        ((ConcurrentHashMap<MeterId, BaseMeter>) Whitebox.getInternalState(meterService, "meterMap")).clear();
+    }
+
     @Test
     public void testTransform() {
-        final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
-        final DoubleAdder counter = new DoubleAdder();
-        CounterTransformer transformer = new CounterTransformer(new TestCounterAdapter(meterId, counter));
+        final Counter counter = MeterFactory.counter("test").tag("k1", "v1").build();
+
+        counter.increment(2d);
+
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 2d, counter.transform());
+    }
+
+    @Test
+    public void testTransformWithRate() {
+        final Counter counter = MeterFactory.counter("test").tag("k1", "v1").mode(CounterMode.RATE).build();
+
+        counter.increment(1d);
+        counter.increment(2d);
 
-        counter.add(2d);
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 3d, counter.transform());
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 0d, counter.transform());
 
-        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 2d, transformer.transform());
+        counter.increment(-4d);
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), -4d, counter.transform());
+    }
+
+    @Test
+    public void testGetCountWithoutRate() {
+        final Counter counter = MeterFactory.counter("test").tag("k1", "v1").mode(CounterMode.INCREMENT).build();
+
+        counter.increment(1d);
+        counter.increment(2d);
+
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 3d, counter.transform());
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), 3d, counter.transform());
+
+        counter.increment(-4d);
+        validateMeterData("test", Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build()), -1d, counter.transform());
     }
 
     /**
@@ -70,26 +99,4 @@ public class CounterTransformerTest {
         Assert.assertEquals(labels, singleValue.getLabelsList());
     }
 
-    /**
-     * Custom {@link CounterAdapter} using {@link DoubleAdder} as the counter value
-     */
-    private static class TestCounterAdapter implements CounterAdapter {
-        private final MeterId meterId;
-        private DoubleAdder counter;
-
-        public TestCounterAdapter(MeterId meterId, DoubleAdder counter) {
-            this.meterId = meterId;
-            this.counter = counter;
-        }
-
-        @Override
-        public Double getCount() {
-            return counter.doubleValue();
-        }
-
-        @Override
-        public MeterId getId() {
-            return meterId;
-        }
-    }
 }
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/GaugeTransformerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/GaugeTest.java
similarity index 55%
rename from apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/GaugeTransformerTest.java
rename to apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/GaugeTest.java
index 45b6904..de0441d 100644
--- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/GaugeTransformerTest.java
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/GaugeTest.java
@@ -16,40 +16,54 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.meter.transform;
+package org.apache.skywalking.apm.agent.core.meter;
 
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.MeterTag;
-import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.agent.core.meter.adapter.GaugeAdapter;
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
 import org.apache.skywalking.apm.network.language.agent.v3.Label;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterSingleValue;
+import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assert;
+import org.junit.Rule;
 import org.junit.Test;
+import org.mockito.internal.util.reflection.Whitebox;
 
 import java.util.Arrays;
 import java.util.List;
-import java.util.function.Supplier;
+import java.util.concurrent.ConcurrentHashMap;
 
-public class GaugeTransformerTest {
+public class GaugeTest {
+    @Rule
+    public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+    @AfterClass
+    public static void afterClass() {
+        ServiceManager.INSTANCE.shutdown();
+    }
+
+    @After
+    public void after() {
+        final MeterService meterService = ServiceManager.INSTANCE.findService(MeterService.class);
+        ((ConcurrentHashMap<MeterId, BaseMeter>) Whitebox.getInternalState(meterService, "meterMap")).clear();
+    }
 
     @Test
     public void testTransform() {
-        final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
         final List<Label> labels = Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build());
 
         // Normal
-        GaugeTransformer transformer1 = new GaugeTransformer(new TestGaugeAdapter(meterId, () -> 2d));
-        validateMeterData("test", labels, 2d, transformer1.transform());
+        final Gauge gauge1 = MeterFactory.gauge("test1", () -> 2d).tag("k1", "v1").build();
+        validateMeterData("test1", labels, 2d, gauge1.transform());
 
         // Exception
-        GaugeTransformer transformer2 = new GaugeTransformer(new TestGaugeAdapter(meterId, () -> Double.valueOf(2 / 0)));
-        Assert.assertNull(transformer2.transform());
+        final Gauge gauge2 = MeterFactory.gauge("test2", () -> Double.valueOf(2 / 0)).tag("k1", "v1").build();
+        Assert.assertNull(gauge2.transform());
 
         // Null
-        GaugeTransformer transformer3 = new GaugeTransformer(new TestGaugeAdapter(meterId, () -> null));
-        Assert.assertNull(transformer3.transform());
+        final Gauge gauge3 = MeterFactory.gauge("test3", () -> null).tag("k1", "v1").build();
+        validateMeterData("test3", labels, 0d, gauge3.transform());
     }
 
     /**
@@ -64,27 +78,4 @@ public class GaugeTransformerTest {
         Assert.assertEquals(singleValue.getName(), name);
         Assert.assertEquals(singleValue.getLabelsList(), labels);
     }
-
-    /**
-     * Custom {@link GaugeAdapter} using {@link Supplier} as data getter
-     */
-    private static class TestGaugeAdapter implements GaugeAdapter {
-        private final MeterId meterId;
-        private Supplier<Double> supplier;
-
-        public TestGaugeAdapter(MeterId meterId, Supplier<Double> supplier) {
-            this.meterId = meterId;
-            this.supplier = supplier;
-        }
-
-        @Override
-        public Double getCount() {
-            return supplier.get();
-        }
-
-        @Override
-        public MeterId getId() {
-            return meterId;
-        }
-    }
 }
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/HistogramTransformerTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/HistogramTest.java
similarity index 54%
rename from apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/HistogramTransformerTest.java
rename to apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/HistogramTest.java
index f85e9a8..cab8626 100644
--- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/transform/HistogramTransformerTest.java
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/HistogramTest.java
@@ -16,50 +16,65 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.meter.transform;
+package org.apache.skywalking.apm.agent.core.meter;
 
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.MeterTag;
-import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
 import org.apache.skywalking.apm.network.language.agent.v3.Label;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterData;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterHistogram;
+import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Assert;
+import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.internal.util.reflection.Whitebox;
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
 
-public class HistogramTransformerTest {
+public class HistogramTest {
+    @Rule
+    public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+    @AfterClass
+    public static void afterClass() {
+        ServiceManager.INSTANCE.shutdown();
+    }
+
+    @After
+    public void after() {
+        final MeterService meterService = ServiceManager.INSTANCE.findService(MeterService.class);
+        ((ConcurrentHashMap<MeterId, BaseMeter>) Whitebox.getInternalState(meterService, "meterMap")).clear();
+    }
 
     @Test
     public void testBuckets() {
         final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
 
         // Check buckets
-        final TestHistogramAdapter adapter = new TestHistogramAdapter(meterId, new double[] {2d, 5d});
-        final HistogramTransformer transformer = new HistogramTransformer(adapter);
-        final HistogramTransformer.Bucket[] buckets = (HistogramTransformer.Bucket[]) Whitebox.getInternalState(transformer, "buckets");
+        final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).minValue(2d).build();
+        final Histogram.Bucket[] buckets = (Histogram.Bucket[]) Whitebox.getInternalState(histogram, "buckets");
         Assert.assertEquals(2, buckets.length);
-        Assert.assertEquals(buckets[0], new HistogramTransformer.Bucket(2));
-        Assert.assertEquals(buckets[1], new HistogramTransformer.Bucket(5));
+        Assert.assertEquals(buckets[0], new Histogram.Bucket(2));
+        Assert.assertEquals(buckets[1], new Histogram.Bucket(5));
     }
 
     @Test
     public void testTransform() {
-        final MeterId meterId = new MeterId("test", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
         final List<Label> labels = Arrays.asList(Label.newBuilder().setName("k1").setValue("v1").build());
 
         // Check histogram message
-        final TestHistogramAdapter adapter = new TestHistogramAdapter(meterId, new double[] {2d, 5d});
-        final HistogramTransformer transformer = new HistogramTransformer(adapter);
-        adapter.setValues(new long[] {5L, 10L});
-        verifyHistogram("test", labels, Arrays.asList(2d, 5d), Arrays.asList(5L, 10L), transformer.transform());
-
-        adapter.setValues(new long[] {6L, 12L});
-        verifyHistogram("test", labels, Arrays.asList(2d, 5d), Arrays.asList(6L, 12L), transformer.transform());
+        final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).minValue(1d).tag("k1", "v1").build();
+        histogram.addValue(1);
+        histogram.addValue(3);
+        histogram.addValue(3);
+        histogram.addValue(7);
+        verifyHistogram("test", labels, Arrays.asList(1d, 2d, 5d), Arrays.asList(1L, 2L, 1L), histogram.transform());
+
+        histogram.addValue(9);
+        verifyHistogram("test", labels, Arrays.asList(1d, 2d, 5d), Arrays.asList(1L, 2L, 2L), histogram.transform());
     }
 
     /**
@@ -83,37 +98,4 @@ public class HistogramTransformerTest {
         }
     }
 
-    /**
-     * Custom {@link HistogramAdapter} with appoint buckets and values
-     */
-    private static class TestHistogramAdapter implements HistogramAdapter {
-        private final MeterId meterId;
-        private final double[] buckets;
-        private long[] values;
-
-        public TestHistogramAdapter(MeterId meterId, double[] buckets) {
-            this.meterId = meterId;
-            this.buckets = buckets;
-        }
-
-        @Override
-        public double[] getAllBuckets() {
-            return buckets;
-        }
-
-        @Override
-        public long[] getBucketValues() {
-            return values;
-        }
-
-        @Override
-        public MeterId getId() {
-            return meterId;
-        }
-
-        public void setValues(long[] values) {
-            this.values = values;
-        }
-    }
-
 }
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterDataBaseTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterDataBaseTest.java
new file mode 100644
index 0000000..b33e39c
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterDataBaseTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.skywalking.apm.agent.core.meter;
+
+import org.junit.Assert;
+
+/**
+ * Meter data base checker
+ */
+public class MeterDataBaseTest {
+
+    /**
+     * Check Counter values
+     */
+    public void testCounter(Counter counter, String name, String[] tags, double val, CounterMode counterMode) {
+        // Check meter name
+        Assert.assertEquals(name, counter.getName());
+        // Check tags
+        if (tags != null && tags.length > 0) {
+            for (int inx = 0; inx < tags.length; inx += 2) {
+                Assert.assertEquals(tags[inx + 1], counter.getTag(tags[inx]));
+            }
+        }
+        // Check current value
+        Assert.assertEquals(val, counter.get(), 0.0);
+
+        // Check mode
+        Assert.assertEquals(counterMode, counter.mode);
+    }
+
+    /**
+     * Check Gauge values
+     */
+    public void testGauge(Gauge gauge, String name, String[] tags, double val) {
+        // Check meter name
+        Assert.assertEquals(name, gauge.getName());
+        // Check tags
+        if (tags != null && tags.length > 0) {
+            for (int inx = 0; inx < tags.length; inx += 2) {
+                Assert.assertEquals(tags[inx + 1], gauge.getTag(tags[inx]));
+            }
+        }
+        // Check current value
+        Assert.assertEquals(val, gauge.get(), 0.0);
+    }
+
+    /**
+     * Check Histogram values
+     */
+    public void testHistogram(Histogram histogram, String name, String[] tags, Double... data) {
+        // Check meter name
+        Assert.assertEquals(name, histogram.getName());
+        // Check tags
+        if (tags != null && tags.length > 0) {
+            for (int inx = 0; inx < tags.length; inx += 2) {
+                Assert.assertEquals(tags[inx + 1], histogram.getTag(tags[inx]));
+            }
+        }
+        // Check buckets
+        for (int i = 0; i < data.length / 2; i++) {
+            Assert.assertEquals(data[i * 2], histogram.buckets[i].bucket, 0.0);
+            Assert.assertEquals(data[i * 2 + 1].longValue(), histogram.buckets[i].count.get());
+        }
+    }
+}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterFactoryTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterFactoryTest.java
new file mode 100644
index 0000000..449f6b3
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterFactoryTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.skywalking.apm.agent.core.meter;
+
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
+import org.apache.skywalking.apm.agent.core.test.tools.TracingSegmentRunner;
+import org.junit.AfterClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(TracingSegmentRunner.class)
+public class MeterFactoryTest extends MeterDataBaseTest {
+
+    @Rule
+    public AgentServiceRule agentServiceRule = new AgentServiceRule();
+
+    @AfterClass
+    public static void afterClass() {
+        ServiceManager.INSTANCE.shutdown();
+    }
+
+    @Test
+    public void testCounter() {
+        // Create counter with different mode
+        final Counter counter1 = MeterFactory.counter("test_counter1")
+            .tag("testA", "testB")
+            .build();
+        testCounter(counter1, "test_counter1", new String[] {"testA", "testB"}, 0.0, CounterMode.INCREMENT);
+
+        final Counter counter2 = MeterFactory.counter("test_counter2")
+            .tag("testA", "testB")
+            .mode(CounterMode.RATE)
+            .build();
+        testCounter(counter2, "test_counter2", new String[] {"testA", "testB"}, 0.0, CounterMode.RATE);
+    }
+
+    @Test
+    public void testGauge() {
+        // Create gauge
+        final Gauge gauge = MeterFactory.gauge("test_gauge", () -> 1d)
+            .tag("testA", "testB")
+            .build();
+        testGauge(gauge, "test_gauge", new String[] {"testA", "testB"}, 1.0);
+    }
+
+    @Test
+    public void testHistogram() {
+        // Create histogram
+        final Histogram histogram = MeterFactory.histogram("test_histogram")
+            .tag("testA", "testB")
+            .steps(Arrays.asList(0d, 10d, 20d, 30d))
+            .build();
+
+        histogram.addValue(3);
+        histogram.addValue(10);
+        testHistogram(histogram, "test_histogram", new String[] {"testA", "testB"}, 0d, 1d, 10d, 1d, 20d, 0d, 30d, 0d);
+    }
+
+}
diff --git a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterServiceTest.java b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterServiceTest.java
index 7fdac30..adbd201 100644
--- a/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterServiceTest.java
+++ b/apm-sniffer/apm-agent-core/src/test/java/org/apache/skywalking/apm/agent/core/meter/MeterServiceTest.java
@@ -22,11 +22,6 @@ import io.grpc.stub.StreamObserver;
 import io.grpc.testing.GrpcServerRule;
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
 import org.apache.skywalking.apm.agent.core.conf.Config;
-import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
-import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
-import org.apache.skywalking.apm.agent.core.meter.transform.CounterTransformer;
-import org.apache.skywalking.apm.agent.core.meter.transform.HistogramTransformer;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus;
 import org.apache.skywalking.apm.agent.core.test.tools.AgentServiceRule;
 import org.apache.skywalking.apm.agent.core.test.tools.TracingSegmentRunner;
@@ -132,8 +127,9 @@ public class MeterServiceTest {
 
         // Add one
         final MeterId counterId = new MeterId("test1", MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
-        final CounterTransformer transformer1 = new CounterTransformer(new TestCounterAdapter(counterId));
-        registryService.register(transformer1);
+        final Counter counter = new Counter(counterId, CounterMode.INCREMENT);
+        counter.increment(2);
+        registryService.register(counter);
         registryService.run();
         assertThat(upstreamMeters.size(), is(1));
         isSameWithCounter(upstreamMeters.get(0), true, counterId, 2);
@@ -141,8 +137,9 @@ public class MeterServiceTest {
         // Add second
         upstreamMeters.clear();
         final MeterId percentileId = new MeterId("test2", MeterType.HISTOGRAM, Arrays.asList(new MeterTag("k1", "v1")));
-        final HistogramTransformer transformer2 = new HistogramTransformer(new TestHistogramAdapter(percentileId));
-        registryService.register(transformer2);
+        final Histogram histogram = new Histogram(percentileId, Arrays.asList(2d));
+        registryService.register(histogram);
+        histogram.addValue(3);
         registryService.run();
         assertThat(upstreamMeters.size(), is(2));
         for (int i = 0; i < upstreamMeters.size(); i++) {
@@ -156,14 +153,14 @@ public class MeterServiceTest {
 
     @Test
     public void testMeterSizeAndShutdown() throws Throwable {
-        final Map<MeterId, MeterTransformer> map = Whitebox.getInternalState(registryService, "meterMap");
+        final Map<MeterId, BaseMeter> map = Whitebox.getInternalState(registryService, "meterMap");
         map.clear();
 
         // Check max meter size
         for (Integer i = 0; i < Config.Meter.MAX_METER_SIZE + 1; i++) {
             final MeterId counterId = new MeterId("test_" + i, MeterType.COUNTER, Arrays.asList(new MeterTag("k1", "v1")));
-            final CounterTransformer transformer1 = new CounterTransformer(new TestCounterAdapter(counterId));
-            registryService.register(transformer1);
+            final Counter counter = new Counter(counterId, CounterMode.INCREMENT);
+            registryService.register(counter);
         }
         assertThat(map.size(), is(Config.Meter.MAX_METER_SIZE));
 
@@ -225,52 +222,4 @@ public class MeterServiceTest {
         }
     }
 
-    /**
-     * Creating a new {@link CounterAdapter} with appoint count
-     */
-    private static class TestCounterAdapter implements CounterAdapter {
-
-        private final MeterId meterId;
-
-        public TestCounterAdapter(MeterId meterId) {
-            this.meterId = meterId;
-        }
-
-        @Override
-        public Double getCount() {
-            return 2d;
-        }
-
-        @Override
-        public MeterId getId() {
-            return this.meterId;
-        }
-    }
-
-    /**
-     * Creating a new {@link HistogramAdapter} with appoint bucket and value
-     */
-    private static class TestHistogramAdapter implements HistogramAdapter {
-        private final MeterId meterId;
-
-        public TestHistogramAdapter(MeterId meterId) {
-            this.meterId = meterId;
-        }
-
-        @Override
-        public MeterId getId() {
-            return meterId;
-        }
-
-        @Override
-        public double[] getAllBuckets() {
-            return new double[] {2};
-        }
-
-        @Override
-        public long[] getBucketValues() {
-            return new long[] {1};
-        }
-    }
-
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterActivation.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterActivation.java
index 063f768..17c38d1 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterActivation.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterActivation.java
@@ -25,6 +25,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsIn
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
 import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 
+import static net.bytebuddy.matcher.ElementMatchers.named;
 import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
 import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
 
@@ -32,7 +33,7 @@ public class CounterActivation extends ClassInstanceMethodsEnhancePluginDefine {
 
     @Override
     protected ClassMatch enhanceClass() {
-        return byName("org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl");
+        return byName("org.apache.skywalking.apm.toolkit.meter.Counter");
     }
 
     @Override
@@ -46,7 +47,7 @@ public class CounterActivation extends ClassInstanceMethodsEnhancePluginDefine {
 
                 @Override
                 public String getConstructorInterceptor() {
-                    return "org.apache.skywalking.apm.toolkit.activation.meter.CounterInterceptor";
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.CounterConstructInterceptor";
                 }
             }
         };
@@ -54,6 +55,39 @@ public class CounterActivation extends ClassInstanceMethodsEnhancePluginDefine {
 
     @Override
     public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
-        return new InstanceMethodsInterceptPoint[0];
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("increment");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.CounterIncrementInterceptor";
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            },
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("get");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.CounterGetInterceptor";
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
     }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterConstructInterceptor.java
similarity index 64%
rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramInterceptor.java
rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterConstructInterceptor.java
index 32016f2..7f247de 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterConstructInterceptor.java
@@ -19,28 +19,30 @@
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.HistogramTransformer;
+import org.apache.skywalking.apm.agent.core.meter.CounterMode;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitHistogramAdapter;
+import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
+import org.apache.skywalking.apm.toolkit.meter.Counter;
+import org.apache.skywalking.apm.toolkit.meter.MeterId;
 
-public class HistogramInterceptor implements InstanceConstructorInterceptor {
+public class CounterConstructInterceptor implements InstanceConstructorInterceptor {
     private static MeterService METER_SERVICE;
 
     @Override
     public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final HistogramImpl toolkitHistogram = (HistogramImpl) objInst;
+        final MeterId meterId = (MeterId) allArguments[0];
+        final Counter.Mode mode = (Counter.Mode) allArguments[1];
 
-        final ToolkitHistogramAdapter histogramAdapter = new ToolkitHistogramAdapter(toolkitHistogram);
-        final HistogramTransformer histogramTransformer = new HistogramTransformer(histogramAdapter);
+        final org.apache.skywalking.apm.agent.core.meter.Counter counter =
+            new org.apache.skywalking.apm.agent.core.meter.Counter(MeterIdConverter.convert(meterId),
+                mode == Counter.Mode.RATE ? CounterMode.RATE : CounterMode.INCREMENT);
 
-        // register the meter
         if (METER_SERVICE == null) {
             METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
         }
-        METER_SERVICE.register(histogramTransformer);
+        objInst.setSkyWalkingDynamicField(METER_SERVICE.register(counter));
     }
 
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterGetInterceptor.java
similarity index 50%
copy from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
copy to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterGetInterceptor.java
index 05222eb..8c70276 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterGetInterceptor.java
@@ -18,28 +18,24 @@
 
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
-import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
-import org.apache.skywalking.apm.agent.core.meter.MeterService;
+import org.apache.skywalking.apm.agent.core.meter.Counter;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
 
-public class GaugeInterceptor implements InstanceConstructorInterceptor {
-    private static MeterService METER_SERVICE;
+import java.lang.reflect.Method;
 
+public class CounterGetInterceptor implements InstanceMethodsAroundInterceptor {
     @Override
-    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final GaugeImpl toolkitGauge = (GaugeImpl) objInst;
-
-        final ToolkitGaugeAdapter gaugeAdapter = new ToolkitGaugeAdapter(toolkitGauge);
-        final GaugeTransformer gaugeTransformer = new GaugeTransformer(gaugeAdapter);
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+    }
 
-        if (METER_SERVICE == null) {
-            METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
-        }
-        METER_SERVICE.register(gaugeTransformer);
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        return ((Counter) objInst.getSkyWalkingDynamicField()).get();
     }
 
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+    }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterIncrementInterceptor.java
similarity index 50%
copy from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
copy to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterIncrementInterceptor.java
index 05222eb..b430cb5 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterIncrementInterceptor.java
@@ -18,28 +18,26 @@
 
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
-import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
-import org.apache.skywalking.apm.agent.core.meter.MeterService;
+import org.apache.skywalking.apm.agent.core.meter.Counter;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
 
-public class GaugeInterceptor implements InstanceConstructorInterceptor {
-    private static MeterService METER_SERVICE;
+import java.lang.reflect.Method;
 
+public class CounterIncrementInterceptor implements InstanceMethodsAroundInterceptor {
     @Override
-    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final GaugeImpl toolkitGauge = (GaugeImpl) objInst;
-
-        final ToolkitGaugeAdapter gaugeAdapter = new ToolkitGaugeAdapter(toolkitGauge);
-        final GaugeTransformer gaugeTransformer = new GaugeTransformer(gaugeAdapter);
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+    }
 
-        if (METER_SERVICE == null) {
-            METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
-        }
-        METER_SERVICE.register(gaugeTransformer);
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        ((Counter) objInst.getSkyWalkingDynamicField()).increment((double) allArguments[0]);
+        return ret;
     }
 
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+
+    }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeActivation.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeActivation.java
index 29a6d51..f9e0496 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeActivation.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeActivation.java
@@ -25,6 +25,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsIn
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
 import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 
+import static net.bytebuddy.matcher.ElementMatchers.named;
 import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
 import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
 
@@ -32,7 +33,7 @@ public class GaugeActivation extends ClassInstanceMethodsEnhancePluginDefine {
 
     @Override
     protected ClassMatch enhanceClass() {
-        return byName("org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl");
+        return byName("org.apache.skywalking.apm.toolkit.meter.Gauge");
     }
 
     @Override
@@ -46,7 +47,7 @@ public class GaugeActivation extends ClassInstanceMethodsEnhancePluginDefine {
 
                 @Override
                 public String getConstructorInterceptor() {
-                    return "org.apache.skywalking.apm.toolkit.activation.meter.GaugeInterceptor";
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.GaugeConstructInterceptor";
                 }
             }
         };
@@ -54,6 +55,23 @@ public class GaugeActivation extends ClassInstanceMethodsEnhancePluginDefine {
 
     @Override
     public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
-        return new InstanceMethodsInterceptPoint[0];
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("get");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.GaugeGetInterceptor";
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
     }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeConstructInterceptor.java
similarity index 70%
copy from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
copy to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeConstructInterceptor.java
index 05222eb..ddd6922 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeConstructInterceptor.java
@@ -19,27 +19,29 @@
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
+import org.apache.skywalking.apm.agent.core.meter.Gauge;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
+import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
+import org.apache.skywalking.apm.toolkit.meter.MeterId;
 
-public class GaugeInterceptor implements InstanceConstructorInterceptor {
+import java.util.function.Supplier;
+
+public class GaugeConstructInterceptor implements InstanceConstructorInterceptor {
     private static MeterService METER_SERVICE;
 
     @Override
     public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final GaugeImpl toolkitGauge = (GaugeImpl) objInst;
+        final MeterId meterId = (MeterId) allArguments[0];
+        final Supplier<Double> getter = (Supplier<Double>) allArguments[1];
 
-        final ToolkitGaugeAdapter gaugeAdapter = new ToolkitGaugeAdapter(toolkitGauge);
-        final GaugeTransformer gaugeTransformer = new GaugeTransformer(gaugeAdapter);
+        final Gauge gauge = new Gauge(MeterIdConverter.convert(meterId), getter);
 
         if (METER_SERVICE == null) {
             METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
         }
-        METER_SERVICE.register(gaugeTransformer);
+        objInst.setSkyWalkingDynamicField(METER_SERVICE.register(gauge));
     }
 
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeGetInterceptor.java
similarity index 50%
copy from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
copy to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeGetInterceptor.java
index 05222eb..362dd01 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeGetInterceptor.java
@@ -18,28 +18,25 @@
 
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
-import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
-import org.apache.skywalking.apm.agent.core.meter.MeterService;
+import org.apache.skywalking.apm.agent.core.meter.Gauge;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
 
-public class GaugeInterceptor implements InstanceConstructorInterceptor {
-    private static MeterService METER_SERVICE;
+import java.lang.reflect.Method;
 
+public class GaugeGetInterceptor implements InstanceMethodsAroundInterceptor {
     @Override
-    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final GaugeImpl toolkitGauge = (GaugeImpl) objInst;
-
-        final ToolkitGaugeAdapter gaugeAdapter = new ToolkitGaugeAdapter(toolkitGauge);
-        final GaugeTransformer gaugeTransformer = new GaugeTransformer(gaugeAdapter);
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+    }
 
-        if (METER_SERVICE == null) {
-            METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
-        }
-        METER_SERVICE.register(gaugeTransformer);
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        return ((Gauge) objInst.getSkyWalkingDynamicField()).get();
     }
 
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+
+    }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramActivation.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramActivation.java
index 2226893..0dcdc16 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramActivation.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramActivation.java
@@ -25,6 +25,7 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsIn
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
 import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
 
+import static net.bytebuddy.matcher.ElementMatchers.named;
 import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
 import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
 
@@ -32,7 +33,7 @@ public class HistogramActivation extends ClassInstanceMethodsEnhancePluginDefine
 
     @Override
     protected ClassMatch enhanceClass() {
-        return byName("org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl");
+        return byName("org.apache.skywalking.apm.toolkit.meter.Histogram");
     }
 
     @Override
@@ -46,7 +47,7 @@ public class HistogramActivation extends ClassInstanceMethodsEnhancePluginDefine
 
                 @Override
                 public String getConstructorInterceptor() {
-                    return "org.apache.skywalking.apm.toolkit.activation.meter.HistogramInterceptor";
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.HistogramConstructInterceptor";
                 }
             }
         };
@@ -54,6 +55,23 @@ public class HistogramActivation extends ClassInstanceMethodsEnhancePluginDefine
 
     @Override
     public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
-        return new InstanceMethodsInterceptPoint[0];
+        return new InstanceMethodsInterceptPoint[] {
+            new InstanceMethodsInterceptPoint() {
+                @Override
+                public ElementMatcher<MethodDescription> getMethodsMatcher() {
+                    return named("addValue");
+                }
+
+                @Override
+                public String getMethodsInterceptor() {
+                    return "org.apache.skywalking.apm.toolkit.activation.meter.HistogramAddValueInterceptor";
+                }
+
+                @Override
+                public boolean isOverrideArgs() {
+                    return false;
+                }
+            }
+        };
     }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramAddValueInterceptor.java
similarity index 50%
rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramAddValueInterceptor.java
index 05222eb..bf3a100 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramAddValueInterceptor.java
@@ -18,28 +18,26 @@
 
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
-import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
-import org.apache.skywalking.apm.agent.core.meter.MeterService;
+import org.apache.skywalking.apm.agent.core.meter.Histogram;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
-import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
+import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
 
-public class GaugeInterceptor implements InstanceConstructorInterceptor {
-    private static MeterService METER_SERVICE;
+import java.lang.reflect.Method;
 
+public class HistogramAddValueInterceptor implements InstanceMethodsAroundInterceptor {
     @Override
-    public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final GaugeImpl toolkitGauge = (GaugeImpl) objInst;
-
-        final ToolkitGaugeAdapter gaugeAdapter = new ToolkitGaugeAdapter(toolkitGauge);
-        final GaugeTransformer gaugeTransformer = new GaugeTransformer(gaugeAdapter);
+    public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
+    }
 
-        if (METER_SERVICE == null) {
-            METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
-        }
-        METER_SERVICE.register(gaugeTransformer);
+    @Override
+    public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
+        ((Histogram) objInst.getSkyWalkingDynamicField()).addValue((double) allArguments[0]);
+        return ret;
     }
 
+    @Override
+    public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
+
+    }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterInterceptor.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramConstructInterceptor.java
similarity index 69%
rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterInterceptor.java
rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramConstructInterceptor.java
index cbd5816..22c98d2 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterInterceptor.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramConstructInterceptor.java
@@ -19,27 +19,30 @@
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
-import org.apache.skywalking.apm.agent.core.meter.transform.CounterTransformer;
+import org.apache.skywalking.apm.agent.core.meter.Histogram;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitCounterAdapter;
+import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
+import org.apache.skywalking.apm.toolkit.meter.MeterId;
 
-public class CounterInterceptor implements InstanceConstructorInterceptor {
+import java.util.List;
+
+public class HistogramConstructInterceptor implements InstanceConstructorInterceptor {
     private static MeterService METER_SERVICE;
 
     @Override
     public void onConstruct(EnhancedInstance objInst, Object[] allArguments) {
-        final CounterImpl toolkitCounter = (CounterImpl) objInst;
+        final MeterId meterId = (MeterId) allArguments[0];
+        final List<Double> steps = (List<Double>) allArguments[1];
 
-        final ToolkitCounterAdapter counterAdapter = new ToolkitCounterAdapter(toolkitCounter);
-        final CounterTransformer counterTransformer = new CounterTransformer(counterAdapter);
+        final Histogram histogram = new Histogram(MeterIdConverter.convert(meterId), steps);
 
+        // register the meter
         if (METER_SERVICE == null) {
             METER_SERVICE = ServiceManager.INSTANCE.findService(MeterService.class);
         }
-        METER_SERVICE.register(counterTransformer);
+        objInst.setSkyWalkingDynamicField(METER_SERVICE.register(histogram));
     }
 
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitCounterAdapter.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitCounterAdapter.java
deleted file mode 100644
index 26337aa..0000000
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitCounterAdapter.java
+++ /dev/null
@@ -1,46 +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.skywalking.apm.toolkit.activation.meter.adapter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.adapter.CounterAdapter;
-import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
-
-public class ToolkitCounterAdapter implements CounterAdapter {
-
-    private final CounterImpl counter;
-    private final MeterId id;
-
-    public ToolkitCounterAdapter(CounterImpl counter) {
-        this.counter = counter;
-        this.id = MeterIdConverter.convert(counter.getMeterId());
-    }
-
-    @Override
-    public Double getCount() {
-        // Using agent get, support rate mode
-        return counter.agentGet();
-    }
-
-    @Override
-    public MeterId getId() {
-        return id;
-    }
-}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitGaugeAdapter.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitGaugeAdapter.java
deleted file mode 100644
index 1607d45..0000000
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitGaugeAdapter.java
+++ /dev/null
@@ -1,46 +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.skywalking.apm.toolkit.activation.meter.adapter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.adapter.GaugeAdapter;
-import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
-import org.apache.skywalking.apm.toolkit.meter.Gauge;
-
-public class ToolkitGaugeAdapter implements GaugeAdapter {
-
-    private final Gauge gauge;
-    private final MeterId id;
-
-    public ToolkitGaugeAdapter(Gauge gauge) {
-        this.gauge = gauge;
-        this.id = MeterIdConverter.convert(gauge.getMeterId());
-    }
-
-    @Override
-    public Double getCount() {
-        return gauge.get();
-    }
-
-    @Override
-    public MeterId getId() {
-        return id;
-    }
-
-}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitHistogramAdapter.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitHistogramAdapter.java
deleted file mode 100644
index d02e104..0000000
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/main/java/org/apache/skywalking/apm/toolkit/activation/meter/adapter/ToolkitHistogramAdapter.java
+++ /dev/null
@@ -1,61 +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.skywalking.apm.toolkit.activation.meter.adapter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.adapter.HistogramAdapter;
-import org.apache.skywalking.apm.toolkit.activation.meter.util.MeterIdConverter;
-import org.apache.skywalking.apm.toolkit.meter.Histogram;
-
-public class ToolkitHistogramAdapter implements HistogramAdapter {
-
-    private final Histogram histogram;
-    private final MeterId id;
-
-    public ToolkitHistogramAdapter(Histogram histogram) {
-        this.histogram = histogram;
-        this.id = MeterIdConverter.convert(histogram.getMeterId());
-    }
-
-    @Override
-    public double[] getAllBuckets() {
-        final int bucketLength = histogram.getBuckets().length;
-        final double[] buckets = new double[bucketLength];
-        for (int i = 0; i < bucketLength; i++) {
-            buckets[i] = histogram.getBuckets()[i].getBucket();
-        }
-        return buckets;
-    }
-
-    @Override
-    public long[] getBucketValues() {
-        final int bucketLength = histogram.getBuckets().length;
-        final long[] bucketValues = new long[bucketLength];
-        for (int i = 0; i < bucketLength; i++) {
-            bucketValues[i] = histogram.getBuckets()[i].getCount();
-        }
-        return bucketValues;
-    }
-
-    @Override
-    public MeterId getId() {
-        return id;
-    }
-
-}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterInterceptorTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterConstructInterceptorTest.java
similarity index 60%
rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterInterceptorTest.java
rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterConstructInterceptorTest.java
index b9158d5..38838db 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterInterceptorTest.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/CounterConstructInterceptorTest.java
@@ -19,14 +19,13 @@
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.meter.BaseMeter;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
-import org.apache.skywalking.apm.agent.core.meter.transform.CounterTransformer;
 import org.apache.skywalking.apm.agent.core.meter.MeterTag;
 import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
+import org.apache.skywalking.apm.toolkit.meter.Counter;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 import org.junit.Assert;
 import org.junit.Rule;
@@ -36,45 +35,45 @@ import org.mockito.internal.util.reflection.Whitebox;
 import java.util.Arrays;
 import java.util.Map;
 
-public class CounterInterceptorTest {
+public class CounterConstructInterceptorTest {
 
     @Rule
     public AgentServiceRule agentServiceRule = new AgentServiceRule();
 
-    private CounterInterceptor counterInterceptor = new CounterInterceptor();
-    private EnhancedInstance enhancedInstance = new CounterEnhance(
-        new MeterId("test", MeterId.MeterType.COUNTER, Arrays.asList(new MeterId.Tag("k1", "v1"))));
+    private CounterConstructInterceptor counterConstructInterceptor = new CounterConstructInterceptor();
+    private EnhancedInstance enhancedInstance = new CounterEnhance();
 
     @Test
     public void testConstruct() {
-        counterInterceptor.onConstruct(enhancedInstance, null);
+        counterConstructInterceptor.onConstruct(enhancedInstance, new Object[] {
+            new MeterId("test", MeterId.MeterType.COUNTER, Arrays.asList(new MeterId.Tag("k1", "v1"))),
+            Counter.Mode.RATE});
 
         final MeterService service = ServiceManager.INSTANCE.findService(MeterService.class);
-        final Map<MeterId, MeterTransformer> meterMap = (Map<MeterId, MeterTransformer>) Whitebox.getInternalState(service, "meterMap");
+        final Map<MeterId, BaseMeter> meterMap = (Map<MeterId, BaseMeter>) Whitebox.getInternalState(service, "meterMap");
         Assert.assertEquals(1, meterMap.size());
 
-        final MeterTransformer transformer = meterMap.values().iterator().next();
-        Assert.assertTrue(transformer instanceof CounterTransformer);
-        final CounterTransformer counterTransformer = (CounterTransformer) transformer;
+        final BaseMeter meterData = meterMap.values().iterator().next();
+        Assert.assertTrue(meterData instanceof org.apache.skywalking.apm.agent.core.meter.Counter);
+        final org.apache.skywalking.apm.agent.core.meter.Counter counter = (org.apache.skywalking.apm.agent.core.meter.Counter) meterData;
 
-        Assert.assertNotNull(counterTransformer.getId());
-        Assert.assertEquals("test", counterTransformer.getId().getName());
-        Assert.assertEquals(MeterType.COUNTER, counterTransformer.getId().getType());
-        Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), counterTransformer.getId().getTags());
+        Assert.assertNotNull(counter.getId());
+        Assert.assertEquals("test", counter.getId().getName());
+        Assert.assertEquals(MeterType.COUNTER, counter.getId().getType());
+        Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), counter.getId().getTags());
     }
 
-    private static class CounterEnhance extends CounterImpl implements EnhancedInstance {
-        protected CounterEnhance(MeterId meterId) {
-            super(meterId, Mode.INCREMENT);
-        }
+    private static class CounterEnhance implements EnhancedInstance {
+        private Object data;
 
         @Override
         public Object getSkyWalkingDynamicField() {
-            return null;
+            return data;
         }
 
         @Override
         public void setSkyWalkingDynamicField(Object value) {
+            this.data = value;
         }
     }
 
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptorTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeConstructInterceptorTest.java
similarity index 63%
rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptorTest.java
rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeConstructInterceptorTest.java
index a97a355..ff4555f 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeInterceptorTest.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/GaugeConstructInterceptorTest.java
@@ -19,14 +19,13 @@
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.meter.BaseMeter;
+import org.apache.skywalking.apm.agent.core.meter.Gauge;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
-import org.apache.skywalking.apm.agent.core.meter.transform.GaugeTransformer;
 import org.apache.skywalking.apm.agent.core.meter.MeterTag;
 import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
-import org.apache.skywalking.apm.toolkit.meter.impl.GaugeImpl;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 import org.junit.Assert;
 import org.junit.Rule;
@@ -37,46 +36,47 @@ import java.util.Arrays;
 import java.util.Map;
 import java.util.function.Supplier;
 
-public class GaugeInterceptorTest {
+public class GaugeConstructInterceptorTest {
 
     @Rule
     public AgentServiceRule agentServiceRule = new AgentServiceRule();
 
-    private GaugeInterceptor gaugeInterceptor = new GaugeInterceptor();
-    private EnhancedInstance enhancedInstance = new GaugeEnhance(
-        new MeterId("test", MeterId.MeterType.GAUGE, Arrays.asList(new MeterId.Tag("k1", "v1"))), () -> 1d);
+    private GaugeConstructInterceptor gaugeConstructInterceptor = new GaugeConstructInterceptor();
+    private EnhancedInstance enhancedInstance = new GaugeEnhance();
 
     @Test
     public void testConstruct() {
-        gaugeInterceptor.onConstruct(enhancedInstance, null);
+        gaugeConstructInterceptor.onConstruct(enhancedInstance, new Object[] {
+            new MeterId("test", MeterId.MeterType.GAUGE, Arrays.asList(new MeterId.Tag("k1", "v1"))),
+            (Supplier<Double>) () -> 1d
+        });
 
         final MeterService service = ServiceManager.INSTANCE.findService(MeterService.class);
-        final Map<MeterId, MeterTransformer> meterMap = (Map<MeterId, MeterTransformer>) Whitebox.getInternalState(service, "meterMap");
+        final Map<MeterId, BaseMeter> meterMap = (Map<MeterId, BaseMeter>) Whitebox.getInternalState(service, "meterMap");
         Assert.assertEquals(1, meterMap.size());
 
         final Object field = meterMap.values().iterator().next();
         Assert.assertNotNull(field);
-        Assert.assertTrue(field instanceof GaugeTransformer);
-        final GaugeTransformer gaugeTransformer = (GaugeTransformer) field;
+        Assert.assertTrue(field instanceof Gauge);
+        final Gauge gauge = (Gauge) field;
 
-        Assert.assertNotNull(gaugeTransformer.getId());
-        Assert.assertEquals("test", gaugeTransformer.getId().getName());
-        Assert.assertEquals(MeterType.GAUGE, gaugeTransformer.getId().getType());
-        Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), gaugeTransformer.getId().getTags());
+        Assert.assertNotNull(gauge.getId());
+        Assert.assertEquals("test", gauge.getId().getName());
+        Assert.assertEquals(MeterType.GAUGE, gauge.getId().getType());
+        Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), gauge.getId().getTags());
     }
 
-    private static class GaugeEnhance extends GaugeImpl implements EnhancedInstance {
-        protected GaugeEnhance(MeterId meterId, Supplier<Double> getter) {
-            super(meterId, getter);
-        }
+    private static class GaugeEnhance implements EnhancedInstance {
+        private Object data;
 
         @Override
         public Object getSkyWalkingDynamicField() {
-            return null;
+            return data;
         }
 
         @Override
         public void setSkyWalkingDynamicField(Object value) {
+            this.data = value;
         }
     }
 
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramInterceptorTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramConstructInterceptorTest.java
similarity index 68%
rename from apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramInterceptorTest.java
rename to apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramConstructInterceptorTest.java
index f000d2d..fc65463 100644
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramInterceptorTest.java
+++ b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/activation/meter/HistogramConstructInterceptorTest.java
@@ -19,14 +19,13 @@
 package org.apache.skywalking.apm.toolkit.activation.meter;
 
 import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.meter.BaseMeter;
+import org.apache.skywalking.apm.agent.core.meter.Histogram;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
-import org.apache.skywalking.apm.agent.core.meter.transform.HistogramTransformer;
 import org.apache.skywalking.apm.agent.core.meter.MeterTag;
 import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
 import org.apache.skywalking.apm.agent.test.tools.AgentServiceRule;
-import org.apache.skywalking.apm.toolkit.meter.impl.HistogramImpl;
 import org.apache.skywalking.apm.toolkit.meter.MeterId;
 import org.junit.Assert;
 import org.junit.Rule;
@@ -34,31 +33,30 @@ import org.junit.Test;
 import org.mockito.internal.util.reflection.Whitebox;
 
 import java.util.Arrays;
-import java.util.List;
 import java.util.Map;
 
-public class HistogramInterceptorTest {
+public class HistogramConstructInterceptorTest {
 
     @Rule
     public AgentServiceRule agentServiceRule = new AgentServiceRule();
 
-    private HistogramInterceptor histogramInterceptor = new HistogramInterceptor();
-    private EnhancedInstance enhancedInstance = new HistogramEnhance(
-        new MeterId("test", MeterId.MeterType.HISTOGRAM, Arrays.asList(new MeterId.Tag("k1", "v1"))),
-        Arrays.asList(1d, 2d, 3d));
+    private HistogramConstructInterceptor histogramConstructInterceptor = new HistogramConstructInterceptor();
+    private EnhancedInstance enhancedInstance = new HistogramEnhance();
 
     @Test
     public void testConstruct() {
-        histogramInterceptor.onConstruct(enhancedInstance, null);
+        histogramConstructInterceptor.onConstruct(enhancedInstance, new Object[] {
+            new MeterId("test", MeterId.MeterType.HISTOGRAM, Arrays.asList(new MeterId.Tag("k1", "v1"))),
+            Arrays.asList(1d, 5d, 10d)});
 
         final MeterService service = ServiceManager.INSTANCE.findService(MeterService.class);
-        final Map<MeterId, MeterTransformer> meterMap = (Map<MeterId, MeterTransformer>) Whitebox.getInternalState(service, "meterMap");
+        final Map<MeterId, BaseMeter> meterMap = (Map<MeterId, BaseMeter>) Whitebox.getInternalState(service, "meterMap");
         Assert.assertEquals(1, meterMap.size());
 
         final Object field = meterMap.values().iterator().next();
         Assert.assertNotNull(field);
-        Assert.assertTrue(field instanceof HistogramTransformer);
-        final HistogramTransformer histogramTransformer = (HistogramTransformer) field;
+        Assert.assertTrue(field instanceof Histogram);
+        final Histogram histogramTransformer = (Histogram) field;
 
         Assert.assertNotNull(histogramTransformer.getId());
         Assert.assertEquals("test", histogramTransformer.getId().getName());
@@ -66,18 +64,17 @@ public class HistogramInterceptorTest {
         Assert.assertEquals(Arrays.asList(new MeterTag("k1", "v1")), histogramTransformer.getId().getTags());
     }
 
-    private static class HistogramEnhance extends HistogramImpl implements EnhancedInstance {
-        protected HistogramEnhance(MeterId meterId, List<Double> steps) {
-            super(meterId, steps);
-        }
+    private static class HistogramEnhance implements EnhancedInstance {
+        private Object data;
 
         @Override
         public Object getSkyWalkingDynamicField() {
-            return null;
+            return data;
         }
 
         @Override
         public void setSkyWalkingDynamicField(Object value) {
+            this.data = value;
         }
     }
 }
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitCounterAdapterTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitCounterAdapterTest.java
deleted file mode 100644
index 5480fa4..0000000
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitCounterAdapterTest.java
+++ /dev/null
@@ -1,71 +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.skywalking.apm.toolkit.meter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.MeterTag;
-import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitCounterAdapter;
-import org.apache.skywalking.apm.toolkit.meter.impl.CounterImpl;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ToolkitCounterAdapterTest {
-
-    @Test
-    public void testGetCount() {
-        final Counter counter = MeterFactory.counter("test").build();
-        final ToolkitCounterAdapter adapter = new ToolkitCounterAdapter((CounterImpl) counter);
-
-        counter.increment(1d);
-        counter.increment(2d);
-
-        Assert.assertEquals(adapter.getCount(), 3d, 0.0);
-
-        counter.increment(-4d);
-        Assert.assertEquals(adapter.getCount(), -1d, 0.0);
-    }
-
-    @Test
-    public void testGetCountWithRate() {
-        final Counter counter = MeterFactory.counter("test_with_rate").mode(Counter.Mode.RATE).build();
-        final ToolkitCounterAdapter adapter = new ToolkitCounterAdapter((CounterImpl) counter);
-
-        counter.increment(1d);
-        counter.increment(2d);
-
-        Assert.assertEquals(adapter.getCount(), 3d, 0.0);
-        Assert.assertEquals(adapter.getCount(), 0d, 0.0);
-
-        counter.increment(-4d);
-        Assert.assertEquals(adapter.getCount(), -4d, 0.0);
-    }
-
-    @Test
-    public void testGetId() {
-        final Counter counter = MeterFactory.counter("test").tag("k1", "v1").build();
-        final ToolkitCounterAdapter adapter = new ToolkitCounterAdapter((CounterImpl) counter);
-
-        final MeterId id = adapter.getId();
-        Assert.assertEquals("test", id.getName());
-        Assert.assertEquals(MeterType.COUNTER, id.getType());
-        Assert.assertEquals(1, id.getTags().size());
-        Assert.assertEquals(new MeterTag("k1", "v1"), id.getTags().get(0));
-    }
-}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitGaugeAdapterTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitGaugeAdapterTest.java
deleted file mode 100644
index afb7d3f..0000000
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitGaugeAdapterTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.apache.skywalking.apm.toolkit.meter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.MeterTag;
-import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitGaugeAdapter;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ToolkitGaugeAdapterTest {
-
-    @Test
-    public void testGetCount() {
-        final Gauge gauge = MeterFactory.gauge("test", () -> 1d).build();
-        final ToolkitGaugeAdapter adapter = new ToolkitGaugeAdapter(gauge);
-
-        Assert.assertEquals(adapter.getCount(), 1d, 0.0);
-    }
-
-    @Test
-    public void testGetId() {
-        final Gauge gauge = MeterFactory.gauge("test", () -> 1d).tag("k1", "v1").build();
-        final ToolkitGaugeAdapter adapter = new ToolkitGaugeAdapter(gauge);
-
-        final MeterId id = adapter.getId();
-        Assert.assertEquals("test", id.getName());
-        Assert.assertEquals(MeterType.GAUGE, id.getType());
-        Assert.assertEquals(1, id.getTags().size());
-        Assert.assertEquals(new MeterTag("k1", "v1"), id.getTags().get(0));
-    }
-}
diff --git a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitHistogramAdapterTest.java b/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitHistogramAdapterTest.java
deleted file mode 100644
index 6a33eb8..0000000
--- a/apm-sniffer/apm-toolkit-activation/apm-toolkit-meter-activation/src/test/java/org/apache/skywalking/apm/toolkit/meter/ToolkitHistogramAdapterTest.java
+++ /dev/null
@@ -1,64 +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.skywalking.apm.toolkit.meter;
-
-import org.apache.skywalking.apm.agent.core.meter.MeterId;
-import org.apache.skywalking.apm.agent.core.meter.MeterTag;
-import org.apache.skywalking.apm.agent.core.meter.MeterType;
-import org.apache.skywalking.apm.toolkit.activation.meter.adapter.ToolkitHistogramAdapter;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.Arrays;
-
-public class ToolkitHistogramAdapterTest {
-
-    @Test
-    public void testGetAllBuckets() {
-        final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).build();
-        final ToolkitHistogramAdapter adapter = new ToolkitHistogramAdapter(histogram);
-
-        Assert.assertArrayEquals(adapter.getAllBuckets(), new double[] {0d, 2d, 5d}, 0.0);
-    }
-
-    @Test
-    public void testGetBucketValues() {
-        final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).build();
-        final ToolkitHistogramAdapter adapter = new ToolkitHistogramAdapter(histogram);
-
-        histogram.addValue(1d);
-        histogram.addValue(2d);
-        histogram.addValue(3d);
-        histogram.addValue(20d);
-
-        Assert.assertArrayEquals(adapter.getBucketValues(), new long[] {1L, 2L, 1L});
-    }
-
-    @Test
-    public void testGetId() {
-        final Histogram histogram = MeterFactory.histogram("test").steps(Arrays.asList(2d, 5d)).tag("k1", "v1").build();
-        final ToolkitHistogramAdapter adapter = new ToolkitHistogramAdapter(histogram);
-
-        final MeterId id = adapter.getId();
-        Assert.assertEquals("test", id.getName());
-        Assert.assertEquals(MeterType.HISTOGRAM, id.getType());
-        Assert.assertEquals(1, id.getTags().size());
-        Assert.assertEquals(new MeterTag("k1", "v1"), id.getTags().get(0));
-    }
-}
diff --git a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaMeterSender.java b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaMeterSender.java
index 30aa901..26e30f2 100644
--- a/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaMeterSender.java
+++ b/apm-sniffer/optional-reporter-plugins/kafka-reporter-plugin/src/main/java/org/apache/skywalking/apm/agent/core/kafka/KafkaMeterSender.java
@@ -27,10 +27,10 @@ import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
 import org.apache.skywalking.apm.agent.core.conf.Config;
 import org.apache.skywalking.apm.agent.core.logging.api.ILog;
 import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
+import org.apache.skywalking.apm.agent.core.meter.BaseMeter;
 import org.apache.skywalking.apm.agent.core.meter.MeterId;
 import org.apache.skywalking.apm.agent.core.meter.MeterSender;
 import org.apache.skywalking.apm.agent.core.meter.MeterService;
-import org.apache.skywalking.apm.agent.core.meter.transform.MeterTransformer;
 import org.apache.skywalking.apm.network.language.agent.v3.MeterDataCollection;
 
 /**
@@ -53,7 +53,8 @@ public class KafkaMeterSender extends MeterSender {
         producer = ServiceManager.INSTANCE.findService(KafkaProducerManager.class).getProducer();
     }
 
-    public void send(Map<MeterId, MeterTransformer> meterMap, MeterService meterService) {
+    @Override
+    public void send(Map<MeterId, BaseMeter> meterMap, MeterService meterService) {
         MeterDataCollection.Builder builder = MeterDataCollection.newBuilder();
         transform(meterMap, meterData -> {
             if (LOGGER.isDebugEnable()) {
diff --git a/docs/en/guides/Java-Plugin-Development-Guide.md b/docs/en/guides/Java-Plugin-Development-Guide.md
index 90706d5..b70e424 100644
--- a/docs/en/guides/Java-Plugin-Development-Guide.md
+++ b/docs/en/guides/Java-Plugin-Development-Guide.md
@@ -1,6 +1,13 @@
 # Plugin Development Guide
-This document describe how to understand, develop and contribute plugin.
+This document describe how to understand, develop and contribute plugin. 
 
+There are 2 kinds of plugin
+1. [Tracing plugin](#tracing-plugin). Follow the distributed tracing concept to collect spans with tags and logs.
+1. [Meter plugin](#meter-plugin). Collect numeric metrics in Counter, Guage, and Histogram formats.
+
+We also provide the [plugin test tool](#plugin-test-tool) to verify the data collected and reported by the plugin. If you plan to contribute any plugin to our main repo, the data would be verified by this tool too.
+
+# Tracing plugin
 ## Concepts
 ### Span
 Span is an important and common concept in distributed tracing system. Learn **Span** from 
@@ -423,7 +430,49 @@ public class SpringMVCPluginConfig {
 }
 ```
 
-### Plugin Test Tool
+
+# Meter Plugin
+Java agent plugin could use meter APIs to collect the metrics for backend analysis.
+
+* `Counter` API represents a single monotonically increasing counter, automatic collect data and report to backend.
+```java
+import org.apache.skywalking.apm.agent.core.meter.MeterFactory;
+
+Counter counter = MeterFactory.counter(meterName).tag("tagKey", "tagValue").mode(Counter.Mode.INCREMENT).build();
+counter.increment(1d);
+```
+1. `MeterFactory.counter` Create a new counter builder with the meter name.
+1. `Counter.Builder.tag(String key, String value)` Mark a tag key/value pair.
+1. `Counter.Builder.mode(Counter.Mode mode)` Change the counter mode, `RATE` mode means reporting rate to the backend.
+1. `Counter.Builder.build()` Build a new `Counter` which is collected and reported to the backend.
+1. `Counter.increment(double count)` Increment count to the `Counter`, It could be a positive value.
+
+* `Gauge` API represents a single numerical value.
+```java
+import org.apache.skywalking.apm.agent.core.meter.MeterFactory;
+
+ThreadPoolExecutor threadPool = ...;
+Gauge gauge = MeterFactory.gauge(meterName, () -> threadPool.getActiveCount()).tag("tagKey", "tagValue").build();
+```
+1. `MeterFactory.gauge(String name, Supplier<Double> getter)` Create a new gauge builder with the meter name and supplier function, this function need to return a `double` value.
+1. `Gauge.Builder.tag(String key, String value)` Mark a tag key/value pair.
+1. `Gauge.Builder.build()` Build a new `Gauge` which is collected and reported to the backend.
+
+* `Histogram` API represents a summary sample observations with customize buckets.
+```java
+import org.apache.skywalking.apm.agent.core.meter.MeterFactory;
+
+Histogram histogram = MeterFactory.histogram("test").tag("tagKey", "tagValue").steps(Arrays.asList(1, 5, 10)).minValue(0).build();
+histogram.addValue(3);
+```
+1. `MeterFactory.histogram(String name)` Create a new histogram builder with the meter name.
+1. `Histogram.Builder.tag(String key, String value)` Mark a tag key/value pair.
+1. `Histogram.Builder.steps(List<Double> steps)` Set up the max values of every histogram buckets.
+1. `Histogram.Builder.minValue(double value)` Set up the minimal value of this histogram, default is `0`.
+1. `Histogram.Builder.build()` Build a new `Histogram` which is collected and reported to the backend.
+1. `Histogram.addValue(double value)` Add value into the histogram, automatically analyze what bucket count needs to be increment. rule: count into [step1, step2).
+
+# Plugin Test Tool
 [Apache SkyWalking Agent Test Tool Suite](https://github.com/apache/skywalking-agent-test-tool)
 a tremendously useful test tools suite in a wide variety of languages of Agent. Includes mock collector and validator. 
 The mock collector is a SkyWalking receiver, like OAP server.
@@ -431,7 +480,7 @@ The mock collector is a SkyWalking receiver, like OAP server.
 You could learn how to use this tool to test the plugin in [this doc](Plugin-test.md). If you want to contribute plugins
 to SkyWalking official repo, this is required.
 
-### Contribute plugins into Apache SkyWalking repository
+# Contribute plugins into Apache SkyWalking repository
 We are welcome everyone to contribute plugins.
 
 Please follow there steps:
diff --git a/docs/en/setup/service-agent/java-agent/Application-toolkit-meter.md b/docs/en/setup/service-agent/java-agent/Application-toolkit-meter.md
index cf04f35..9570930 100644
--- a/docs/en/setup/service-agent/java-agent/Application-toolkit-meter.md
+++ b/docs/en/setup/service-agent/java-agent/Application-toolkit-meter.md
@@ -20,7 +20,7 @@ counter.increment(1d);
 1. `Counter.Builder.tag(String key, String value)` Mark a tag key/value pair.
 1. `Counter.Builder.mode(Counter.Mode mode)` Change the counter mode, `RATE` mode means reporting rate to the backend.
 1. `Counter.Builder.build()` Build a new `Counter` which is collected and reported to the backend.
-1. `Counter.increment(double count)` Increment count to the `Counter`, It could be a positive/negative value.
+1. `Counter.increment(double count)` Increment count to the `Counter`, It could be a positive value.
 
 * `Gauge` API represents a single numerical value.
 ```java
diff --git a/test/e2e/e2e-service-provider/pom.xml b/test/e2e/e2e-service-provider/pom.xml
index 604ec58..693eab2 100644
--- a/test/e2e/e2e-service-provider/pom.xml
+++ b/test/e2e/e2e-service-provider/pom.xml
@@ -51,7 +51,7 @@
         <dependency>
             <groupId>org.apache.skywalking</groupId>
             <artifactId>apm-toolkit-micrometer-registry</artifactId>
-            <version>8.1.0</version>
+            <version>8.2.0-SNAPSHOT</version>
         </dependency>
     </dependencies>
 
@@ -76,4 +76,12 @@
             </plugin>
         </plugins>
     </build>
+
+    <repositories>
+        <repository>
+            <id>apache-snapshot</id>
+            <name>Apache Snapshot</name>
+            <url>https://repository.apache.org/content/repositories/snapshots</url>
+        </repository>
+    </repositories>
 </project>