You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by mi...@apache.org on 2019/04/12 03:34:28 UTC

[incubator-dubbo] branch master updated: metrics service (#3833)

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

min pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new fa8aabf  metrics service (#3833)
fa8aabf is described below

commit fa8aabfd3a6977d027751a37041c1139369bbbcb
Author: panxiaojun233 <43...@users.noreply.github.com>
AuthorDate: Fri Apr 12 11:34:23 2019 +0800

    metrics service (#3833)
    
    * metrics service
    
    * bug fix
    
    * full method name
    
    * return type fix
    
    * return type fix
    
    * modify bug
    
    * bug fix
    
    * bug fix
    
    * add metrics message
    
    * bug fix
    
    * add config ip
    
    * code optimization
---
 .../java/org/apache/dubbo/common/Constants.java    |   2 +
 .../org/apache/dubbo/common/utils/NetUtils.java    |  10 +
 .../dubbo/config/AbstractInterfaceConfig.java      |  12 +
 .../org/apache/dubbo/config/MetricsConfig.java     |  33 ++-
 .../org/apache/dubbo/config/ReferenceConfig.java   |   2 +
 .../org/apache/dubbo/config/ServiceConfig.java     |   2 +
 .../apache/dubbo/config/spring/ReferenceBean.java  |  17 ++
 .../apache/dubbo/config/spring/ServiceBean.java    |  31 ++-
 .../spring/schema/DubboNamespaceHandler.java       |   9 +-
 .../src/main/resources/META-INF/compat/dubbo.xsd   |  24 ++
 .../src/main/resources/META-INF/dubbo.xsd          |  24 ++
 dubbo-monitor/dubbo-monitor-api/pom.xml            |  19 +-
 .../org/apache/dubbo/monitor/MetricsService.java}  |  14 +-
 .../dubbo/monitor/support/MetricsFilter.java       | 102 --------
 .../dubbo/internal/org.apache.dubbo.rpc.Filter     |   1 -
 .../dubbo/monitor/support/MetricsFilterTest.java   | 167 ------------
 dubbo-monitor/dubbo-monitor-default/pom.xml        |  14 +-
 .../apache/dubbo/monitor/dubbo/MetricsFilter.java  | 254 ++++++++++++++++++
 .../dubbo/internal/org.apache.dubbo.rpc.Filter     |   1 +
 .../dubbo/monitor/dubbo/MetricsFilterTest.java     | 289 +++++++++++++++++++++
 .../dubbo/monitor/dubbo}/service/DemoService.java  |   2 +-
 21 files changed, 720 insertions(+), 309 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index b43c532..596d91c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@ -871,6 +871,8 @@ public class Constants {
     public static final String METHOD = "method";
     public static final String DUBBO_GROUP = "dubbo";
     public static final String METRICS_KEY = "metrics";
+    public static final String METRICS_PORT = "metrics.port";
+    public static final String METRICS_PROTOCOL = "metrics.protocol";
 
 
 }
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 91f04b8..187e0e2 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
@@ -18,6 +18,7 @@ package org.apache.dubbo.common.utils;
 
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 
@@ -210,6 +211,15 @@ public class NetUtils {
         return host;
     }
 
+    public static String getIpByConfig() {
+        String configIp = ConfigurationUtils.getProperty(Constants.DUBBO_IP_TO_BIND);
+        if (configIp != null) {
+            return configIp;
+        }
+
+        return getIpByHost(getLocalAddress().getHostName());
+    }
+
     /**
      * Find first valid IP from local network card
      *
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 082a0c1..57cb6c3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -141,6 +141,11 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
      * Disconnection events
      */
     protected String ondisconnect;
+
+    /**
+     * The metrics configuration
+     */
+    protected MetricsConfig metrics;
     protected MetadataReportConfig metadataReportConfig;
 
     protected ConfigCenterConfig configCenter;
@@ -825,4 +830,11 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         this.metadataReportConfig = metadataReportConfig;
     }
 
+    public MetricsConfig getMetrics() {
+        return metrics;
+    }
+
+    public void setMetrics(MetricsConfig metrics) {
+        this.metrics = metrics;
+    }
 }
diff --git a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetricsConfig.java
similarity index 53%
copy from dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java
copy to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetricsConfig.java
index 149da77..907d88e 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/MetricsConfig.java
@@ -14,17 +14,38 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.monitor.service;
 
-public interface DemoService {
+package org.apache.dubbo.config;
 
-    String sayName(String name);
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.config.support.Parameter;
 
-    void timeoutException();
+public class MetricsConfig extends AbstractConfig {
 
-    void throwDemoException() throws Exception;
+    private static final long serialVersionUID = -9089919311611546383L;
 
-    int echo(int i);
+    private String port;
+    private String protocol;
 
+    public MetricsConfig() {
+    }
+
+    @Parameter(key = Constants.METRICS_PORT)
+    public String getPort() {
+        return port;
+    }
+
+    public void setPort(String port) {
+        this.port = port;
+    }
+
+    @Parameter(key = Constants.METRICS_PROTOCOL)
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
 
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index d265399..87ccdf3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -260,6 +260,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
         Map<String, String> map = new HashMap<String, String>();
 
         map.put(Constants.SIDE_KEY, Constants.CONSUMER_SIDE);
+
         appendRuntimeParameters(map);
         if (!isGeneric()) {
             String revision = Version.getVersion(interfaceClass, version);
@@ -276,6 +277,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
             }
         }
         map.put(Constants.INTERFACE_KEY, interfaceName);
+        appendParameters(map, metrics);
         appendParameters(map, application);
         appendParameters(map, module);
         appendParameters(map, consumer, Constants.DEFAULT_KEY);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index 24d6b83..dce2c94 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -426,7 +426,9 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
 
         Map<String, String> map = new HashMap<String, String>();
         map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE);
