add metrics integration #3598 (#3643)

* add metrics integration

* add license
This commit is contained in:
min 2019-03-14 15:32:49 +08:00 committed by Ian Luo
parent ea3fbc822a
commit e4bfb3d0e7
25 changed files with 335 additions and 1695 deletions

View File

@ -840,4 +840,17 @@ public class Constants {
public static final int DEFAULT_GRPC_QUEUES = 300_0000;
/**
* metrics
*/
public static final String DUBBO_PROVIDER = "dubbo.provider";
public static final String DUBBO_CONSUMER = "dubbo.consumer";
public static final String DUBBO_PROVIDER_METHOD = "dubbo.provider.method";
public static final String DUBBO_CONSUMER_METHOD = "dubbo.consumer.method";
public static final String SERVICE = "service";
public static final String METHOD = "method";
public static final String DUBBO_GROUP = "dubbo";
public static final String METRICS_KEY = "metrics";
}

View File

@ -143,6 +143,7 @@
<swagger_version>1.5.19</swagger_version>
<spring_test_version>4.3.16.RELEASE</spring_test_version>
<metrics_version>2.0.1</metrics_version>
<gson_version>2.8.5</gson_version>
</properties>
@ -493,6 +494,28 @@
<version>${swagger_version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-core-api</artifactId>
<version>${metrics_version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-core-impl</artifactId>
<version>${metrics_version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-common</artifactId>
<version>${metrics_version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-rest</artifactId>
<version>${metrics_version}</version>
</dependency>
<!-- Test lib -->
<dependency>
<groupId>org.apache.curator</groupId>

View File

@ -1,28 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-metrics-api</artifactId>
</project>

View File

@ -1,57 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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();
}

View File

@ -1,75 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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();
}

View File

@ -1,50 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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);
}

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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();
}

View File

@ -1,104 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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);
}

View File

@ -1,29 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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();
}

View File

@ -1,42 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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);
}

View File

@ -1,45 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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
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;
}
}

View File

@ -1,108 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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;
}
}

View File

@ -1,389 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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;
}
}

View File

@ -1,157 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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);
}

View File

@ -1,33 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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();
}

View File

@ -1,292 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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;
}
}

View File

@ -1,53 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class MetricManagerTest {
@Test
public void testNOPMetricManager() {
Assertions.assertTrue(MetricManager.getIMetricManager() instanceof NOPMetricManager);
}
@Test
public void testNOPCompass() {
Compass compass = MetricManager.getCompass("test", MetricName.build("test"));
compass.record(10, "success");
Assertions.assertEquals(0, compass.getCountAndRtPerCategory().size());
Assertions.assertEquals(0, compass.getMethodCountPerCategory().size());
Assertions.assertEquals(0, compass.getMethodRtPerCategory().size());
}
@Test
public void testNopCounter() {
Counter counter = MetricManager.getCounter("test", MetricName.build("test2"));
counter.inc();
Assertions.assertEquals(0, counter.getCount());
}
@Test
public void testBucketCounter() {
BucketCounter bc = MetricManager.getBucketCounters("test", MetricName.build("test3"));
bc.update();
Assertions.assertEquals(0, bc.getBucketInterval());
Assertions.assertEquals(0, bc.getBucketCounts().size());
}
}

View File

