You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2018/07/06 12:26:37 UTC

[incubator-dubbo] branch master updated: Merge pull request #1966, introduces dubbo metrics API module.

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

liujun 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 b36a6ee  Merge pull request #1966, introduces dubbo metrics API module.
b36a6ee is described below

commit b36a6eea627f9854c909b3a9368ddb06fc6610e4
Author: Huxing Zhang <hu...@gmail.com>
AuthorDate: Fri Jul 6 20:26:16 2018 +0800

    Merge pull request #1966, introduces dubbo metrics API module.
    
    Fixes #1922.
---
 dubbo-metrics/dubbo-metrics-api/pom.xml            |  15 +
 .../org/apache/dubbo/metrics/BucketCounter.java    |  57 ++++
 .../java/org/apache/dubbo/metrics/Compass.java     |  75 +++++
 .../java/org/apache/dubbo/metrics/Counter.java     |  50 +++
 .../java/org/apache/dubbo/metrics/Counting.java    |  29 ++
 .../main/java/org/apache/dubbo/metrics/Gauge.java  |  42 +++
 .../org/apache/dubbo/metrics/IMetricManager.java   | 104 ++++++
 .../main/java/org/apache/dubbo/metrics/Metric.java |  29 ++
 .../org/apache/dubbo/metrics/MetricFilter.java     |  42 +++
 .../java/org/apache/dubbo/metrics/MetricLevel.java |  53 +++
 .../org/apache/dubbo/metrics/MetricManager.java    | 108 ++++++
 .../java/org/apache/dubbo/metrics/MetricName.java  | 367 +++++++++++++++++++++
 .../org/apache/dubbo/metrics/MetricRegistry.java   | 158 +++++++++
 .../java/org/apache/dubbo/metrics/MetricSet.java   |  33 ++
 .../org/apache/dubbo/metrics/NOPMetricManager.java | 292 ++++++++++++++++
 .../apache/dubbo/metrics/MetricManagerTest.java    |  40 +++
 .../org/apache/dubbo/metrics/MetricNameTest.java   | 125 +++++++
 dubbo-metrics/pom.xml                              |  41 +++
 pom.xml                                            |   1 +
 19 files changed, 1661 insertions(+)

