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

albumenj pushed a commit to branch 3.1
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.1 by this push:
     new 2958351a22 metrics series 2 : add DefaultMetricsCollector (#10499)
2958351a22 is described below

commit 2958351a22fc2ec6771554c98ea059aa21f9c837
Author: Hui Yao <[email protected]>
AuthorDate: Sat Aug 27 09:46:27 2022 +0800

    metrics series 2 : add DefaultMetricsCollector (#10499)
    
    * metrics series 1 : add TimeWindowCounter
    
    * metrics series 2 : add DefaultMetricsCollector
    
    * Handling comments
    
    * Abstract to enumeration class
---
 .../dubbo/common/constants/MetricsConstants.java   |  54 +++++-
 .../MetricsReporter.java}                          |  18 +-
 .../MetricsReporterFactory.java}                   |  25 ++-
 .../metrics/collector/DefaultMetricsCollector.java | 187 +++++++++++++++++++++
 .../collector/MetricsCollector.java}               |  20 ++-
 .../event/MetricsEvent.java}                       |  29 +++-
 .../event/RTEvent.java}                            |  22 ++-
 .../event/RequestEvent.java}                       |  29 +++-
 .../listener/MetricsListener.java}                 |  19 ++-
 .../dubbo/common/metrics/model/MethodMetric.java   | 124 ++++++++++++++
 .../model/MetricsCategory.java}                    |  17 +-
 .../dubbo/common/metrics/model/MetricsKey.java     |  54 ++++++
 .../metrics/model/sample/GaugeMetricSample.java    |  50 ++++++
 .../common/metrics/model/sample/MetricSample.java  | 131 +++++++++++++++
 .../nop/NopMetricsReporter.java}                   |  20 ++-
 .../nop/NopMetricsReporterFactory.java}            |  19 ++-
 .../common/metrics/service/MetricsEntity.java      |  91 ++++++++++
 .../common/metrics/service/MetricsService.java     |  73 ++++++++
 .../service/MetricsServiceExporter.java}           |  31 +++-
 .../org/apache/dubbo/common/utils/NetUtils.java    |   8 +
 .../collector/DefaultMetricsCollectorTest.java     | 163 ++++++++++++++++++
 .../dubbo/common/metrics/event/RTEventTest.java}   |  19 ++-
 .../common/metrics/event/RequestEventTest.java}    |  19 ++-
 .../common/metrics/model/MethodMetricTest.java     |  64 +++++++
 .../model/sample/GaugeMetricSampleTest.java        |  61 +++++++
 .../metrics/model/sample/MetricSampleTest.java     |  57 +++++++
 .../common/metrics/service/MetricsEntityTest.java  |  51 ++++++
 27 files changed, 1366 insertions(+), 89 deletions(-)

diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
index a8fd9a91ef..74a4fe4221 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
@@ -20,9 +20,57 @@ public interface MetricsConstants {
 
     String PROTOCOL_PROMETHEUS = "prometheus";
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+    String TAG_IP = "ip";
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    String TAG_HOSTNAME = "hostname";
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    String TAG_APPLICATION_NAME = "application.name";
+
+    String TAG_INTERFACE_KEY = "interface";
+
+    String TAG_METHOD_KEY = "method";
+
+    String TAG_GROUP_KEY = "group";
+
+    String TAG_VERSION_KEY = "version";
+
+    String ENABLE_JVM_METRICS_KEY = "enable.jvm.metrics";
+
+    String AGGREGATION_COLLECTOR_KEY = "aggregation";
+
+    String AGGREGATION_ENABLED_KEY = "aggregation.enabled";
+
+    String AGGREGATION_BUCKET_NUM_KEY = "aggregation.bucket.num";
+
+    String AGGREGATION_TIME_WINDOW_SECONDS_KEY = 
"aggregation.time.window.seconds";
+
+    String PROMETHEUS_EXPORTER_ENABLED_KEY = "prometheus.exporter.enabled";
+
+    String PROMETHEUS_EXPORTER_ENABLE_HTTP_SERVICE_DISCOVERY_KEY = 
"prometheus.exporter.enable.http.service.discovery";
+
+    String PROMETHEUS_EXPORTER_HTTP_SERVICE_DISCOVERY_URL_KEY = 
"prometheus.exporter.http.service.discovery.url";
+
+    String PROMETHEUS_EXPORTER_METRICS_PORT_KEY = 
"prometheus.exporter.metrics.port";
+
+    String PROMETHEUS_EXPORTER_METRICS_PATH_KEY = 
"prometheus.exporter.metrics.path";
+
+    String PROMETHEUS_PUSHGATEWAY_ENABLED_KEY = 
"prometheus.pushgateway.enabled";
+
+    String PROMETHEUS_PUSHGATEWAY_BASE_URL_KEY = 
"prometheus.pushgateway.base.url";
+
+    String PROMETHEUS_PUSHGATEWAY_USERNAME_KEY = 
"prometheus.pushgateway.username";
+
+    String PROMETHEUS_PUSHGATEWAY_PASSWORD_KEY = 
"prometheus.pushgateway.password";
+
+    String PROMETHEUS_PUSHGATEWAY_PUSH_INTERVAL_KEY = 
"prometheus.pushgateway.push.interval";
+
+    String PROMETHEUS_PUSHGATEWAY_JOB_KEY = "prometheus.pushgateway.job";
+
+    int PROMETHEUS_DEFAULT_METRICS_PORT = 20888;
+
+    String PROMETHEUS_DEFAULT_METRICS_PATH = "/metrics";
+
+    int PROMETHEUS_DEFAULT_PUSH_INTERVAL = 30;
+
+    String PROMETHEUS_DEFAULT_JOB_NAME = "default_dubbo_job";
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/MetricsReporter.java
similarity index 71%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/MetricsReporter.java
index a8fd9a91ef..b07af77888 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/MetricsReporter.java
@@ -14,15 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
-
-    String AGGREGATION_ENABLE = "aggregation.enable";
-
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+/**
+ * Metrics Reporter.
+ * Report metrics to specific metrics server(e.g. Prometheus).
+ */
+public interface MetricsReporter {
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    /**
+     * Initialize metrics reporter.
+     */
+    void init();
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/MetricsReporterFactory.java
similarity index 56%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/MetricsReporterFactory.java
index a8fd9a91ef..ade70ca3c8 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/MetricsReporterFactory.java
@@ -14,15 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
+import org.apache.dubbo.common.extension.SPI;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
-
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+/**
+ * The factory interface to create the instance of {@link MetricsReporter}.
+ */
+@SPI(value = "nop", scope = ExtensionScope.APPLICATION)
+public interface MetricsReporterFactory {
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    /**
+     * Create metrics reporter.
+     *
+     * @param url URL
+     * @return Metrics reporter implementation.
+     */
+    @Adaptive({"protocol"})
+    MetricsReporter createMetricsReporter(URL url);
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/collector/DefaultMetricsCollector.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/collector/DefaultMetricsCollector.java
new file mode 100644
index 0000000000..599b6c83b9
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/collector/DefaultMetricsCollector.java
@@ -0,0 +1,187 @@
+/*
+ * 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.dubbo.common.metrics.collector;
+
+import org.apache.dubbo.common.metrics.event.MetricsEvent;
+import org.apache.dubbo.common.metrics.event.RTEvent;
+import org.apache.dubbo.common.metrics.event.RequestEvent;
+import org.apache.dubbo.common.metrics.listener.MetricsListener;
+import org.apache.dubbo.common.metrics.model.MethodMetric;
+import org.apache.dubbo.common.metrics.model.MetricsKey;
+import org.apache.dubbo.common.metrics.model.sample.GaugeMetricSample;
+import org.apache.dubbo.common.metrics.model.sample.MetricSample;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.LongAccumulator;
+
+import static org.apache.dubbo.common.metrics.model.MetricsCategory.REQUESTS;
+import static org.apache.dubbo.common.metrics.model.MetricsCategory.RT;
+
+/**
+ * Default implementation of {@link MetricsCollector}
+ */
+public class DefaultMetricsCollector implements MetricsCollector {
+
+    private AtomicBoolean collectEnabled = new AtomicBoolean(false);
+    private final List<MetricsListener> listeners = new ArrayList<>();
+    private final ApplicationModel applicationModel;
+    private final String applicationName;
+
+    private final Map<MethodMetric, AtomicLong> totalRequests = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, AtomicLong> succeedRequests = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, AtomicLong> failedRequests = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, AtomicLong> processingRequests = new 
ConcurrentHashMap<>();
+
+    private final Map<MethodMetric, AtomicLong> lastRT = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, LongAccumulator> minRT = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, LongAccumulator> maxRT = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, AtomicLong> avgRT = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, AtomicLong> totalRT = new 
ConcurrentHashMap<>();
+    private final Map<MethodMetric, AtomicLong> rtCount = new 
ConcurrentHashMap<>();
+
+    public DefaultMetricsCollector(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+        this.applicationName = applicationModel.getApplicationName();
+    }
+
+    public void setCollectEnabled(Boolean collectEnabled) {
+        this.collectEnabled.compareAndSet(isCollectEnabled(), collectEnabled);
+    }
+
+    public Boolean isCollectEnabled() {
+        return collectEnabled.get();
+    }
+
+    public void addListener(MetricsListener listener) {
+        listeners.add(listener);
+    }
+
+    public void increaseTotalRequests(String interfaceName, String methodName, 
String group, String version) {
+        if (isCollectEnabled()) {
+            MethodMetric metric = new MethodMetric(applicationName, 
interfaceName, methodName, group, version);
+            AtomicLong count = totalRequests.computeIfAbsent(metric, k -> new 
AtomicLong(0L));
+            count.incrementAndGet();
+
+            publishEvent(new RequestEvent(metric, RequestEvent.Type.TOTAL));
+        }
+    }
+
+    public void increaseSucceedRequests(String interfaceName, String 
methodName, String group, String version) {
+        if (isCollectEnabled()) {
+            MethodMetric metric = new MethodMetric(applicationName, 
interfaceName, methodName, group, version);
+            AtomicLong count = succeedRequests.computeIfAbsent(metric, k -> 
new AtomicLong(0L));
+            count.incrementAndGet();
+
+            publishEvent(new RequestEvent(metric, RequestEvent.Type.SUCCEED));
+        }
+    }
+
+    public void increaseFailedRequests(String interfaceName, String 
methodName, String group, String version) {
+        if (isCollectEnabled()) {
+            MethodMetric metric = new MethodMetric(applicationName, 
interfaceName, methodName, group, version);
+            AtomicLong count = failedRequests.computeIfAbsent(metric, k -> new 
AtomicLong(0L));
+            count.incrementAndGet();
+
+            publishEvent(new RequestEvent(metric, RequestEvent.Type.FAILED));
+        }
+    }
+
+    public void increaseProcessingRequests(String interfaceName, String 
methodName, String group, String version) {
+        if (isCollectEnabled()) {
+            MethodMetric metric = new MethodMetric(applicationName, 
interfaceName, methodName, group, version);
+            AtomicLong count = processingRequests.computeIfAbsent(metric, k -> 
new AtomicLong(0L));
+            count.incrementAndGet();
+        }
+    }
+
+    public void decreaseProcessingRequests(String interfaceName, String 
methodName, String group, String version) {
+        if (isCollectEnabled()) {
+            MethodMetric metric = new MethodMetric(applicationName, 
interfaceName, methodName, group, version);
+            AtomicLong count = processingRequests.computeIfAbsent(metric, k -> 
new AtomicLong(0L));
+            count.decrementAndGet();
+        }
+    }
+
+    public void addRT(String interfaceName, String methodName, String group, 
String version, Long responseTime) {
+        if (isCollectEnabled()) {
+            MethodMetric metric = new MethodMetric(applicationName, 
interfaceName, methodName, group, version);
+
+            AtomicLong last = lastRT.computeIfAbsent(metric, k -> new 
AtomicLong());
+            last.set(responseTime);
+
+            LongAccumulator min = minRT.computeIfAbsent(metric, k -> new 
LongAccumulator(Long::min, Long.MAX_VALUE));
+            min.accumulate(responseTime);
+
+            LongAccumulator max = maxRT.computeIfAbsent(metric, k -> new 
LongAccumulator(Long::max, Long.MIN_VALUE));
+            max.accumulate(responseTime);
+
+            AtomicLong total = totalRT.computeIfAbsent(metric, k -> new 
AtomicLong());
+            total.addAndGet(responseTime);
+
+            AtomicLong count = rtCount.computeIfAbsent(metric, k -> new 
AtomicLong());
+            count.incrementAndGet();
+
+            avgRT.computeIfAbsent(metric, k -> new AtomicLong());
+
+            publishEvent(new RTEvent(metric, responseTime));
+        }
+    }
+
+    private void publishEvent(MetricsEvent event) {
+        for (MetricsListener listener : listeners) {
+            listener.onEvent(event);
+        }
+    }
+
+    @Override
+    public List<MetricSample> collect() {
+        List<MetricSample> list = new ArrayList<>();
+        collectRequests(list);
+        collectRT(list);
+
+        return list;
+    }
+
+    private void collectRequests(List<MetricSample> list) {
+        totalRequests.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_REQUESTS_TOTAL, k.getTags(), REQUESTS, 
v::get)));
+        succeedRequests.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_REQUESTS_SUCCEED, k.getTags(), REQUESTS, 
v::get)));
+        failedRequests.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_REQUESTS_FAILED, k.getTags(), REQUESTS, 
v::get)));
+        processingRequests.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_REQUESTS_PROCESSING, k.getTags(), REQUESTS, 
v::get)));
+    }
+
+    private void collectRT(List<MetricSample> list) {
+        lastRT.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_RT_LAST, k.getTags(), RT, v::get)));
+        minRT.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_RT_MIN, k.getTags(), RT, v::get)));
+        maxRT.forEach((k, v) -> list.add(new 
GaugeMetricSample(MetricsKey.METRIC_RT_MAX, k.getTags(), RT, v::get)));
+
+        totalRT.forEach((k, v) -> {
+            list.add(new GaugeMetricSample(MetricsKey.METRIC_RT_TOTAL, 
k.getTags(), RT, v::get));
+
+            AtomicLong avg = avgRT.get(k);
+            AtomicLong count = rtCount.get(k);
+            avg.set(v.get() / count.get());
+            list.add(new GaugeMetricSample(MetricsKey.METRIC_RT_AVG, 
k.getTags(), RT, avg::get));
+        });
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/collector/MetricsCollector.java
similarity index 66%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/collector/MetricsCollector.java
index a8fd9a91ef..12eaa2a979 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/collector/MetricsCollector.java
@@ -14,15 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.collector;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.metrics.model.sample.MetricSample;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+import java.util.List;
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+/**
+ * Metrics Collector.
+ * An interface of collector to collect framework internal metrics.
+ */
+public interface MetricsCollector {
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    /**
+     * Collect metrics as {@link MetricSample}
+     *
+     * @return List of MetricSample
+     */
+    List<MetricSample> collect();
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/MetricsEvent.java
similarity index 57%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/MetricsEvent.java
index a8fd9a91ef..3b009db980 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/MetricsEvent.java
@@ -14,15 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.event;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+/**
+ * BaseMetricsEvent.
+ */
+public abstract class MetricsEvent {
+
+    /**
+     * Metric object. (eg. {@link 
org.apache.dubbo.common.metrics.model.MethodMetric})
+     */
+    protected transient Object source;
+
+    public MetricsEvent(Object source) {
+        if (source == null) {
+            throw new IllegalArgumentException("null source");
+        }
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+        this.source = source;
+    }
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    public Object getSource() {
+        return source;
+    }
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    public String toString() {
+        return getClass().getName() + "[source=" + source + "]";
+    }
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/RTEvent.java
similarity index 70%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/RTEvent.java
index a8fd9a91ef..68887dcb99 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/RTEvent.java
@@ -14,15 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.event;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+/**
+ * RtEvent.
+ */
+public class RTEvent extends MetricsEvent {
+    private Long rt;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+    public RTEvent(Object source, Long rt) {
+        super(source);
+        this.rt = rt;
+    }
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    public Long getRt() {
+        return rt;
+    }
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    public void setRt(Long rt) {
+        this.rt = rt;
+    }
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/RequestEvent.java
similarity index 63%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/RequestEvent.java
index a8fd9a91ef..b1d050bcb9 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/event/RequestEvent.java
@@ -14,15 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.event;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+/**
+ * RequestEvent.
+ */
+public class RequestEvent extends MetricsEvent {
+    private Type type;
+
+    public RequestEvent(Object source, Type type) {
+        super(source);
+        this.type = type;
+    }
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+    public Type getType() {
+        return type;
+    }
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    public void setType(Type type) {
+        this.type = type;
+    }
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    public enum Type {
+        TOTAL,
+        SUCCEED,
+        FAILED,
+        PROCESSING
+    }
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/listener/MetricsListener.java
similarity index 71%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/listener/MetricsListener.java
index a8fd9a91ef..0f55e9b42c 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/listener/MetricsListener.java
@@ -14,15 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.listener;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.metrics.event.MetricsEvent;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
-
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+/**
+ * Metrics Listener.
+ */
+public interface MetricsListener {
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    /**
+     * notify event.
+     *
+     * @param event BaseMetricsEvent
+     */
+    void onEvent(MetricsEvent event);
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MethodMetric.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MethodMetric.java
new file mode 100644
index 0000000000..3e3f75a601
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MethodMetric.java
@@ -0,0 +1,124 @@
+/*
+ * 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.dubbo.common.metrics.model;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
+import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
+import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
+
+/**
+ * Metric class for method.
+ */
+public class MethodMetric {
+    private String applicationName;
+    private String interfaceName;
+    private String methodName;
+    private String group;
+    private String version;
+
+    public MethodMetric() {
+
+    }
+
+    public MethodMetric(String applicationName, String interfaceName, String 
methodName, String group, String version) {
+        this.applicationName = applicationName;
+        this.interfaceName = interfaceName;
+        this.methodName = methodName;
+        this.group = group;
+        this.version = version;
+    }
+
+    public String getInterfaceName() {
+        return interfaceName;
+    }
+
+    public void setInterfaceName(String interfaceName) {
+        this.interfaceName = interfaceName;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    public void setMethodName(String methodName) {
+        this.methodName = methodName;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public Map<String, String> getTags() {
+        Map<String, String> tags = new HashMap<>();
+        tags.put(TAG_IP, getLocalHost());
+        tags.put(TAG_HOSTNAME, getLocalHostName());
+        tags.put(TAG_APPLICATION_NAME, applicationName);
+
+        tags.put(TAG_INTERFACE_KEY, interfaceName);
+        tags.put(TAG_METHOD_KEY, methodName);
+        tags.put(TAG_GROUP_KEY, group);
+        tags.put(TAG_VERSION_KEY, version);
+        return tags;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MethodMetric that = (MethodMetric) o;
+        return Objects.equals(interfaceName, that.interfaceName) && 
Objects.equals(methodName, that.methodName)
+            && Objects.equals(group, that.group) && Objects.equals(version, 
that.version);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(interfaceName, methodName, group, version);
+    }
+
+    @Override
+    public String toString() {
+        return "MethodMetric{" +
+            "interfaceName='" + interfaceName + '\'' +
+            ", methodName='" + methodName + '\'' +
+            ", group='" + group + '\'' +
+            ", version='" + version + '\'' +
+            '}';
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MetricsCategory.java
similarity index 71%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MetricsCategory.java
index a8fd9a91ef..700a47f21f 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MetricsCategory.java
@@ -14,15 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.model;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
-
-    String AGGREGATION_ENABLE = "aggregation.enable";
-
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
-
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+/**
+ * Metric category.
+ */
+public enum MetricsCategory {
+    RT,
+    QPS,
+    REQUESTS,
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MetricsKey.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MetricsKey.java
new file mode 100644
index 0000000000..3c9ff0221f
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/MetricsKey.java
@@ -0,0 +1,54 @@
+/*
+ * 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.dubbo.common.metrics.model;
+
+public enum MetricsKey {
+
+    METRIC_REQUESTS_TOTAL("requests.total", "Total Requests"),
+    METRIC_REQUESTS_SUCCEED("requests.succeed", "Succeed Requests"),
+    METRIC_REQUESTS_FAILED("requests.failed", "Failed Requests"),
+    METRIC_REQUESTS_PROCESSING("requests.processing", "Processing Requests"),
+    METRIC_REQUESTS_TOTAL_AGG("requests.total.aggregate", "Aggregated Total 
Requests"),
+    METRIC_REQUESTS_SUCCEED_AGG("requests.succeed.aggregate", "Aggregated 
Succeed Requests"),
+    METRIC_REQUESTS_FAILED_AGG("requests.failed.aggregate", "Aggregated Failed 
Requests"),
+    METRIC_QPS_NAME("qps", "Query Per Seconds"),
+    METRIC_RT_LAST("rt.last", "Last Response Time"),
+    METRIC_RT_MIN("rt.min", "Min Response Time"),
+    METRIC_RT_MAX("rt.max", "Max Response Time"),
+    METRIC_RT_TOTAL("rt.total", "Total Response Time"),
+    METRIC_RT_AVG("rt.avg", "Average Response Time"),
+    METRIC_RT_P99("rt.p99", "Response Time P99"),
+    METRIC_RT_P95("rt.p95", "Response Time P95"),
+    ;
+
+    private final String name;
+    private final String description;
+
+    public final String getName() {
+        return this.name;
+    }
+
+    public final String getDescription() {
+        return this.description;
+    }
+
+    MetricsKey(String name, String description) {
+        this.name = name;
+        this.description = description;
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/sample/GaugeMetricSample.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/sample/GaugeMetricSample.java
new file mode 100644
index 0000000000..1bdb2aaada
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/sample/GaugeMetricSample.java
@@ -0,0 +1,50 @@
+/*
+ * 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.dubbo.common.metrics.model.sample;
+
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+import org.apache.dubbo.common.metrics.model.MetricsKey;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
+/**
+ * GaugeMetricSample.
+ */
+public class GaugeMetricSample extends MetricSample {
+
+    private Supplier<Number> supplier;
+
+    public GaugeMetricSample(MetricsKey metricsKey, Map<String, String> tags, 
MetricsCategory category, Supplier<Number> supplier) {
+        super(metricsKey.getName(), metricsKey.getDescription(), tags, 
Type.GAUGE, category);
+        this.supplier = supplier;
+    }
+
+    public GaugeMetricSample(String name, String description, Map<String, 
String> tags, MetricsCategory category, String baseUnit, Supplier<Number> 
supplier) {
+        super(name, description, tags, Type.GAUGE, category, baseUnit);
+        this.supplier = supplier;
+    }
+
+    public Supplier<Number> getSupplier() {
+        return supplier;
+    }
+
+    public void setSupplier(Supplier<Number> supplier) {
+        this.supplier = supplier;
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/sample/MetricSample.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/sample/MetricSample.java
new file mode 100644
index 0000000000..21fe5e0446
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/model/sample/MetricSample.java
@@ -0,0 +1,131 @@
+/*
+ * 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.dubbo.common.metrics.model.sample;
+
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * MetricSample.
+ */
+public class MetricSample {
+    private String name;
+    private String description;
+    private Map<String, String> tags;
+    private Type type;
+    private MetricsCategory category;
+    private String baseUnit;
+
+    public MetricSample(String name, String description, Map<String, String> 
tags, Type type, MetricsCategory category) {
+        this(name, description, tags, type, category, null);
+    }
+
+    public MetricSample(String name, String description, Map<String, String> 
tags, Type type, MetricsCategory category, String baseUnit) {
+        this.name = name;
+        this.description = description;
+        this.tags = tags;
+        this.type = type;
+        this.category = category;
+        this.baseUnit = baseUnit;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Map<String, String> getTags() {
+        return tags;
+    }
+
+    public void setTags(Map<String, String> tags) {
+        this.tags = tags;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    public MetricsCategory getCategory() {
+        return category;
+    }
+
+    public void setCategory(MetricsCategory category) {
+        this.category = category;
+    }
+
+    public String getBaseUnit() {
+        return baseUnit;
+    }
+
+    public void setBaseUnit(String baseUnit) {
+        this.baseUnit = baseUnit;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MetricSample that = (MetricSample) o;
+        return Objects.equals(name, that.name) && Objects.equals(description, 
that.description)
+            && Objects.equals(baseUnit, that.baseUnit) && type == that.type
+            && Objects.equals(category, that.category) && Objects.equals(tags, 
that.tags);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, description, baseUnit, type, category, tags);
+    }
+
+    @Override
+    public String toString() {
+        return "MetricSample{" +
+            "name='" + name + '\'' +
+            ", description='" + description + '\'' +
+            ", baseUnit='" + baseUnit + '\'' +
+            ", type=" + type +
+            ", category=" + category +
+            ", tags=" + tags +
+            '}';
+    }
+
+    public enum Type {
+        COUNTER,
+        GAUGE,
+        LONG_TASK_TIMER,
+        TIMER,
+        DISTRIBUTION_SUMMARY
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/nop/NopMetricsReporter.java
similarity index 70%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/nop/NopMetricsReporter.java
index a8fd9a91ef..07e8c6c96c 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/nop/NopMetricsReporter.java
@@ -14,15 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.nop;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.metrics.MetricsReporter;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+/**
+ * Metrics reporter without any operations.
+ */
+public class NopMetricsReporter implements MetricsReporter {
+
+    public NopMetricsReporter(URL url) {
+
+    }
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    @Override
+    public void init() {
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    }
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/nop/NopMetricsReporterFactory.java
similarity index 63%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/nop/NopMetricsReporterFactory.java
index a8fd9a91ef..462de5e49d 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/nop/NopMetricsReporterFactory.java
@@ -14,15 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.nop;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.metrics.MetricsReporter;
+import org.apache.dubbo.common.metrics.MetricsReporterFactory;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
-
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+/**
+ * MetricsReporterFactory to create NopMetricsReporter.
+ */
+public class NopMetricsReporterFactory implements MetricsReporterFactory {
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    @Override
+    public MetricsReporter createMetricsReporter(URL url) {
+        return new NopMetricsReporter(url);
+    }
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsEntity.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsEntity.java
new file mode 100644
index 0000000000..7c64e290e3
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsEntity.java
@@ -0,0 +1,91 @@
+/*
+ * 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.dubbo.common.metrics.service;
+
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Metrics response entity.
+ */
+public class MetricsEntity {
+
+    private String name;
+    private Map<String, String> tags;
+    private MetricsCategory category;
+    private Object value;
+
+    public MetricsEntity() {
+
+    }
+
+    public MetricsEntity(String name, Map<String, String> tags, 
MetricsCategory category, Object value) {
+        this.name = name;
+        this.tags = tags;
+        this.category = category;
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Map<String, String> getTags() {
+        return tags;
+    }
+
+    public void setTags(Map<String, String> tags) {
+        this.tags = tags;
+    }
+
+    public MetricsCategory getCategory() {
+        return category;
+    }
+
+    public void setCategory(MetricsCategory category) {
+        this.category = category;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    public void setValue(Object value) {
+        this.value = value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        MetricsEntity entity = (MetricsEntity) o;
+        return Objects.equals(name, entity.name) && Objects.equals(tags, 
entity.tags)
+            && Objects.equals(category, entity.category) && 
Objects.equals(value, entity.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(name, tags, category, value);
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsService.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsService.java
new file mode 100644
index 0000000000..7c8724e8da
--- /dev/null
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsService.java
@@ -0,0 +1,73 @@
+/*
+ * 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.dubbo.common.metrics.service;
+
+import org.apache.dubbo.common.extension.ExtensionScope;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+
+import java.util.List;
+import java.util.Map;
+
+import static 
org.apache.dubbo.common.metrics.service.MetricsService.DEFAULT_EXTENSION_NAME;
+
+/**
+ * Metrics Service.
+ * Provide an interface to get metrics from {@link 
org.apache.dubbo.common.metrics.collector.MetricsCollector}
+ */
+@SPI(value = DEFAULT_EXTENSION_NAME, scope = ExtensionScope.APPLICATION)
+public interface MetricsService {
+
+    /**
+     * Default {@link MetricsService} extension name.
+     */
+    String DEFAULT_EXTENSION_NAME = "default";
+
+    /**
+     * The contract version of {@link MetricsService}, the future update must 
make sure compatible.
+     */
+    String VERSION = "1.0.0";
+
+    /**
+     * Get metrics by prefixes
+     *
+     * @param categories categories
+     * @return metrics - key=MetricCategory value=MetricsEntityList
+     */
+    Map<MetricsCategory, List<MetricsEntity>> 
getMetricsByCategories(List<MetricsCategory> categories);
+
+    /**
+     * Get metrics by interface and prefixes
+     *
+     * @param serviceUniqueName serviceUniqueName 
(eg.group/interfaceName:version)
+     * @param categories categories
+     * @return metrics - key=MetricCategory value=MetricsEntityList
+     */
+    Map<MetricsCategory, List<MetricsEntity>> getMetricsByCategories(String 
serviceUniqueName, List<MetricsCategory> categories);
+
+    /**
+     * Get metrics by interface态method and prefixes
+     *
+     * @param serviceUniqueName serviceUniqueName 
(eg.group/interfaceName:version)
+     * @param methodName methodName
+     * @param parameterTypes method parameter types
+     * @param categories categories
+     * @return metrics - key=MetricCategory value=MetricsEntityList
+     */
+    Map<MetricsCategory, List<MetricsEntity>> getMetricsByCategories(String 
serviceUniqueName, String methodName, Class<?>[] parameterTypes, 
List<MetricsCategory> categories);
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsServiceExporter.java
similarity index 53%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsServiceExporter.java
index a8fd9a91ef..8a9a6a06f3 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/main/java/org/apache/dubbo/common/metrics/service/MetricsServiceExporter.java
@@ -14,15 +14,34 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.service;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.extension.ExtensionScope;
+import org.apache.dubbo.common.extension.SPI;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+/**
+ * The exporter of {@link MetricsService}
+ */
+@SPI(value = "default", scope = ExtensionScope.APPLICATION)
+public interface MetricsServiceExporter {
+
+    /**
+     * Initialize exporter
+     */
+    void init();
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    /**
+     * Exports the {@link MetricsService} as a Dubbo service
+     *
+     * @return {@link MetricsServiceExporter itself}
+     */
+    MetricsServiceExporter export();
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+    /**
+     * Unexports the {@link MetricsService}
+     *
+     * @return {@link MetricsServiceExporter itself}
+     */
+    MetricsServiceExporter unexport();
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java 
b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
index c4f24dfc09..389f7eb9a0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
@@ -472,6 +472,14 @@ public class NetUtils {
         return address;
     }
 
+    public static String getLocalHostName() {
+        try {
+            return InetAddress.getLocalHost().getHostName();
+        } catch (UnknownHostException e) {
+            return getLocalAddress().getHostName();
+        }
+    }
+
     /**
      * @param hostName
      * @return ip address or hostName if UnknownHostException
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/collector/DefaultMetricsCollectorTest.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/collector/DefaultMetricsCollectorTest.java
new file mode 100644
index 0000000000..1dcd22782e
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/collector/DefaultMetricsCollectorTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.dubbo.common.metrics.collector;
+
+import org.apache.dubbo.common.metrics.event.MetricsEvent;
+import org.apache.dubbo.common.metrics.event.RTEvent;
+import org.apache.dubbo.common.metrics.event.RequestEvent;
+import org.apache.dubbo.common.metrics.listener.MetricsListener;
+import org.apache.dubbo.common.metrics.model.sample.GaugeMetricSample;
+import org.apache.dubbo.common.metrics.model.sample.MetricSample;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
+import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
+import static 
org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
+
+public class DefaultMetricsCollectorTest {
+
+    private ApplicationModel applicationModel;
+    private String interfaceName;
+    private String methodName;
+    private String group;
+    private String version;
+
+    @BeforeEach
+    public void setup() {
+        ApplicationConfig config = new ApplicationConfig();
+        config.setName("MockMetrics");
+
+        applicationModel = ApplicationModel.defaultModel();
+        applicationModel.getApplicationConfigManager().setApplication(config);
+
+        interfaceName = "org.apache.dubbo.MockInterface";
+        methodName = "mockMethod";
+        group = "mockGroup";
+        version = "1.0.0";
+    }
+
+    @AfterEach
+    public void teardown() {
+        applicationModel.destroy();
+    }
+
+    @Test
+    public void testRequestsMetrics() {
+        DefaultMetricsCollector collector = new 
DefaultMetricsCollector(applicationModel);
+        collector.setCollectEnabled(true);
+        collector.increaseTotalRequests(interfaceName, methodName, group, 
version);
+        collector.increaseProcessingRequests(interfaceName, methodName, group, 
version);
+        collector.increaseSucceedRequests(interfaceName, methodName, group, 
version);
+        collector.increaseFailedRequests(interfaceName, methodName, group, 
version);
+
+        List<MetricSample> samples = collector.collect();
+        for (MetricSample sample : samples) {
+            Assertions.assertTrue(sample instanceof GaugeMetricSample);
+            GaugeMetricSample gaugeSample = (GaugeMetricSample) sample;
+            Map<String, String> tags = gaugeSample.getTags();
+            Supplier<Number> supplier = gaugeSample.getSupplier();
+
+            Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), 
interfaceName);
+            Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
+            Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
+            Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
+            Assertions.assertEquals(supplier.get().longValue(), 1);
+        }
+
+        collector.decreaseProcessingRequests(interfaceName, methodName, group, 
version);
+        samples = collector.collect();
+        Map<String, Long> sampleMap = 
samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
+            Number number = ((GaugeMetricSample) k).getSupplier().get();
+            return number.longValue();
+        }));
+
+        Assertions.assertEquals(sampleMap.get("requests.processing"), 0L);
+    }
+
+    @Test
+    public void testRTMetrics() {
+        DefaultMetricsCollector collector = new 
DefaultMetricsCollector(applicationModel);
+        collector.setCollectEnabled(true);
+        collector.addRT(interfaceName, methodName, group, version, 10L);
+        collector.addRT(interfaceName, methodName, group, version, 0L);
+
+        List<MetricSample> samples = collector.collect();
+        for (MetricSample sample : samples) {
+            Map<String, String> tags = sample.getTags();
+
+            Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), 
interfaceName);
+            Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
+            Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
+            Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
+        }
+
+        Map<String, Long> sampleMap = 
samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
+            Number number = ((GaugeMetricSample) k).getSupplier().get();
+            return number.longValue();
+        }));
+
+        Assertions.assertEquals(sampleMap.get("rt.last"), 0L);
+        Assertions.assertEquals(sampleMap.get("rt.min"), 0L);
+        Assertions.assertEquals(sampleMap.get("rt.max"), 10L);
+        Assertions.assertEquals(sampleMap.get("rt.avg"), 5L);
+        Assertions.assertEquals(sampleMap.get("rt.total"), 10L);
+    }
+
+    @Test
+    public void testListener() {
+        DefaultMetricsCollector collector = new 
DefaultMetricsCollector(applicationModel);
+        collector.setCollectEnabled(true);
+
+        MockListener mockListener = new MockListener();
+        collector.addListener(mockListener);
+
+        collector.increaseTotalRequests(interfaceName, methodName, group, 
version);
+        Assertions.assertNotNull(mockListener.getCurEvent());
+        Assertions.assertTrue(mockListener.getCurEvent() instanceof 
RequestEvent);
+        Assertions.assertEquals(((RequestEvent) 
mockListener.getCurEvent()).getType(), RequestEvent.Type.TOTAL);
+
+        collector.addRT(interfaceName, methodName, group, version, 5L);
+        Assertions.assertTrue(mockListener.getCurEvent() instanceof RTEvent);
+        Assertions.assertEquals(((RTEvent) 
mockListener.getCurEvent()).getRt(), 5L);
+    }
+
+    static class MockListener implements MetricsListener {
+
+        private MetricsEvent curEvent;
+
+        @Override
+        public void onEvent(MetricsEvent event) {
+            curEvent = event;
+        }
+
+        public MetricsEvent getCurEvent() {
+            return curEvent;
+        }
+    }
+}
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/event/RTEventTest.java
similarity index 62%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/test/java/org/apache/dubbo/common/metrics/event/RTEventTest.java
index a8fd9a91ef..fea3e0ecec 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/event/RTEventTest.java
@@ -14,15 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.event;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.metrics.model.MethodMetric;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+public class RTEventTest {
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    @Test
+    public void testNewEvent() {
+        MethodMetric metric = new MethodMetric();
+        Long rt = 5L;
+        RTEvent event = new RTEvent(metric, rt);
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+        Assertions.assertEquals(event.getSource(), metric);
+        Assertions.assertEquals(event.getRt(), rt);
+    }
 }
diff --git 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/event/RequestEventTest.java
similarity index 59%
copy from 
dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
copy to 
dubbo-common/src/test/java/org/apache/dubbo/common/metrics/event/RequestEventTest.java
index a8fd9a91ef..3da2f3ac5c 100644
--- 
a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/MetricsConstants.java
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/event/RequestEventTest.java
@@ -14,15 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.constants;
 
-public interface MetricsConstants {
+package org.apache.dubbo.common.metrics.event;
 
-    String PROTOCOL_PROMETHEUS = "prometheus";
+import org.apache.dubbo.common.metrics.model.MethodMetric;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
 
-    String AGGREGATION_ENABLE = "aggregation.enable";
+public class RequestEventTest {
 
-    String AGGREGATION_BUCKET_NUM = "aggregation.bucket.num";
+    @Test
+    public void testNewEvent() {
+        MethodMetric metric = new MethodMetric();
+        RequestEvent.Type type = RequestEvent.Type.TOTAL;
+        RequestEvent event = new RequestEvent(metric, type);
 
-    String AGGREGATION_TIME_WINDOW_SECONDS = "aggregation.time.window.seconds";
+        Assertions.assertEquals(event.getSource(), metric);
+        Assertions.assertEquals(event.getType(), type);
+    }
 }
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/MethodMetricTest.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/MethodMetricTest.java
new file mode 100644
index 0000000000..f4dbcf2ded
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/MethodMetricTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.dubbo.common.metrics.model;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import static org.apache.dubbo.common.constants.MetricsConstants.*;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
+
+public class MethodMetricTest {
+
+    private static final String applicationName = null;
+    private static String interfaceName;
+    private static String methodName;
+    private static String group;
+    private static String version;
+
+    @BeforeAll
+    public static void setup() {
+        interfaceName = "org.apache.dubbo.MockInterface";
+        methodName = "mockMethod";
+        group = "mockGroup";
+        version = "1.0.0";
+    }
+
+    @Test
+    public void test() {
+        MethodMetric metric = new MethodMetric(applicationName, interfaceName, 
methodName, group, version);
+        Assertions.assertEquals(metric.getInterfaceName(), interfaceName);
+        Assertions.assertEquals(metric.getMethodName(), methodName);
+        Assertions.assertEquals(metric.getGroup(), group);
+        Assertions.assertEquals(metric.getVersion(), version);
+
+        Map<String, String> tags = metric.getTags();
+        Assertions.assertEquals(tags.get(TAG_IP), getLocalHost());
+        Assertions.assertEquals(tags.get(TAG_HOSTNAME), getLocalHostName());
+        Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), 
applicationName);
+
+        Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
+        Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
+        Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
+        Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/sample/GaugeMetricSampleTest.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/sample/GaugeMetricSampleTest.java
new file mode 100644
index 0000000000..d45ee03c11
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/sample/GaugeMetricSampleTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.dubbo.common.metrics.model.sample;
+
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Supplier;
+
+public class GaugeMetricSampleTest {
+
+    private static String name;
+    private static String description;
+    private static Map<String, String> tags;
+    private static MetricsCategory category;
+    private static String baseUnit;
+    private static Supplier<Number> supplier;
+
+    @BeforeAll
+    public static void setup() {
+        name = "test";
+        description = "test";
+        tags = new HashMap<>();
+        category = MetricsCategory.REQUESTS;
+        baseUnit = "byte";
+        supplier = () -> 1;
+    }
+
+    @Test
+    public void test() {
+        GaugeMetricSample sample = new GaugeMetricSample(name, description, 
tags, category, baseUnit, supplier);
+        Assertions.assertEquals(sample.getName(), name);
+        Assertions.assertEquals(sample.getDescription(), description);
+        Assertions.assertEquals(sample.getTags(), tags);
+        Assertions.assertEquals(sample.getType(), MetricSample.Type.GAUGE);
+        Assertions.assertEquals(sample.getCategory(), category);
+        Assertions.assertEquals(sample.getBaseUnit(), baseUnit);
+        Assertions.assertEquals(sample.getSupplier().get(), 1);
+        sample.setSupplier(() -> 2);
+        Assertions.assertEquals(sample.getSupplier().get(), 2);
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/sample/MetricSampleTest.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/sample/MetricSampleTest.java
new file mode 100644
index 0000000000..78b575304a
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/model/sample/MetricSampleTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.dubbo.common.metrics.model.sample;
+
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MetricSampleTest {
+
+    private static String name;
+    private static String description;
+    private static Map<String, String> tags;
+    private static MetricSample.Type type;
+    private static MetricsCategory category;
+    private static String baseUnit;
+
+    @BeforeAll
+    public static void setup() {
+        name = "test";
+        description = "test";
+        tags = new HashMap<>();
+        type = MetricSample.Type.GAUGE;
+        category = MetricsCategory.REQUESTS;
+        baseUnit = "byte";
+    }
+
+    @Test
+    public void test() {
+        MetricSample sample = new MetricSample(name, description, tags, type, 
category, baseUnit);
+        Assertions.assertEquals(sample.getName(), name);
+        Assertions.assertEquals(sample.getDescription(), description);
+        Assertions.assertEquals(sample.getTags(), tags);
+        Assertions.assertEquals(sample.getType(), type);
+        Assertions.assertEquals(sample.getCategory(), category);
+        Assertions.assertEquals(sample.getBaseUnit(), baseUnit);
+    }
+}
diff --git 
a/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/service/MetricsEntityTest.java
 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/service/MetricsEntityTest.java
new file mode 100644
index 0000000000..c2688cefce
--- /dev/null
+++ 
b/dubbo-common/src/test/java/org/apache/dubbo/common/metrics/service/MetricsEntityTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.dubbo.common.metrics.service;
+
+import org.apache.dubbo.common.metrics.model.MetricsCategory;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MetricsEntityTest {
+
+    private static String name;
+    private static Map<String, String> tags;
+    private static MetricsCategory category;
+    private static Object value;
+
+    @BeforeAll
+    public static void setup() {
+        name = "test";
+        tags = new HashMap<>();
+        category = MetricsCategory.REQUESTS;
+        value = 1;
+    }
+
+    @Test
+    public void test() {
+        MetricsEntity entity = new MetricsEntity(name, tags, category, value);
+        Assertions.assertEquals(entity.getName(), name);
+        Assertions.assertEquals(entity.getTags(), tags);
+        Assertions.assertEquals(entity.getCategory(), category);
+        Assertions.assertEquals(entity.getValue(), value);
+    }
+}

Reply via email to