@ -1,138 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
public class MetricNameTest {
@Test
public void testEmpty() {
Assertions.assertEquals(MetricName.EMPTY.getTags(), MetricName.EMPTY_TAGS);
Assertions.assertNull(MetricName.EMPTY.getKey());
Assertions.assertEquals(new MetricName().getTags(), MetricName.EMPTY_TAGS);
Assertions.assertEquals(MetricName.EMPTY, new MetricName());
Assertions.assertEquals(MetricName.build(), MetricName.EMPTY);
Assertions.assertEquals(MetricName.EMPTY.resolve(null), MetricName.EMPTY);
}
@Test
public void testEmptyResolve() {
final MetricName name = new MetricName();
Assertions.assertEquals(name.resolve("foo"), new MetricName("foo"));
}
@Test
public void testResolveToEmpty() {
final MetricName name = new MetricName("foo");
Assertions.assertEquals(name.resolve(null), new MetricName("foo"));
}
@Test
public void testResolve() {
final MetricName name = new MetricName("foo");
Assertions.assertEquals(name.resolve("bar"), new MetricName("foo.bar"));
}
@Test
public void testResolveWithTags() {
final MetricName name = new MetricName("foo").tag("key", "value");
Assertions.assertEquals(name.resolve("bar"), new MetricName("foo.bar").tag("key", "value"));
}
@Test
public void testResolveWithoutTags() {
final MetricName name = new MetricName("foo").tag("key", "value");
Assertions.assertEquals(name.resolve("bar", false), new MetricName("foo.bar"));
}
@Test
public void testResolveBothEmpty() {
final MetricName name = new MetricName(null);
Assertions.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);
Assertions.assertEquals(test, new MetricName(null, refTags));
Assertions.assertEquals(test.getTags(), refTags);
Assertions.assertEquals(test2, new MetricName(null, refTags));
Assertions.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");
Assertions.assertEquals(MetricName.EMPTY.tag("foo", "bar", "baz", "biz").getTags(), refTags);
}
@Test
public void testTaggedNotPairs() {
Assertions.assertThrows(IllegalArgumentException.class, () -> MetricName.EMPTY.tag("foo"));
}
@Test
public void testTaggedNotPairs2() {
Assertions.assertThrows(IllegalArgumentException.class, () -> 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");
Assertions.assertTrue(a.compareTo(b) < 0);
Assertions.assertTrue(b.compareTo(a) > 0);
Assertions.assertTrue(b.compareTo(b) == 0);
Assertions.assertTrue(b.resolve("key").compareTo(b) < 0);
Assertions.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");
Assertions.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"));
Assertions.assertEquals(tagged.getMetricLevel(), MetricLevel.CRITICAL);
}
@Test
public void testResolveWithLevel() {
final MetricName name = new MetricName("foo").level(MetricLevel.CRITICAL).tag("key", "value");
Assertions.assertEquals(name.resolve("bar"), new MetricName("foo.bar").tag("key", "value").level(MetricLevel.CRITICAL));
}
}

View File

@ -1,39 +0,0 @@
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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.1-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>

View File

@ -34,5 +34,20 @@
<artifactId>dubbo-rpc-api</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-core-api</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-core-impl</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>metrics-common</artifactId>
</dependency>
</dependencies>
</project>
</project>

View File

@ -0,0 +1,102 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.monitor.support;
import com.alibaba.metrics.FastCompass;
import com.alibaba.metrics.MetricLevel;
import com.alibaba.metrics.MetricManager;
import com.alibaba.metrics.MetricName;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.util.HashMap;
public class MetricsFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MetricsFilter.class);
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext context = RpcContext.getContext();
boolean isProvider = context.isProviderSide();
long start = System.currentTimeMillis();
try {
Result result = invoker.invoke(invocation); // proceed invocation chain
long duration = System.currentTimeMillis() - start;
reportMetrics(invoker, invocation, duration, "success", isProvider);
return result;
} catch (RpcException e) {
long duration = System.currentTimeMillis() - start;
String result = "error";
if (e.isTimeout()) {
result = "timeoutError";
}
if (e.isBiz()) {
result = "bisError";
}
if (e.isNetwork()) {
result = "networkError";
}
if (e.isSerialization()) {
result = "serializationError";
}
reportMetrics(invoker, invocation, duration, result, isProvider);
throw e;
}
}
private void reportMetrics(Invoker<?> invoker, Invocation invocation, long duration, String result, boolean isProvider) {
String serviceName = invoker.getInterface().getName();
String methodName = RpcUtils.getMethodName(invocation);
MetricName global;
MetricName method;
if (isProvider) {
global = new MetricName(Constants.DUBBO_PROVIDER, MetricLevel.MAJOR);
method = new MetricName(Constants.DUBBO_PROVIDER_METHOD, new HashMap<String, String>(4) {
{
put(Constants.SERVICE, serviceName);
put(Constants.METHOD, methodName);
}
}, MetricLevel.NORMAL);
} else {
global = new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR);
method = new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
{
put(Constants.SERVICE, serviceName);
put(Constants.METHOD, methodName);
}
}, MetricLevel.NORMAL);
}
setCompassQuantity(Constants.DUBBO_GROUP, result, duration, global, method);
}
private void setCompassQuantity(String groupName, String result, long duration, MetricName... metricNames) {
for (MetricName metricName : metricNames) {
FastCompass compass = MetricManager.getFastCompass(groupName, metricName);
compass.record(duration, result);
}
}
}

View File

@ -1 +1,2 @@
monitor=org.apache.dubbo.monitor.support.MonitorFilter
monitor=org.apache.dubbo.monitor.support.MonitorFilter
metrics=org.apache.dubbo.monitor.support.MetricsFilter

View File

