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<String> queue = new ConcurrentLinkedQueue<String>();
+ * final Gauge<Integer> queueDepth = new Gauge<Integer>() {
+ * 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>