+
         appendRuntimeParameters(map);
+        appendParameters(map, metrics);
         appendParameters(map, application);
         appendParameters(map, module);
         appendParameters(map, provider, Constants.DEFAULT_KEY);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
index 3daec13..3c1111b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.config.ModuleConfig;
 import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.MetricsConfig;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.apache.dubbo.config.support.Parameter;
@@ -216,6 +217,22 @@ public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
             }
         }
 
+        if (getMetrics() == null) {
+            Map<String, MetricsConfig> metricsConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class, false, false);
+            if (metricsConfigMap != null && metricsConfigMap.size() > 0) {
+                MetricsConfig metricsConfig = null;
+                for (MetricsConfig config : metricsConfigMap.values()) {
+                    if (metricsConfig != null) {
+                        throw new IllegalStateException("Duplicate metrics configs: " + metricsConfig + " and " + config);
+                    }
+                    metricsConfig = config;
+                }
+                if (metricsConfig != null) {
+                    setMetrics(metricsConfig);
+                }
+            }
+        }
+
         if (shouldInit()) {
             getObject();
         }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
index 7c216a6..ec132ee 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
@@ -19,15 +19,16 @@ package org.apache.dubbo.config.spring;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConfigCenterConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
-import org.apache.dubbo.config.ModuleConfig;
-import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
-import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.MetricsConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ConfigCenterConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.MonitorConfig;
+import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
@@ -256,6 +257,22 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
             }
         }
 