diff --git a/dubbo-metrics/dubbo-metrics-api/pom.xml b/dubbo-metrics/dubbo-metrics-api/pom.xml
new file mode 100644
index 0000000..3ebdc20
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/pom.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>dubbo-metrics</artifactId>
+        <groupId>org.apache.dubbo</groupId>
+        <version>2.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-metrics-api</artifactId>
+
+
+</project>
\ No newline at end of file
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/BucketCounter.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/BucketCounter.java
new file mode 100644
index 0000000..8c449fb
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/BucketCounter.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.metrics;
+
+import java.util.Map;
+
+/**
+ * Store the count in multiple buckets,
+ * every event will go into one specific bucket according to the happening timestamp.
+ * The BucketCounter will reserve data for the last N time interval,
+ * older values will be automatically discarded.
+ */
+public interface BucketCounter extends Metric {
+
+    /**
+     * update the counter to the given bucket
+     */
+    void update();
+
+    /**
+     * update the counter to the given bucket
+     */
+    void update(long n);
+
+    /**
+     * Return the bucket count, keyed by timestamp
+     * @return the bucket count, keyed by timestamp
+     */
+    Map<Long, Long> getBucketCounts();
+
+    /**
+     * Return the bucket count, keyed by timestamp, since (including) the startTime.
+     * @param startTime the start time
+     * @return the bucket count, keyed by timestamp
+     */
+    Map<Long, Long> getBucketCounts(long startTime);
+
+    /**
+     * Get the interval of the bucket
+     * @return the interval of the bucket
+     */
+    int getBucketInterval();
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Compass.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Compass.java
new file mode 100644
index 0000000..eff395d
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Compass.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metrics;
+
+import java.util.Map;
+
+/**
+ * A metric that provides an easy way to collect method invocation,
+ * response time, success count, and error code count.
+ */
+public interface Compass extends Metric {
+
+    /**
+     * record a method invocation with execution time and sub-categories
+     * @param duration must be milliseconds
+     * @param subCategory all the sub-categories should be orthogonal,
+     *                    which will be added up to the total number of method invocations
+     */
+    void record(long duration, String subCategory);
+    
+    /**
+     * return method count per bucket per category
+     * @return
+     */
+    Map<String, Map<Long, Long>> getMethodCountPerCategory();
+
+    /**
+     * return method count per bucket per category
+     * @return
+     */
+    Map<String, Map<Long, Long>> getMethodCountPerCategory(long startTime);
+
+    /**
+     * return method execution time per bucket per category
+     * @return
+     */
+    Map<String, Map<Long, Long>> getMethodRtPerCategory();
+
+    /**
+     * return method execution time per bucket per category
+     * @return
+     */
+    Map<String, Map<Long, Long>> getMethodRtPerCategory(long startTime);
+
+    /**
+     * return method execution time and count per bucket per category
+     * @return
+     */
+    Map<String, Map<Long, Long>> getCountAndRtPerCategory();
+    
+    /**
+     * return method execution time and count per bucket per category
+     * @return
+     */
+    Map<String, Map<Long, Long>> getCountAndRtPerCategory(long startTime);
+    
+    /**
+     * @return the bucket interval
+     */
+    int getBucketInterval();
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Counter.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Counter.java
new file mode 100644
index 0000000..22be662
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Counter.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.metrics;
+
+/**
+ * <pre>
+ * An incrementing and decrementing counter metric.
+ * </pre>
+ */
+public interface Counter extends Metric, Counting {
+
+    /**
+     * Increment the counter by one.
+     */
+    void inc();
+
+    /**
+     * Increment the counter by {@code n}.
+     *
+     * @param n the amount by which the counter will be increased
+     */
+    void inc(long n);
+
+    /**
+     * Decrement the counter by one.
+     */
+    void dec();
+
+    /**
+     * Decrement the counter by {@code n}.
+     *
+     * @param n the amount by which the counter will be decreased
+     */
+    void dec(long n);
+
+}
\ No newline at end of file
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Counting.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Counting.java
new file mode 100644
index 0000000..6795902
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Counting.java
@@ -0,0 +1,29 @@
+/*
+ * 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.metrics;
+
+/**
+ * An interface for metric types which have counts.
+ */
+public interface Counting {
+    /**
+     * Returns the current count.
+     *
+     * @return the current count
+     */
+    long getCount();
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Gauge.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Gauge.java
new file mode 100644
index 0000000..a094225
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Gauge.java
@@ -0,0 +1,42 @@
+/*
+ * 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.metrics;
+
+
+/**
+ * <pre>
+ * A gauge metric is an instantaneous reading of a particular value. To instrument a queue's depth,
+ * for example:
+ *
+ * final Queue&lt;String&gt; queue = new ConcurrentLinkedQueue&lt;String&gt;();
+ * final Gauge&lt;Integer&gt; queueDepth = new Gauge&lt;Integer&gt;() {
+ *     public Integer getValue() {
+ *         return queue.size();
+ *     }
+ * };
+ * </pre>
+ *
+ * @param <T> the type of the metric's value
+ */
+public interface Gauge<T> extends Metric {
+    /**
+     * Returns the metric's current value.
+     *
+     * @return the metric's current value
+     */
+    T getValue();
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/IMetricManager.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/IMetricManager.java
new file mode 100644
index 0000000..eef6720
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/IMetricManager.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metrics;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface IMetricManager {
+
+    /**
+     * Create a {@link Counter} metric in given group, and name.
+     * if not exist, an instance will be created.
+     *
+     * @param group the group of MetricRegistry
+     * @param name the name of the metric
+     * @return an instance of counter
+     */
+    Counter getCounter(String group, MetricName name);
+
+    /**
+     * Create a {@link BucketCounter} metric in given group, and name.
+     * if not exist, an instance will be created.
+     *
+     * @param group the group of MetricRegistry
+     * @param name the name of the metric
+     * @return an instance of {@link BucketCounter}
+     */
+    BucketCounter getBucketCounter(String group, MetricName name);
+
+    /**
+     * Create a {@link Compass} metric in give group, name, and type
+     * if not exist, an instance will be created.
+     * @param group the group of MetricRegistry
+     * @param name the name of the metric
+     * @return an instance of {@link Compass}
+     */
+    Compass getCompass(String group, MetricName name);
+
+    /**
+     * Register a customized metric to specified group.
+     * @param group: the group name of MetricRegistry
+     * @param metric the metric to register
+     */
+    void register(String group, MetricName name, Metric metric);
+
+    /**
+     * Get a list of group in current MetricManager
+     * @return a list of group name
+     */
+    List<String> listMetricGroups();
+
+    /**
+     * list all metric names by group
+     * @return a map of metric name set, keyed by group name
+     */
+    Map<String, Set<MetricName>> listMetricNamesByGroup();
+
+    /**
+     * Get metric registry by group name,
+     * if not found, null will be returned
+     * @param group the group name to query
+     * @return the MetricRegistry that is correspondent to the group
+     */
+    MetricRegistry getMetricRegistryByGroup(String group);
+
+    /**
+     * Get all the counters by the specific group and filter
+     * @param group the given group
+     * @param filter the given filter
+     * @return the MetricName to Counter map
+     */
+    Map<MetricName, Counter> getCounters(String group, MetricFilter filter);
+
+    /**
+     * Get all the compasses by the specific group and filter
+     * @param group the given group
+     * @param filter the given filter
+     * @return the MetricName to Compass map
+     */
+    Map<MetricName, Compass> getCompasses(String group, MetricFilter filter);
+
+    /**
+     * A map of metric names to metrics.
+     *
+     * @return all the metrics
+     */
+    Map<MetricName, Metric> getMetrics(String group);
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Metric.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Metric.java
new file mode 100644
index 0000000..70823f0
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/Metric.java
@@ -0,0 +1,29 @@
+/*
+ * 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.metrics;
+
+/**
+ * A tag interface to indicate that a class is a metric.
+ */
+public interface Metric {
+
+    /**
+     * Return the last update time in milliseconds
+     * @return the last updated time in milliseconds
+     */
+    long lastUpdateTime();
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricFilter.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricFilter.java
new file mode 100644
index 0000000..243c3b7
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricFilter.java
@@ -0,0 +1,42 @@
+/*
+ * 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.metrics;
+
+/**
+ * A filter used to determine whether or not a metric should be reported, among other things.
+ */
+public interface MetricFilter {
+
+    /**
+     * Matches all metrics, regardless of type or name.
+     */
+    MetricFilter ALL = new MetricFilter() {
+        @Override
+        public boolean matches(MetricName name, Metric metric) {
+            return true;
+        }
+    };
+
+    /**
+     * Returns {@code true} if the metric matches the filter; {@code false} otherwise.
+     *
+     * @param name      the metric's name
+     * @param metric    the metric
+     * @return {@code true} if the metric matches the filter
+     */
+    boolean matches(MetricName name, Metric metric);
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricLevel.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricLevel.java
new file mode 100644
index 0000000..6634307
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricLevel.java
@@ -0,0 +1,53 @@
+/*
+ * 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.metrics;
+
+/**
+ * An enumeration class to represent the metric level
+ */
+public enum MetricLevel {
+
+    TRIVIAL, // trivial metrics
+
+    MINOR,   // minor metrics
+
+    NORMAL,  // normal metrics
+
+    MAJOR,   // major metrics
+
+    CRITICAL; // critical metrics
+
+    static {
+        for (MetricLevel level : MetricLevel.values()) {
+            if (level.ordinal() < 0) {
+                throw new RuntimeException("MetricLevel can not < 0");
+            }
+        }
+    }
+
+    public static int getMaxValue() {
+        MetricLevel[] levels = MetricLevel.values();
+        int max = levels[0].ordinal();
+        for (MetricLevel level : levels) {
+            int value = level.ordinal();
+            if (value > max) {
+                max = value;
+            }
+        }
+        return max;
+    }
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricManager.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricManager.java
new file mode 100644
index 0000000..1c032ac
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricManager.java
@@ -0,0 +1,108 @@
+/*
+ * 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.metrics;
+
+import java.lang.reflect.Method;
+
+/**
+ * The design concept is heavily borrowed from SLF4j (http://www.slf4j.org/), the logging framework.
+ * The application only depends on the metrics api.
+ * The implementation will be dynamically bound.
+ * If the implementation if not found in classpath, by default the {@link NOPMetricManager} will be bound.
+ */
+public class MetricManager {
+
+    private static final String BINDER_CLASS = "org.apache.dubbo.metrics.MetricManagerBinder";
+
+    private static final IMetricManager NOP_METRIC_MANAGER = new NOPMetricManager();
+
+    private static volatile IMetricManager iMetricManager;
+
+    /**
+     * Create a {@link Counter} metric in given group, and name.
+     * if not exist, an instance will be created.
+     *
+     * @param group the group of MetricRegistry
+     * @param name the name of the metric
+     * @return an instance of counter
+     */
+    public static Counter getCounter(String group, MetricName name) {
+        IMetricManager manager = getIMetricManager();
+        return manager.getCounter(group, name);
+    }
+
+    /**
+     * Create a {@link BucketCounter} metric in given group, and name.
+     * if not exist, an instance will be created.
+     *
+     * @param group the group of MetricRegistry
+     * @param name the name of the metric
+     * @return an instance of {@link BucketCounter}
+     */
+    public static BucketCounter getBucketCounters(String group, MetricName name) {
+        IMetricManager manager = getIMetricManager();
+        return manager.getBucketCounter(group, name);
+    }
+
+    /**
+     * Create a {@link Compass} metric in given group, and name
+     * if not exist, an instance will be created.
+     *
+     * @param group the group of MetricRegistry
+     * @param name the name of the metric
+     * @return an instance of {@link Compass}
+     */
+    public static Compass getCompass(String group, MetricName name) {
+        IMetricManager manager = getIMetricManager();
+        return manager.getCompass(group, name);
+    }
+
+    /**
+     * Register a customized metric to specified group.
+     * @param group the group name of MetricRegistry
+     * @param metric the metric to register
+     */
+    public static void register(String group, MetricName name, Metric metric) {
+        IMetricManager manager = getIMetricManager();
+        manager.register(group, name, metric);
+    }
+
+    /**
+     * get dynamically bound {@link IMetricManager} instance
+     * @return the {@link IMetricManager} instance bound
+     */
+    @SuppressWarnings("unchecked")
+    public static IMetricManager getIMetricManager() {
+        if (iMetricManager == null) {
+            synchronized (MetricManager.class) {
+                if (iMetricManager == null) {
+                    try {
+                        Class binderClazz = MetricManager.class.getClassLoader().loadClass(BINDER_CLASS);
+                        Method getSingleton = binderClazz.getMethod("getSingleton");
+                        Object binderObject = getSingleton.invoke(null);
+                        Method getMetricManager = binderClazz.getMethod("getMetricManager");
+                        iMetricManager = (IMetricManager) getMetricManager.invoke(binderObject);
+                    } catch (Exception e) {
+                        iMetricManager = NOP_METRIC_MANAGER;
+                    }
+                }
+            }
+        }
+        return iMetricManager;
+    }
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricName.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricName.java
new file mode 100644
index 0000000..93ae922
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricName.java
@@ -0,0 +1,367 @@
+/*
+ * 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.metrics;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * This class is based on Dropwizard metrics, see io/dropwizard/metrics/MetricName.java
+ *
+ * The following changes are made:
+ *   * Add metric level
+ *   * Cache the hash code
+ *
+ */
+public class MetricName implements Comparable<MetricName> {
+
+    public static final String SEPARATOR = ".";
+    public static final Map<String, String> EMPTY_TAGS = Collections.emptyMap();
+    public static final MetricName EMPTY = new MetricName();
+
+    private final String key;
+    private final Map<String, String> tags;
+    // the level to indicate the importance of a metric
+    private MetricLevel level;
+
+    private int hashCode = 0;
+    
+    private boolean hashCodeCached = false;
+    
+    public MetricName() {
+        this(null, null, null);
+    }
+
+    public MetricName(String key) {
+        this(key, null, null);
+    }
+
+    public MetricName(String key, Map<String, String> tags) {
+        this(key, tags, null);
+    }
+
+    public MetricName(String key, MetricLevel level) {
+        this(key, null, level);
+    }
+
+    public MetricName(String key, Map<String, String> tags, MetricLevel level) {
+        this.key = key;
+        this.tags = checkTags(tags);
+        this.level = level == null ? MetricLevel.NORMAL : level;
+    }
+
+    private Map<String, String> checkTags(Map<String, String> tags) {
+        if (tags == null || tags.isEmpty()) {
+            return EMPTY_TAGS;
+        }
+
+        return Collections.unmodifiableMap(tags);
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public Map<String, String> getTags() {
+        return tags;
+    }
+
+    /**
+     * Return the level of this metric
+     * The level indicates the importance of the metric
+     *
+     * @return when level tag do not exist or illegal tag, will return null.
+     */
+    public MetricLevel getMetricLevel() {
+        return level;
+    }
+
+
+    /**
+     * Metric level can be changed during runtime
+     * @param level the level to set
+     */
+    public MetricName level(MetricLevel level) {
+        this.level = level;
+        return this;
+    }
+
+
+    /**
+     * @see {@link #resolve(String, boolean)}
+     */
+    public MetricName resolve(String p) {
+        return resolve(p, true);
+    }
+
+    /**
+     * Build the MetricName that is this with another path appended to it.
+     *
+     * The new MetricName inherits the tags of this one.
+     *
+     * @param p The extra path element to add to the new metric.
+     * @param inheritTags if true, tags will be inherited
+     * @return A new metric name relative to the original by the path specified
+     *         in p.
+     */
+    public MetricName resolve(String p, boolean inheritTags) {
+        final String next;
+
+        if (p != null && !p.isEmpty()) {
+            if (key != null && !key.isEmpty()) {
+                next = key + SEPARATOR + p;
+            } else {
+                next = p;
+            }
+        } else {
+            next = this.key;
+        }
+
+        return inheritTags ? new MetricName(next, tags, level) : new MetricName(next, level);
+    }
+
+    /**
+     * Add tags to a metric name and return the newly created MetricName.
+     *
+     * @param add Tags to add.
+     * @return A newly created metric name with the specified tags associated with it.
+     */
+    public MetricName tag(Map<String, String> add) {
+        final Map<String, String> tags = new HashMap<String, String>(add);
+        tags.putAll(this.tags);
+        return new MetricName(key, tags, level);
+    }
+
+    /**
+     * Same as {@link #tag(Map)}, but takes a variadic list
+     * of arguments.
+     *
+     * @see #tag(Map)
+     * @param pairs An even list of strings acting as key-value pairs.
+     * @return A newly created metric name with the specified tags associated
+     *         with it.
+     */
+    public MetricName tag(String... pairs) {
+        if (pairs == null) {
+            return this;
+        }
+
+        if (pairs.length % 2 != 0) {
+            throw new IllegalArgumentException("Argument count must be even");
+        }
+
+        final Map<String, String> add = new HashMap<String, String>();
+
+        for (int i = 0; i < pairs.length; i += 2) {
+            add.put(pairs[i], pairs[i+1]);
+        }
+
+        return tag(add);
+    }
+
+    /**
+     * Join the specified set of metric names.
+     *
+     * @param parts Multiple metric names to join using the separator.
+     * @return A newly created metric name which has the name of the specified
+     *         parts and includes all tags of all child metric names.
+     **/
+    public static MetricName join(MetricName... parts) {
+        final StringBuilder nameBuilder = new StringBuilder();
+        final Map<String, String> tags = new HashMap<String, String>();
+
+        boolean first = true;
+        MetricName firstName = null;
+
+        for (MetricName part : parts) {
+            final String name = part.getKey();
+
+            if (name != null && !name.isEmpty()) {
+                if (first) {
+                    first = false;
+                    firstName = part;
+                } else {
+                    nameBuilder.append(SEPARATOR);
+                }
+
+                nameBuilder.append(name);
+            }
+
+            if (!part.getTags().isEmpty())
+                tags.putAll(part.getTags());
+        }
+
+        MetricLevel level = firstName == null ? null : firstName.getMetricLevel();
+        return new MetricName(nameBuilder.toString(), tags, level);
+    }
+
+    /**
+     * Build a new metric name using the specific path components.
+     *
+     * @param parts Path of the new metric name.
+     * @return A newly created metric name with the specified path.
+     **/
+    public static MetricName build(String... parts) {
+        if (parts == null || parts.length == 0)
+            return MetricName.EMPTY;
+
+        if (parts.length == 1)
+            return new MetricName(parts[0], EMPTY_TAGS);
+
+        return new MetricName(buildName(parts), EMPTY_TAGS);
+    }
+
+    private static String buildName(String... names) {
+        final StringBuilder builder = new StringBuilder();
+        boolean first = true;
+
+        for (String name : names) {
+            if (name == null || name.isEmpty())
+                continue;
+
+            if (first) {
+                first = false;
+            } else {
+                builder.append(SEPARATOR);
+            }
+
+            builder.append(name);
+        }
+
+        return builder.toString();
+    }
+
+    @Override
+    public String toString() {
+        if (tags.isEmpty()) {
+            return key;
+        }
+
+        return key + tags;
+    }
+
+    @Override
+    public int hashCode() {
+        
+        if (!hashCodeCached){
+            
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((key == null) ? 0 : key.hashCode());
+            result = prime * result + ((tags == null) ? 0 : tags.hashCode());
+            
+            hashCode = result;
+            hashCodeCached = true;
+        }
+
+        return hashCode;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null)
+            return false;
+
+        if (getClass() != obj.getClass())
+            return false;
+
+        MetricName other = (MetricName) obj;
+
+        if (key == null) {
+            if (other.key != null)
+                return false;
+        } else if (!key.equals(other.key))
+            return false;
+
+        if (!tags.equals(other.tags))
+            return false;
+
+        return true;
+    }
+
+    @Override
+    public int compareTo(MetricName o) {
+        if (o == null)
+            return -1;
+
+        int c = compareName(key, o.getKey());
+
+        if (c != 0)
+            return c;
+
+        return compareTags(tags, o.getTags());
+    }
+
+    private int compareName(String left, String right) {
+        if (left == null && right == null)
+            return 0;
+
+        if (left == null)
+            return 1;
+
+        if (right == null)
+            return -1;
+
+        return left.compareTo(right);
+    }
+
+    private int compareTags(Map<String, String> left, Map<String, String> right) {
+        if (left == null && right == null)
+            return 0;
+
+        if (left == null)
+            return 1;
+
+        if (right == null)
+            return -1;
+
+        final Iterable<String> keys = uniqueSortedKeys(left, right);
+
+        for (final String key : keys) {
+            final String a = left.get(key);
+            final String b = right.get(key);
+
+            if (a == null && b == null)
+                continue;
+
+            if (a == null)
+                return -1;
+
+            if (b == null)
+                return 1;
+
+            int c = a.compareTo(b);
+
+            if (c != 0)
+                return c;
+        }
+
+        return 0;
+    }
+
+    private Iterable<String> uniqueSortedKeys(Map<String, String> left, Map<String, String> right) {
+        final Set<String> set = new TreeSet<String>(left.keySet());
+        set.addAll(right.keySet());
+        return set;
+    }
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricRegistry.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricRegistry.java
new file mode 100644
index 0000000..abb467a
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricRegistry.java
@@ -0,0 +1,158 @@
+/*
+ * 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.metrics;
+
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A registry of metric instances.
+ */
+public abstract class MetricRegistry implements MetricSet {
+
+    /**
+     * Given a {@link Metric}, registers it under the given name.
+     *
+     * @param name   the name of the metric
+     * @param metric the metric
+     * @param <T>    the type of the metric
+     * @return {@code metric}
+     * @throws IllegalArgumentException if the name is already registered
+     */
+    public abstract <T extends Metric> T register(String name, T metric) throws IllegalArgumentException;
+
+    /**
+     * Given a {@link Metric}, registers it under the given name.
+     *
+     * @param name   the name of the metric
+     * @param metric the metric
+     * @param <T>    the type of the metric
+     * @return {@code metric}
+     * @throws IllegalArgumentException if the name is already registered
+     */
+    public abstract <T extends Metric> T register(MetricName name, T metric) throws IllegalArgumentException;
+
+    /**
+     * Given a metric set, registers them.
+     *
+     * @param metrics    a set of metrics
+     * @throws IllegalArgumentException if any of the names are already registered
+     */
+    public abstract void registerAll(MetricSet metrics) throws IllegalArgumentException;
+
+    /**
+     * Creates a new {@link Counter} and registers it under the given name.
+     *
+     * @param name the name of the metric
+     * @return a new {@link Counter}
+     */
+    public abstract Counter counter(String name);
+
+    /**
+     * Return the {@link Counter} registered under this name; or create and register
+     * a new {@link Counter} if none is registered.
+     *
+     * @param name the name of the metric
+     * @return a new or pre-existing {@link Counter}
+     */
+    public abstract Counter counter(MetricName name);
+
+    /**
+     * Create a FastCompass with given name
+     * @param name the name of the metric
+     * @return a FastCompass instance
+     */
+    public abstract Compass compass(MetricName name);
+
+    /**
+     * Removes the metric with the given name.
+     *
+     * @param name the name of the metric
+     * @return whether or not the metric was removed
+     */
+    public abstract boolean remove(MetricName name);
+
+    /**
+     * Removes all metrics which match the given filter.
+     *
+     * @param filter a filter
+     */
+    public abstract void removeMatching(MetricFilter filter);
+
+    /**
+     * Returns a set of the names of all the metrics in the registry.
+     *
+     * @return the names of all the metrics
+     */
+    public abstract Set<MetricName> getNames();
+
+    /**
+     * Returns a map of all the gauges in the registry and their names.
+     *
+     * @return all the gauges in the registry
+     */
+    public abstract Map<MetricName, Gauge> getGauges();
+
+    /**
+     * Returns a map of all the gauges in the registry and their names which match the given filter.
+     *
+     * @param filter    the metric filter to match
+     * @return all the gauges in the registry
+     */
+    public abstract Map<MetricName, Gauge> getGauges(MetricFilter filter);
+
+    /**
+     * Returns a map of all the counters in the registry and their names.
+     *
+     * @return all the counters in the registry
+     */
+    public abstract Map<MetricName, Counter> getCounters();
+
+    /**
+     * Returns a map of all the counters in the registry and their names which match the given
+     * filter.
+     *
+     * @param filter    the metric filter to match
+     * @return all the counters in the registry
+     */
+    public abstract Map<MetricName, Counter> getCounters(MetricFilter filter);
+
+    /**
+     * Returns a map of all the compasses in the registry and their names.
+     *
+     * @return all the compasses in the registry
+     */
+    public abstract Map<MetricName, Compass> getCompasses();
+
+    /**
+     * Returns a map of all the compasses in the registry and their names which match the given filter.
+     *
+     * @param filter    the metric filter to match
+     * @return all the compasses in the registry
+     */
+    public abstract Map<MetricName, Compass> getCompasses(MetricFilter filter);
+
+    /**
+     * Returns a map of all the metrics in the registry and their names which match the given filter
+     * @param filter the metric filter to match
+     * @return all the metrics in the registry
+     */
+    public abstract Map<MetricName, Metric> getMetrics(MetricFilter filter);
+
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricSet.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricSet.java
new file mode 100644
index 0000000..68c95a1
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/MetricSet.java
@@ -0,0 +1,33 @@
+/*
+ * 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.metrics;
+
+import java.util.Map;
+
+/**
+ * A set of named metrics.
+ *
+ * @see MetricRegistry#registerAll(MetricSet)
+ */
+public interface MetricSet extends Metric {
+    /**
+     * A map of metric names to metrics.
+     *
+     * @return the metrics
+     */
+    Map<MetricName, Metric> getMetrics();
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/NOPMetricManager.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/NOPMetricManager.java
new file mode 100644
index 0000000..2228fd7
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/metrics/NOPMetricManager.java
@@ -0,0 +1,292 @@
+/*
+ * 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.metrics;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The empty implementation for IMetricManager
+ */
+public class NOPMetricManager implements IMetricManager {
+
+    private static final Map emptyMap = new HashMap();
+    private static final Set emptySet = new HashSet();
+
+    @Override
+    public Counter getCounter(String group, MetricName name) {
+        return NOP_COUNTER;
+    }
+
+    @Override
+    public BucketCounter getBucketCounter(String group, MetricName name) {
+        return NOP_BUCKET_COUNTER;
+    }
+
+    @Override
+    public Compass getCompass(String group, MetricName name) {
+        return NOP_COMPASS;
+    }
+
+    @Override
+    public List<String> listMetricGroups() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public Map<String, Set<MetricName>> listMetricNamesByGroup() {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public MetricRegistry getMetricRegistryByGroup(String group) {
+        return NOP_REGISTRY;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Map<MetricName, Counter> getCounters(String group, MetricFilter filter) {
+        return emptyMap;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Map<MetricName, Compass> getCompasses(String group, MetricFilter filter) {
+        return emptyMap;
+    }
+
+    @Override
+    public void register(String group, MetricName name, Metric metric) {
+
+    }
+
+    static final BucketCounter NOP_BUCKET_COUNTER = new BucketCounter() {
+        @Override
+        public void update() {
+
+        }
+
+        @Override
+        public void update(long n) {
+
+        }
+
+        @Override
+        public Map<Long, Long> getBucketCounts() {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<Long, Long> getBucketCounts(long startTime) {
+            return emptyMap;
+        }
+
+        @Override
+        public int getBucketInterval() {
+            return 0;
+        }
+
+        @Override
+        public long lastUpdateTime() {
+            return 0;
+        }
+    };
+
+    static final Counter NOP_COUNTER = new Counter() {
+        @Override
+        public void inc() {
+        }
+
+        @Override
+        public void inc(long n) {
+        }
+
+        @Override
+        public void dec() {
+        }
+
+        @Override
+        public void dec(long n) {
+        }
+
+        @Override
+        public long getCount() {
+            return 0;
+        }
+
+        @Override
+        public long lastUpdateTime() {
+            return 0;
+        }
+    };
+
+    static final Compass NOP_COMPASS = new Compass() {
+        @Override
+        public void record(long duration, String subCategory) {
+
+        }
+
+        @Override
+        public Map<String, Map<Long, Long>> getMethodCountPerCategory() {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<String, Map<Long, Long>> getMethodRtPerCategory() {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<String, Map<Long, Long>> getMethodCountPerCategory(long startTime) {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<String, Map<Long, Long>> getMethodRtPerCategory(long startTime) {
+            return emptyMap;
+        }
+
+        @Override
+        public int getBucketInterval() {
+            return 0;
+        }
+
+        @Override
+        public Map<String, Map<Long, Long>> getCountAndRtPerCategory() {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<String, Map<Long, Long>> getCountAndRtPerCategory(long startTime) {
+            return emptyMap;
+        }
+
+        @Override
+        public long lastUpdateTime() {
+            return 0;
+        }
+    };
+
+    private static final MetricRegistry NOP_REGISTRY = new MetricRegistry() {
+        @Override
+        public <T extends Metric> T register(String name, T metric) throws IllegalArgumentException {
+            return metric;
+        }
+
+        @Override
+        public <T extends Metric> T register(MetricName name, T metric) throws IllegalArgumentException {
+            return metric;
+        }
+
+        @Override
+        public void registerAll(MetricSet metrics) throws IllegalArgumentException {
+
+        }
+
+        @Override
+        public Counter counter(String name) {
+            return NOP_COUNTER;
+        }
+
+        @Override
+        public Counter counter(MetricName name) {
+            return NOP_COUNTER;
+        }
+
+        @Override
+        public Compass compass(MetricName name) {
+            return NOP_COMPASS;
+        }
+
+        @Override
+        public boolean remove(MetricName name) {
+            return false;
+        }
+
+        @Override
+        public void removeMatching(MetricFilter filter) {
+
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Set<MetricName> getNames() {
+            return emptySet;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Map<MetricName, Gauge> getGauges() {
+            return emptyMap;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Map<MetricName, Gauge> getGauges(MetricFilter filter) {
+            return emptyMap;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Map<MetricName, Counter> getCounters() {
+            return emptyMap;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Map<MetricName, Counter> getCounters(MetricFilter filter) {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<MetricName, Compass> getCompasses() {
+            return emptyMap;
+        }
+
+        @Override
+        public Map<MetricName, Compass> getCompasses(MetricFilter filter) {
+            return emptyMap;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Map<MetricName, Metric> getMetrics(MetricFilter filter) {
+            return emptyMap;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Map<MetricName, Metric> getMetrics() {
+            return emptyMap;
+        }
+
+        @Override
+        public long lastUpdateTime() {
+            return 0;
+        }
+    };
+
+    @Override
+    public Map<MetricName, Metric> getMetrics(String group) {
+        return emptyMap;
+    }
+
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/MetricManagerTest.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/MetricManagerTest.java
new file mode 100644
index 0000000..fcadbf5
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/MetricManagerTest.java
@@ -0,0 +1,40 @@
+package org.apache.dubbo.metrics;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author wangtao 2016-07-09 08:43.
+ */
+public class MetricManagerTest {
+
+    @Test
+    public void testNOPMetricManager() {
+        Assert.assertTrue(MetricManager.getIMetricManager() instanceof NOPMetricManager);
+    }
+
+    @Test
+    public void testNOPCompass() {
+        Compass compass = MetricManager.getCompass("test", MetricName.build("test"));
+        compass.record(10, "success");
+
+        Assert.assertEquals(0, compass.getCountAndRtPerCategory().size());
+        Assert.assertEquals(0, compass.getMethodCountPerCategory().size());
+        Assert.assertEquals(0, compass.getMethodRtPerCategory().size());
+    }
+
+    @Test
+    public void testNopCounter() {
+        Counter counter = MetricManager.getCounter("test", MetricName.build("test2"));
+        counter.inc();
+        Assert.assertEquals(0, counter.getCount());
+    }
+
+    @Test
+    public void testBucketCounter() {
+        BucketCounter bc = MetricManager.getBucketCounters("test", MetricName.build("test3"));
+        bc.update();
+        Assert.assertEquals(0, bc.getBucketInterval());
+        Assert.assertEquals(0, bc.getBucketCounts().size());
+    }
+}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/MetricNameTest.java b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/MetricNameTest.java
new file mode 100644
index 0000000..74399d8
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/test/java/org/apache/dubbo/metrics/MetricNameTest.java
@@ -0,0 +1,125 @@
+package org.apache.dubbo.metrics;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * @author wangtao 2016-07-08 17:56.
+ */
+public class MetricNameTest {
+
+    @Test
+    public void testEmpty() {
+        Assert.assertEquals(MetricName.EMPTY.getTags(), MetricName.EMPTY_TAGS);
+        Assert.assertNull(MetricName.EMPTY.getKey());
+        Assert.assertEquals(new MetricName().getTags(), MetricName.EMPTY_TAGS);
+
+        Assert.assertEquals(MetricName.EMPTY, new MetricName());
+        Assert.assertEquals(MetricName.build(), MetricName.EMPTY);
+        Assert.assertEquals(MetricName.EMPTY.resolve(null), MetricName.EMPTY);
+    }
+
+    @Test
+    public void testEmptyResolve() {
+        final MetricName name = new MetricName();
+        Assert.assertEquals(name.resolve("foo"), new MetricName("foo"));
+    }
+
+    @Test
+    public void testResolveToEmpty() {
+        final MetricName name = new MetricName("foo");
+        Assert.assertEquals(name.resolve(null), new MetricName("foo"));
+    }
+
+    @Test
+    public void testResolve() {
+        final MetricName name = new MetricName("foo");
+        Assert.assertEquals(name.resolve("bar"), new MetricName("foo.bar"));
+    }
+
+    @Test
+    public void testResolveWithTags() {
+        final MetricName name = new MetricName("foo").tag("key", "value");
+        Assert.assertEquals(name.resolve("bar"), new MetricName("foo.bar").tag("key", "value"));
+    }
+
+    @Test
+    public void testResolveWithoutTags() {
+        final MetricName name = new MetricName("foo").tag("key", "value");
+        Assert.assertEquals(name.resolve("bar", false), new MetricName("foo.bar"));
+    }
+
+    @Test
+    public void testResolveBothEmpty() {
+        final MetricName name = new MetricName(null);
+        Assert.assertEquals(name.resolve(null), new MetricName());
+    }
+
+    @Test
+    public void testAddTagsVarious() {
+        final Map<String, String> refTags = new HashMap<String, String>();
+        refTags.put("foo", "bar");
+        final MetricName test = MetricName.EMPTY.tag("foo", "bar");
+        final MetricName test2 = MetricName.EMPTY.tag(refTags);
+
+        Assert.assertEquals(test, new MetricName(null, refTags));
+        Assert.assertEquals(test.getTags(), refTags);
+
+        Assert.assertEquals(test2, new MetricName(null, refTags));
+        Assert.assertEquals(test2.getTags(), refTags);
+    }
+
+    @Test
+    public void testTaggedMoreArguments() {
+        final Map<String, String> refTags = new HashMap<String, String>();
+        refTags.put("foo", "bar");
+        refTags.put("baz", "biz");
+        Assert.assertEquals(MetricName.EMPTY.tag("foo", "bar", "baz", "biz").getTags(), refTags);
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testTaggedNotPairs() {
+        MetricName.EMPTY.tag("foo");
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testTaggedNotPairs2() {
+        MetricName.EMPTY.tag("foo", "bar", "baz");
+    }
+
+    @Test
+    public void testCompareTo() {
+        final MetricName a = MetricName.EMPTY.tag("foo", "bar");
+        final MetricName b = MetricName.EMPTY.tag("foo", "baz");
+
+        Assert.assertTrue(a.compareTo(b) < 0);
+        Assert.assertTrue(b.compareTo(a) > 0);
+        Assert.assertTrue(b.compareTo(b) == 0);
+        Assert.assertTrue(b.resolve("key").compareTo(b) < 0);
+        Assert.assertTrue(b.compareTo(b.resolve("key")) > 0);
+    }
+
+    @Test
+    public void testTaggedWithLevel() {
+        MetricName name = MetricName.build("test").level(MetricLevel.CRITICAL);
+        MetricName tagged = name.tag("foo", "bar");
+        Assert.assertEquals(tagged.getMetricLevel(), MetricLevel.CRITICAL);
+    }
+
+    @Test
+    public void testJoinWithLevel() {
+        MetricName name = MetricName.build("test").level(MetricLevel.CRITICAL);
+        MetricName tagged = MetricName.join(name, MetricName.build("abc"));
+        Assert.assertEquals(tagged.getMetricLevel(), MetricLevel.CRITICAL);
+    }
+
+    @Test
+    public void testResolveWithLevel() {
+        final MetricName name = new MetricName("foo").level(MetricLevel.CRITICAL).tag("key", "value");
+        Assert.assertEquals(name.resolve("bar"), new MetricName("foo.bar").tag("key", "value").level(MetricLevel.CRITICAL));
+    }
+}
diff --git a/dubbo-metrics/pom.xml b/dubbo-metrics/pom.xml
new file mode 100644
index 0000000..d76e4e7
--- /dev/null
+++ b/dubbo-metrics/pom.xml
@@ -0,0 +1,41 @@
+<!--
+  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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-parent</artifactId>
+        <version>2.7.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-metrics</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>The metrics module of dubbo project</description>
+
+    <properties>
+        <skip_maven_deploy>false</skip_maven_deploy>
+    </properties>
+
+    <modules>
+        <module>dubbo-metrics-api</module>
+    </modules>
+
+
+</project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2413fe2..152788e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -144,6 +144,7 @@
         <module>bom</module>
         <module>all</module>
         <module>distribution</module>
+        <module>dubbo-metrics</module>
     </modules>
 
     <dependencyManagement>