@ -14,16 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.metrics;
package org.apache.dubbo.monitor.service;
public interface DemoService {
String sayName(String name);
void timeoutException();
void throwDemoException() throws Exception;
int echo(int i);
/**
* An interface for metric types which have counts.
*/
public interface Counting {
/**
* Returns the current count.
*
* @return the current count
*/
long getCount();
}

View File

@ -0,0 +1,167 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.monitor.support;
import com.alibaba.metrics.FastCompass;
import com.alibaba.metrics.IMetricManager;
import com.alibaba.metrics.MetricLevel;
import com.alibaba.metrics.MetricManager;
import com.alibaba.metrics.MetricName;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.monitor.service.DemoService;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
public class MetricsFilterTest {
private final Invoker<DemoService> serviceInvoker = new Invoker<DemoService>() {
@Override
public Class<DemoService> getInterface() {
return DemoService.class;
}
public URL getUrl() {
return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880/org.apache.dubbo.monitor.service.DemoService");
}
@Override
public boolean isAvailable() {
return false;
}
public Result invoke(Invocation invocation) throws RpcException {
return null;
}
@Override
public void destroy() {
}
};
private final Invoker<DemoService> timeoutInvoker = new Invoker<DemoService>() {
@Override
public Class<DemoService> getInterface() {
return DemoService.class;
}
public URL getUrl() {
return URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880/org.apache.dubbo.monitor.service.DemoService");
}
@Override
public boolean isAvailable() {
return false;
}
public Result invoke(Invocation invocation) throws RpcException {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION);
}
@Override
public void destroy() {
}
};
@Test
public void testConsumerSuccess() throws Exception {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE));
for (int i = 0; i < 100; i++) {
metricsFilter.invoke(serviceInvoker, invocation);
}
FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR));
FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
{
put(Constants.SERVICE, "org.apache.dubbo.monitor.service.DemoService");
put(Constants.METHOD, "sayName");
}
}, MetricLevel.NORMAL));
long timestamp = System.currentTimeMillis() / 5000 * 5000;
Assertions.assertEquals(100, dubboClient.getMethodCountPerCategory(0).get("success").get(timestamp));
timestamp = timestamp / 15000 * 15000;
Assertions.assertEquals(100, dubboMethod.getMethodCountPerCategory(0).get("success").get(timestamp));
}
@Test
public void testConsumerTimeout() {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("timeoutException", null, null);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(timeoutInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.CONSUMER_SIDE)
.addParameter(Constants.TIMEOUT_KEY, 300));
for (int i = 0; i < 10; i++) {
try {
metricsFilter.invoke(timeoutInvoker, invocation);
} catch (RpcException e) {
//ignore
}
}
FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER, MetricLevel.MAJOR));
FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_CONSUMER_METHOD, new HashMap<String, String>(4) {
{
put(Constants.SERVICE, "org.apache.dubbo.monitor.service.DemoService");
put(Constants.METHOD, "timeoutException");
}
}, MetricLevel.NORMAL));
long timestamp = System.currentTimeMillis() / 5000 * 5000;
Assertions.assertEquals(10, dubboClient.getMethodCountPerCategory(0).get("timeoutError").get(timestamp));
timestamp = timestamp / 15000 * 15000;
Assertions.assertEquals(10, dubboMethod.getMethodCountPerCategory(0).get("timeoutError").get(timestamp));
}
@Test
public void testProviderSuccess() throws Exception {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(Constants.SIDE_KEY, Constants.PROVIDER));
for (int i = 0; i < 100; i++) {
metricsFilter.invoke(serviceInvoker, invocation);
}
FastCompass dubboClient = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_PROVIDER, MetricLevel.MAJOR));
FastCompass dubboMethod = metricManager.getFastCompass(Constants.DUBBO_GROUP, new MetricName(Constants.DUBBO_PROVIDER_METHOD, new HashMap<String, String>(4) {
{
put(Constants.SERVICE, "org.apache.dubbo.monitor.service.DemoService");
put(Constants.METHOD, "sayName");
}
}, MetricLevel.NORMAL));
long timestamp = System.currentTimeMillis() / 5000 * 5000;
Assertions.assertEquals(100, dubboClient.getMethodCountPerCategory(0).get("success").get(timestamp));
timestamp = timestamp / 15000 * 15000;
Assertions.assertEquals(100, dubboMethod.getMethodCountPerCategory(0).get("success").get(timestamp));
}
}

View File

@ -128,7 +128,6 @@
<modules>
<module>dubbo-common</module>
<module>dubbo-metrics</module>
<module>dubbo-container</module>
<module>dubbo-remoting</module>
<module>dubbo-rpc</module>