+        if (getMetrics() == null) {
+            Map<String, MetricsConfig> metricsConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class, false, false);
+            if (metricsConfigMap != null && metricsConfigMap.size() > 0) {
+                MetricsConfig metricsConfig = null;
+                for (MetricsConfig config : metricsConfigMap.values()) {
+                    if (metricsConfig != null) {
+                        throw new IllegalStateException("Duplicate metrics configs: " + metricsConfig + " and " + config);
+                    }
+                    metricsConfig = config;
+                }
+                if (metricsConfig != null) {
+                    setMetrics(metricsConfig);
+                }
+            }
+        }
+
         if (StringUtils.isEmpty(getProtocolIds())) {
             if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getProtocolIds())) {
                 setProtocolIds(getProvider().getProtocolIds());
@@ -352,4 +369,4 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
     public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
         this.applicationEventPublisher = applicationEventPublisher;
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index 4d7b0af..915a9ea 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -17,14 +17,16 @@
 package org.apache.dubbo.config.spring.schema;
 
 import org.apache.dubbo.common.Version;
+
 import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConsumerConfig;
 import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.MonitorConfig;
-import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.MetricsConfig;
 import org.apache.dubbo.config.ProviderConfig;
-import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.spring.ConfigCenterBean;
 import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.ServiceBean;
@@ -50,6 +52,7 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport {
         registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
         registerBeanDefinitionParser("metadata-report", new DubboBeanDefinitionParser(MetadataReportConfig.class, true));
         registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
+        registerBeanDefinitionParser("metrics", new DubboBeanDefinitionParser(MetricsConfig.class, true));
         registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
         registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
         registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index 6568ab1..01996ae 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -773,6 +773,19 @@
         </xsd:attribute>
     </xsd:complexType>
 
+    <xsd:complexType name="metricsType">
+        <xsd:attribute name="port" type="xsd:string" use="required">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metrics service port. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="protocol" type="xsd:string" use="required">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metrics service protocol. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+    </xsd:complexType>
+
     <xsd:complexType name="methodType">
         <xsd:complexContent>
             <xsd:extension base="abstractMethodType">
@@ -1459,4 +1472,15 @@
         </xsd:annotation>
     </xsd:element>
 
+    <xsd:element name="metrics" type="metricsType">
+        <xsd:annotation>
+            <xsd:documentation><![CDATA[ The metrics service ]]></xsd:documentation>
+            <xsd:appinfo>
+                <tool:annotation>
+                    <tool:exports type="org.apache.dubbo.config.MetricsConfig"/>
+                </tool:annotation>
+            </xsd:appinfo>
+        </xsd:annotation>
+    </xsd:element>
+
 </xsd:schema>
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 03fe3f7..33ff3ad 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -767,6 +767,19 @@
         </xsd:attribute>
     </xsd:complexType>
 
+    <xsd:complexType name="metricsType">
+        <xsd:attribute name="port" type="xsd:string" use="required">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metrics service port. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+        <xsd:attribute name="protocol" type="xsd:string" use="required">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metrics service protocol. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
+    </xsd:complexType>
+
     <xsd:complexType name="methodType">
         <xsd:complexContent>
             <xsd:extension base="abstractMethodType">
@@ -1484,4 +1497,15 @@
         </xsd:annotation>
     </xsd:element>
 
+    <xsd:element name="metrics" type="metricsType">
+        <xsd:annotation>
+            <xsd:documentation><![CDATA[ The metrics service ]]></xsd:documentation>
+            <xsd:appinfo>
+                <tool:annotation>
+                    <tool:exports type="org.apache.dubbo.config.MetricsConfig"/>
+                </tool:annotation>
+            </xsd:appinfo>
+        </xsd:annotation>
+    </xsd:element>
+
 </xsd:schema>
diff --git a/dubbo-monitor/dubbo-monitor-api/pom.xml b/dubbo-monitor/dubbo-monitor-api/pom.xml
index ec69d4e..14f157a 100644
--- a/dubbo-monitor/dubbo-monitor-api/pom.xml
+++ b/dubbo-monitor/dubbo-monitor-api/pom.xml
@@ -36,18 +36,17 @@
         </dependency>
 
         <dependency>
-            <groupId>com.alibaba.middleware</groupId>
-            <artifactId>metrics-core-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>com.alibaba.middleware</groupId>
-            <artifactId>metrics-core-impl</artifactId>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-remoting-netty4</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
         </dependency>
+
         <dependency>
-            <groupId>com.alibaba.middleware</groupId>
-            <artifactId>metrics-common</artifactId>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-serialization-hessian2</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
         </dependency>
-
-
     </dependencies>
 </project>
diff --git a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MetricsService.java
similarity index 79%
copy from dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java
copy to dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MetricsService.java
index 149da77..41c7b3b 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java
+++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/MetricsService.java
@@ -14,17 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.monitor.service;
-
-public interface DemoService {
-
-    String sayName(String name);
-
-    void timeoutException();
-
-    void throwDemoException() throws Exception;
-
-    int echo(int i);
 
+package org.apache.dubbo.monitor;
 
+public interface MetricsService {
+    String getMetricsByGroup(String group);
 }
diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MetricsFilter.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MetricsFilter.java
deleted file mode 100644
index 648d231..0000000
--- a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/monitor/support/MetricsFilter.java
+++ /dev/null
@@ -1,102 +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.dubbo.monitor.support;
-
-import com.alibaba.metrics.FastCompass;
-import com.alibaba.metrics.MetricLevel;
-import com.alibaba.metrics.MetricManager;
-import com.alibaba.metrics.MetricName;
-import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.rpc.Filter;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.support.RpcUtils;
-
-import java.util.HashMap;
-
-public class MetricsFilter implements Filter {
-
-    private static final Logger logger = LoggerFactory.getLogger(MetricsFilter.class);
-
-    @Override
-    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
-        RpcContext context = RpcContext.getContext();
-        boolean isProvider = context.isProviderSide();
-        long start = System.currentTimeMillis();
-        try {
-            Result result = invoker.invoke(invocation); // proceed invocation chain
-            long duration = System.currentTimeMillis() - start;
-            reportMetrics(invoker, invocation, duration, "success", isProvider);
-            return result;
-        } catch (RpcException e) {
-            long duration = System.currentTimeMillis() - start;
-            String result = "error";
-            if (e.isTimeout()) {
-                result = "timeoutError";
-            }
-            if (e.isBiz()) {
-                result = "bisError";
-            }
-            if (e.isNetwork()) {
-                result = "networkError";
-            }
-            if (e.isSerialization()) {
-                result = "serializationError";
-            }
-            reportMetrics(invoker, invocation, duration, result, isProvider);
-            throw e;
-        }
-    }
-
-    private void reportMetrics(Invoker<?> invoker, Invocation invocation, long duration, String result, boolean isProvider) {
-        String serviceName = invoker.getInterface().getName();
-        String methodName = RpcUtils.getMethodName(invocation);
-        MetricName global;
-        MetricName method;
-        if (isProvider) {
-            global = new MetricName(Constants.DUBBO_PROVIDER, MetricLevel.MAJOR);
-            method = new MetricName(Constants.DUBBO_PROVIDER_METHOD, new HashMap<String, String>(4) {
-                {
-                    put(Constants.SERVICE, serviceName);
-                    put(Constants.METHOD, methodName);
-                }
-            }, MetricLevel.NORMAL);
-        } else {
-            global = new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR);
-            method = new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
-                {
-                    put(Constants.SERVICE, serviceName);
-                    put(Constants.METHOD, methodName);
-                }
-            }, MetricLevel.NORMAL);
-        }
-        setCompassQuantity(Constants.DUBBO_GROUP, result, duration, global, method);
-    }
-
-    private void setCompassQuantity(String groupName, String result, long duration, MetricName... metricNames) {
-        for (MetricName metricName : metricNames) {
-            FastCompass compass = MetricManager.getFastCompass(groupName, metricName);
-            compass.record(duration, result);
-        }
-    }
-
-}
diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter b/dubbo-monitor/dubbo-monitor-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
index 2407d6b..fbeff59 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
+++ b/dubbo-monitor/dubbo-monitor-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
@@ -1,2 +1 @@
 monitor=org.apache.dubbo.monitor.support.MonitorFilter
-metrics=org.apache.dubbo.monitor.support.MetricsFilter
diff --git a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MetricsFilterTest.java b/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MetricsFilterTest.java
deleted file mode 100644
index 8645aa2..0000000
--- a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/support/MetricsFilterTest.java
+++ /dev/null
@@ -1,167 +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.dubbo.monitor.support;
-
-import com.alibaba.metrics.FastCompass;
-import com.alibaba.metrics.IMetricManager;
-import com.alibaba.metrics.MetricLevel;
-import com.alibaba.metrics.MetricManager;
-import com.alibaba.metrics.MetricName;
-import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.monitor.service.DemoService;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcInvocation;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import java.util.HashMap;
-
-public class MetricsFilterTest {
-
-    private final Invoker<DemoService> serviceInvoker = new Invoker<DemoService>() {
-        @Override
-        public Class<DemoService> getInterface() {
-            return DemoService.class;
-        }
-
-        public URL getUrl() {
-            return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880/org.apache.dubbo.monitor.service.DemoService");
-        }
-
-        @Override
-        public boolean isAvailable() {
-            return false;
-        }
-
-        public Result invoke(Invocation invocation) throws RpcException {
-            return null;
-        }
-
-        @Override
-        public void destroy() {
-        }
-    };
-
-    private final Invoker<DemoService> timeoutInvoker = new Invoker<DemoService>() {
-        @Override
-        public Class<DemoService> getInterface() {
-            return DemoService.class;
-        }
-
-        public URL getUrl() {
-            return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880/org.apache.dubbo.monitor.service.DemoService");
-        }
-
-        @Override
-        public boolean isAvailable() {
-            return false;
-        }
-
-        public Result invoke(Invocation invocation) throws RpcException {
-            throw new RpcException(RpcException.TIMEOUT_EXCEPTION);
-        }
-
-        @Override
-        public void destroy() {
-        }
-    };
-
-    @Test
-    public void testConsumerSuccess() throws Exception {
-        IMetricManager metricManager = MetricManager.getIMetricManager();
-        metricManager.clear();
-        MetricsFilter metricsFilter = new MetricsFilter();
-        Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
-        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
-        RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE));
-        for (int i = 0; i < 100; i++) {
-            metricsFilter.invoke(serviceInvoker, invocation);
-        }
-        FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR));
-        FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
-            {
-                put(Constants.SERVICE, "org.apache.dubbo.monitor.service.DemoService");
-                put(Constants.METHOD, "sayName");
-            }
-        }, MetricLevel.NORMAL));
-        long timestamp = System.currentTimeMillis() / 5000 * 5000;
-        Assertions.assertEquals(100, dubboClient.getMethodCountPerCategory(0).get("success").get(timestamp));
-        timestamp = timestamp / 15000 * 15000;
-        Assertions.assertEquals(100, dubboMethod.getMethodCountPerCategory(0).get("success").get(timestamp));
-
-    }
-
-    @Test
-    public void testConsumerTimeout() {
-        IMetricManager metricManager = MetricManager.getIMetricManager();
-        metricManager.clear();
-        MetricsFilter metricsFilter = new MetricsFilter();
-        Invocation invocation = new RpcInvocation("timeoutException", null, null);
-        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
-        RpcContext.getContext().setUrl(timeoutInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE)
-                                                              .addParameter(Constants.TIMEOUT_KEY, 300));
-        for (int i = 0; i < 10; i++) {
-            try {
-                metricsFilter.invoke(timeoutInvoker, invocation);
-            } catch (RpcException e) {
-                //ignore
-            }
-        }
-        FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR));
-        FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
-            {
-                put(Constants.SERVICE, "org.apache.dubbo.monitor.service.DemoService");
-                put(Constants.METHOD, "timeoutException");
-            }
-        }, MetricLevel.NORMAL));
-        long timestamp = System.currentTimeMillis() / 5000 * 5000;
-        Assertions.assertEquals(10, dubboClient.getMethodCountPerCategory(0).get("timeoutError").get(timestamp));
-        timestamp = timestamp / 15000 * 15000;
-        Assertions.assertEquals(10, dubboMethod.getMethodCountPerCategory(0).get("timeoutError").get(timestamp));
-
-    }
-
-    @Test
-    public void testProviderSuccess() throws Exception {
-        IMetricManager metricManager = MetricManager.getIMetricManager();
-        metricManager.clear();
-        MetricsFilter metricsFilter = new MetricsFilter();
-        Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
-        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
-        RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.PROVIDER));
-        for (int i = 0; i < 100; i++) {
-            metricsFilter.invoke(serviceInvoker, invocation);
-        }
-        FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_PROVIDER, MetricLevel.MAJOR));
-        FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_PROVIDER_METHOD, new HashMap<String, String>(4) {
-            {
-                put(Constants.SERVICE, "org.apache.dubbo.monitor.service.DemoService");
-                put(Constants.METHOD, "sayName");
-            }
-        }, MetricLevel.NORMAL));
-        long timestamp = System.currentTimeMillis() / 5000 * 5000;
-        Assertions.assertEquals(100, dubboClient.getMethodCountPerCategory(0).get("success").get(timestamp));
-        timestamp = timestamp / 15000 * 15000;
-        Assertions.assertEquals(100, dubboMethod.getMethodCountPerCategory(0).get("success").get(timestamp));
-    }
-}
diff --git a/dubbo-monitor/dubbo-monitor-default/pom.xml b/dubbo-monitor/dubbo-monitor-default/pom.xml
index 0b84690..de785c1 100644
--- a/dubbo-monitor/dubbo-monitor-default/pom.xml
+++ b/dubbo-monitor/dubbo-monitor-default/pom.xml
@@ -35,6 +35,18 @@
             <version>${project.parent.version}</version>
         </dependency>
         <dependency>
+            <groupId>com.alibaba.middleware</groupId>
+            <artifactId>metrics-core-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.middleware</groupId>
+            <artifactId>metrics-core-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.middleware</groupId>
+            <artifactId>metrics-common</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-rpc-dubbo</artifactId>
             <version>${project.parent.version}</version>
@@ -53,4 +65,4 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-</project>
\ No newline at end of file
+</project>
diff --git a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
new file mode 100644
index 0000000..c613f75
--- /dev/null
+++ b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
@@ -0,0 +1,254 @@
+/*
+ * 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.monitor.dubbo;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.metrics.FastCompass;
+import com.alibaba.metrics.MetricLevel;
+import com.alibaba.metrics.MetricManager;
+import com.alibaba.metrics.MetricName;
+import com.alibaba.metrics.MetricRegistry;
+import com.alibaba.metrics.common.CollectLevel;
+import com.alibaba.metrics.common.MetricObject;
+import com.alibaba.metrics.common.MetricsCollector;
+import com.alibaba.metrics.common.MetricsCollectorFactory;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.store.DataStore;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.monitor.MetricsService;
+import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcResult;
+import org.apache.dubbo.rpc.support.RpcUtils;
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class MetricsFilter implements Filter {
+
+    private static final Logger logger = LoggerFactory.getLogger(MetricsFilter.class);
+    private static volatile AtomicBoolean exported = new AtomicBoolean(false);
+    private Integer port;
+    private String protocolName;
+
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        if (exported.compareAndSet(false, true)) {
+            this.protocolName = invoker.getUrl().getParameter(Constants.METRICS_PROTOCOL) == null ?
+                    Constants.DEFAULT_PROTOCOL : invoker.getUrl().getParameter(Constants.METRICS_PROTOCOL);
+
+            Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(protocolName);
+
+            this.port = invoker.getUrl().getParameter(Constants.METRICS_PORT) == null ?
+                    protocol.getDefaultPort() : Integer.valueOf(invoker.getUrl().getParameter(Constants.METRICS_PORT));
+
+            Invoker<MetricsService> metricsInvoker = initMetricsInvoker();
+
+            try {
+                protocol.export(metricsInvoker);
+            } catch (RuntimeException e) {
+                logger.error("Metrics Service need to be configured" +
+                        " when multiple processes are running on a host" + e.getMessage());
+            }
+        }
+
+        RpcContext context = RpcContext.getContext();
+        boolean isProvider = context.isProviderSide();
+        long start = System.currentTimeMillis();
+        try {
+            Result result = invoker.invoke(invocation); // proceed invocation chain
+            long duration = System.currentTimeMillis() - start;
+            reportMetrics(invoker, invocation, duration, "success", isProvider);
+            return result;
+        } catch (RpcException e) {
+            long duration = System.currentTimeMillis() - start;
+            String result = "error";
+            if (e.isTimeout()) {
+                result = "timeoutError";
+            }
+            if (e.isBiz()) {
+                result = "bisError";
+            }
+            if (e.isNetwork()) {
+                result = "networkError";
+            }
+            if (e.isSerialization()) {
+                result = "serializationError";
+            }
+            reportMetrics(invoker, invocation, duration, result, isProvider);
+            throw e;
+        }
+    }
+
+    private String buildMethodName(Invocation invocation) {
+        String methodName = RpcUtils.getMethodName(invocation);
+        StringBuilder method = new StringBuilder(methodName);
+        Class<?>[] argTypes = RpcUtils.getParameterTypes(invocation);
+
+        method.append("(");
+
+        for (int i = 0; i < argTypes.length; i++) {
+            method.append((i == 0 ? "" : ", ") + argTypes[i].getSimpleName());
+        }
+        method.append(")");
+        Class<?> returnType = RpcUtils.getReturnType(invocation);
+        String typeName = null;
+        if(returnType != null) {
+            typeName = returnType.getTypeName();
+            typeName = typeName.substring(typeName.lastIndexOf(".") + 1);
+        }
+
+        return (typeName == null ? "void" : typeName) + " " + method;
+    }
+
+    private void reportMetrics(Invoker<?> invoker, Invocation invocation, long duration, String result, boolean isProvider) {
+        String serviceName = invoker.getInterface().getName();
+        String methodName = buildMethodName(invocation);
+        MetricName global;
+        MetricName method;
+        if (isProvider) {
+            global = new MetricName(Constants.DUBBO_PROVIDER, MetricLevel.MAJOR);
+            method = new MetricName(Constants.DUBBO_PROVIDER_METHOD, new HashMap<String, String>(4) {
+                {
+                    put(Constants.SERVICE, serviceName);
+                    put(Constants.METHOD, methodName);
+                }
+            }, MetricLevel.NORMAL);
+        } else {
+            global = new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR);
+            method = new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
+                {
+                    put(Constants.SERVICE, serviceName);
+                    put(Constants.METHOD, methodName);
+                }
+            }, MetricLevel.NORMAL);
+        }
+        setCompassQuantity(Constants.DUBBO_GROUP, result, duration, global, method);
+    }
+
+    private void setCompassQuantity(String groupName, String result, long duration, MetricName... metricNames) {
+        for (MetricName metricName : metricNames) {
+            FastCompass compass = MetricManager.getFastCompass(groupName, metricName);
+            compass.record(duration, result);
+        }
+    }
+
+    private List<MetricObject> getThreadPoolMessage() {
+        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
+        Map<String, Object> executors = dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);
+
+        List<MetricObject> threadPoolMtricList = new ArrayList<>();
+        for (Map.Entry<String, Object> entry : executors.entrySet()) {
+            String port = entry.getKey();
+            ExecutorService executor = (ExecutorService) entry.getValue();
+            if (executor instanceof ThreadPoolExecutor) {
+                ThreadPoolExecutor tp = (ThreadPoolExecutor) executor;
+                // ignore metrcis service
+                if (port.equals(this.port + "")) {
+                    continue;
+                }
+
+                threadPoolMtricList.add(value2MetricObject("threadPool.active", tp.getActiveCount(), MetricLevel.MAJOR));
+                threadPoolMtricList.add(value2MetricObject("threadPool.core", tp.getCorePoolSize(), MetricLevel.MAJOR));
+                threadPoolMtricList.add(value2MetricObject("threadPool.max", tp.getMaximumPoolSize(), MetricLevel.MAJOR));
+                threadPoolMtricList.add(value2MetricObject("threadPool.current", tp.getPoolSize(), MetricLevel.MAJOR));
+            }
+        }
+
+        return threadPoolMtricList;
+    }
+
+    private MetricObject value2MetricObject(String metric, Integer value, MetricLevel level) {
+        if (metric == null || value == null || level == null)
+            return null;
+
+        return new MetricObject
+                .Builder(metric)
+                .withValue(value)
+                .withLevel(level)
+                .build();
+    }
+
+    private Invoker<MetricsService> initMetricsInvoker() {
+        Invoker<MetricsService> metricsInvoker = new Invoker<MetricsService>() {
+            @Override
+            public Class<MetricsService> getInterface() {
+                return MetricsService.class;
+            }
+
+            @Override
+            public Result invoke(Invocation invocation) throws RpcException {
+                String group = invocation.getArguments()[0].toString();
+                MetricRegistry registry = MetricManager.getIMetricManager().getMetricRegistryByGroup(group);
+
+                SortedMap<MetricName, FastCompass> fastCompasses = registry.getFastCompasses();
+
+                long timestamp = System.currentTimeMillis();
+                double rateFactor = TimeUnit.SECONDS.toSeconds(1);
+                double durationFactor = 1.0 / TimeUnit.MILLISECONDS.toNanos(1);
+
+
+                MetricsCollector collector = MetricsCollectorFactory.createNew(
+                        CollectLevel.NORMAL, Collections.EMPTY_MAP, rateFactor, durationFactor, null);
+
+                for (Map.Entry<MetricName, FastCompass> entry : fastCompasses.entrySet()) {
+                    collector.collect(entry.getKey(), entry.getValue(), timestamp);
+                }
+
+                RpcResult result = new RpcResult();
+
+                List res = collector.build();
+                res.addAll(getThreadPoolMessage());
+                result.setValue(JSON.toJSONString(res));
+                return result;
+            }
+
+            @Override
+            public URL getUrl() {
+                return URL.valueOf(protocolName + "://" + NetUtils.getIpByConfig() + ":" + port + "/" + MetricsService.class.getName());
+            }
+
+            @Override
+            public boolean isAvailable() {
+                return false;
+            }
+
+            @Override
+            public void destroy() {
+
+            }
+        };
+
+        return metricsInvoker;
+    }
+}
diff --git a/dubbo-monitor/dubbo-monitor-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter b/dubbo-monitor/dubbo-monitor-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
new file mode 100644
index 0000000..8441a9c
--- /dev/null
+++ b/dubbo-monitor/dubbo-monitor-default/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter
@@ -0,0 +1 @@
+metrics=org.apache.dubbo.monitor.dubbo.MetricsFilter
diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java
new file mode 100644
index 0000000..bca62f4
--- /dev/null
+++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java
@@ -0,0 +1,289 @@
+/*
+ * 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.monitor.dubbo;
+
+import com.alibaba.metrics.FastCompass;
+import com.alibaba.metrics.IMetricManager;
+import com.alibaba.metrics.MetricLevel;
+import com.alibaba.metrics.MetricManager;
+import com.alibaba.metrics.MetricName;
+import com.alibaba.metrics.common.MetricObject;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.monitor.MetricsService;
+import org.apache.dubbo.monitor.dubbo.service.DemoService;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MetricsFilterTest {
+
+    private final Invoker<DemoService> serviceInvoker = new Invoker<DemoService>() {
+        @Override
+        public Class<DemoService> getInterface() {
+            return DemoService.class;
+        }
+
+        public URL getUrl() {
+            return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880/org.apache.dubbo.monitor.dubbo.service.DemoService");
+        }
+
+        @Override
+        public boolean isAvailable() {
+            return false;
+        }
+
+        public Result invoke(Invocation invocation) throws RpcException {
+            return null;
+        }
+
+        @Override
+        public void destroy() {
+        }
+    };
+
+    private final Invoker<DemoService> timeoutInvoker = new Invoker<DemoService>() {
+        @Override
+        public Class<DemoService> getInterface() {
+            return DemoService.class;
+        }
+
+        public URL getUrl() {
+            return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880/org.apache.dubbo.monitor.dubbo.service.DemoService");
+        }
+
+        @Override
+        public boolean isAvailable() {
+            return false;
+        }
+
+        public Result invoke(Invocation invocation) throws RpcException {
+            throw new RpcException(RpcException.TIMEOUT_EXCEPTION);
+        }
+
+        @Override
+        public void destroy() {
+        }
+    };
+
+    @Test
+    public void testConsumerSuccess() throws Exception {
+        IMetricManager metricManager = MetricManager.getIMetricManager();
+        metricManager.clear();
+        MetricsFilter metricsFilter = new MetricsFilter();
+        Invocation invocation = new RpcInvocation("sayName", new Class<?>[] {Integer.class}, new Object[0]);
+        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
+        RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE));
+        for (int i = 0; i < 100; i++) {
+            metricsFilter.invoke(serviceInvoker, invocation);
+        }
+        FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR));
+        FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
+            {
+                put(Constants.SERVICE, "org.apache.dubbo.monitor.dubbo.service.DemoService");
+                put(Constants.METHOD, "void sayName(Integer)");
+            }
+        }, MetricLevel.NORMAL));
+        long timestamp = System.currentTimeMillis() / 5000 * 5000;
+        Assertions.assertEquals(100, dubboClient.getMethodCountPerCategory(0).get("success").get(timestamp));
+        timestamp = timestamp / 15000 * 15000;
+        Assertions.assertEquals(100, dubboMethod.getMethodCountPerCategory(0).get("success").get(timestamp));
+
+    }
+
+    @Test
+    public void testConsumerTimeout() {
+        IMetricManager metricManager = MetricManager.getIMetricManager();
+        metricManager.clear();
+        MetricsFilter metricsFilter = new MetricsFilter();
+        Invocation invocation = new RpcInvocation("timeoutException", null, null);
+        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
+        RpcContext.getContext().setUrl(timeoutInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE)
+                .addParameter(Constants.TIMEOUT_KEY, 300));
+        for (int i = 0; i < 10; i++) {
+            try {
+                metricsFilter.invoke(timeoutInvoker, invocation);
+            } catch (RpcException e) {
+                //ignore
+            }
+        }
+        FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR));
+        FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
+            {
+                put(Constants.SERVICE, "org.apache.dubbo.monitor.dubbo.service.DemoService");
+                put(Constants.METHOD, "void timeoutException()");
+            }
+        }, MetricLevel.NORMAL));
+        long timestamp = System.currentTimeMillis() / 5000 * 5000;
+        Assertions.assertEquals(10, dubboClient.getMethodCountPerCategory(0).get("timeoutError").get(timestamp));
+        timestamp = timestamp / 15000 * 15000;
+        Assertions.assertEquals(10, dubboMethod.getMethodCountPerCategory(0).get("timeoutError").get(timestamp));
+
+    }
+
+    @Test
+    public void testProviderSuccess() throws Exception {
+        IMetricManager metricManager = MetricManager.getIMetricManager();
+        metricManager.clear();
+        MetricsFilter metricsFilter = new MetricsFilter();
+        Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
+        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
+        RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.PROVIDER));
+        for (int i = 0; i < 100; i++) {
+            metricsFilter.invoke(serviceInvoker, invocation);
+        }
+        FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_PROVIDER, MetricLevel.MAJOR));
+        FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_PROVIDER_METHOD, new HashMap<String, String>(4) {
+            {
+                put(Constants.SERVICE, "org.apache.dubbo.monitor.dubbo.service.DemoService");
+                put(Constants.METHOD, "void sayName()");
+            }
+        }, MetricLevel.NORMAL));
+        long timestamp = System.currentTimeMillis() / 5000 * 5000;
+        Assertions.assertEquals(100, dubboClient.getMethodCountPerCategory(0).get("success").get(timestamp));
+        timestamp = timestamp / 15000 * 15000;
+        Assertions.assertEquals(100, dubboMethod.getMethodCountPerCategory(0).get("success").get(timestamp));
+    }
+
+    @Test
+    public void testInvokeMetricsService() {
+        IMetricManager metricManager = MetricManager.getIMetricManager();
+        metricManager.clear();
+        MetricsFilter metricsFilter = new MetricsFilter();
+        Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
+        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
+        RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.PROVIDER_SIDE)
+                .addParameter(Constants.TIMEOUT_KEY, 300));
+        for (int i = 0; i < 50; i++) {
+            try {
+                metricsFilter.invoke(serviceInvoker, invocation);
+                metricsFilter.invoke(timeoutInvoker, invocation);
+            } catch (RpcException e) {
+                //ignore
+            }
+        }
+        Protocol protocol = new DubboProtocol();
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":20880/" + MetricsService.class.getName());
+        Invoker<MetricsService> invoker = protocol.refer(MetricsService.class, url);
+        invocation = new RpcInvocation("getMetricsByGroup", new Class<?>[]{String.class}, new Object[]{Constants.DUBBO_GROUP});
+        try{
+            Thread.sleep(5000);
+        } catch (Exception e) {
+            // ignore
+        }
+        String resStr = invoker.invoke(invocation).getValue().toString();
+        List<MetricObject> metricObjectList = new Gson().fromJson(resStr, new TypeToken<List<MetricObject>>(){}.getType());
+        Map<String, Object> metricMap = new HashMap<>();
+        for(int i = 0; i < metricObjectList.size(); i++) {
+            MetricObject object = metricObjectList.get(i);
+            String metric = object.getMetric().substring(object.getMetric().lastIndexOf(".") + 1);
+            if((double)object.getValue() > 0.0 && object.getMetricLevel().equals(MetricLevel.MAJOR))
+                metricMap.put(metric, object.getValue());
+        }
+
+        Assertions.assertEquals(50.0, metricMap.get("success_bucket_count"));
+        Assertions.assertEquals(50.0, metricMap.get("timeoutError_bucket_count"));
+        Assertions.assertEquals(100.0, metricMap.get("bucket_count"));
+        Assertions.assertEquals(100.0 / 5, metricMap.get("qps"));
+        Assertions.assertEquals(50.0 / 100.0, metricMap.get("success_rate"));
+    }
+
+    @Test
+    public void testInvokeMetricsMethodService() {
+        IMetricManager metricManager = MetricManager.getIMetricManager();
+        metricManager.clear();
+        MetricsFilter metricsFilter = new MetricsFilter();
+        Invocation sayNameInvocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
+        Invocation echoInvocation = new RpcInvocation("echo", new Class<?>[]{Integer.class}, new Integer[]{1});
+        RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
+        RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.PROVIDER_SIDE)
+                .addParameter(Constants.TIMEOUT_KEY, 300));
+        for (int i = 0; i < 50; i++) {
+                metricsFilter.invoke(serviceInvoker, sayNameInvocation);
+                metricsFilter.invoke(serviceInvoker, echoInvocation);
+            try {
+                metricsFilter.invoke(timeoutInvoker, sayNameInvocation);
+            } catch (RpcException e) {
+                // ignore
+            }
+            try {
+                metricsFilter.invoke(timeoutInvoker, echoInvocation);
+            } catch (RpcException e) {
+                // ignore
+            }
+        }
+
+        Protocol protocol = new DubboProtocol();
+        URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":20880/" + MetricsService.class.getName());
+        Invoker<MetricsService> invoker = protocol.refer(MetricsService.class, url);
+        Invocation invocation = new RpcInvocation("getMetricsByGroup", new Class<?>[]{String.class}, new Object[]{Constants.DUBBO_GROUP});
+        try{
+            Thread.sleep(15000);
+        } catch (Exception e) {
+            // ignore
+        }
+        String resStr = invoker.invoke(invocation).getValue().toString();
+        List<MetricObject> metricObjectList = new Gson().fromJson(resStr, new TypeToken<List<MetricObject>>(){}.getType());
+        Map<String, Map<String, Object>> methodMetricMap = new HashMap<>();
+        for(int i = 0; i < metricObjectList.size(); i++) {
+            MetricObject object = metricObjectList.get(i);
+            String service = object.getTags().get("service");
+            String method = service + "." + object.getTags().get("method");
+            String metric = object.getMetric().substring(object.getMetric().lastIndexOf(".") + 1);
+            Map map = methodMetricMap.get(method);
+            if(map == null) {
+                map = new HashMap();
+                methodMetricMap.put(method, map);
+            }
+            map.put(metric, object.getValue());
+        }
+
+        Assertions.assertEquals(50.0,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void sayName()").get("success_bucket_count"));
+        Assertions.assertEquals(50.0,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void echo(Integer)").get("success_bucket_count"));
+
+        Assertions.assertEquals(50.0,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void sayName()").get("timeoutError_bucket_count"));
+        Assertions.assertEquals(50.0,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void echo(Integer)").get("timeoutError_bucket_count"));
+
+        Assertions.assertEquals(100.0 / 15,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void sayName()").get("qps"));
+        Assertions.assertEquals(100.0 / 15,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void echo(Integer)").get("qps"));
+
+        Assertions.assertEquals(50.0 / 100.0,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void sayName()").get("success_rate"));
+        Assertions.assertEquals(50.0 / 100.0,
+                methodMetricMap.get("org.apache.dubbo.monitor.dubbo.service.DemoService.void echo(Integer)").get("success_rate"));
+    }
+}
diff --git a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/service/DemoService.java
similarity index 95%
rename from dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java
rename to dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/service/DemoService.java
index 149da77..a2fb2d1 100644
--- a/dubbo-monitor/dubbo-monitor-api/src/test/java/org/apache/dubbo/monitor/service/DemoService.java
+++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/service/DemoService.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.monitor.service;
+package org.apache.dubbo.monitor.dubbo.service;
 
 public interface DemoService {